<meter id="pryje"><nav id="pryje"><delect id="pryje"></delect></nav></meter>
          <label id="pryje"></label>

          新聞中心

          FPGA:JTAG接口

          作者: 時(shí)間:2024-01-08 來源:EEPW編譯 收藏

          大多數(shù)都支持JTAG。

          本文引用地址:http://www.ex-cimer.com/article/202401/454547.htm

          JTAG 1 - 什么是JTAG?

          JTAG 是 1149 年代開發(fā)的 IEEE 標(biāo)準(zhǔn) (1.1980),用于解決電子板制造問題。 如今,它更多地用作編程、調(diào)試和探測端口。

          但首先,讓我們看看JTAG的原始用途,邊界測試。

          邊界測試

          這是一個(gè)簡單的電子板(也稱為“PCB”,意為“印刷電路板”),帶有兩個(gè) IC(“集成電路”)、一個(gè) CPU 和一個(gè) 。典型的電路板可能有更多的IC。

          IC可以有很多引腳。 因此,當(dāng)然,IC通過許多連接(PCB走線)連接在一起。

          我們?cè)谶@里只展示四個(gè)。 但是你可以很容易地在PCB上有幾千個(gè)。

          現(xiàn)在,如果你構(gòu)建了一千個(gè)板子,每個(gè)板子都有幾千個(gè)連接,你不可避免地會(huì)有一些壞板子。 您如何測試所有這些電路板?您必須確保所有這些連接都正常。 您不能只手動(dòng)測試所有這些連接。于是JTAG誕生了。

          JTAG可以控制(或劫持)所有IC的引腳。 從圖上看,也許JTAG將使所有CPU引腳輸出,所有引腳輸入。 然后,通過從CPU引腳發(fā)送一些數(shù)據(jù),并從FPGA引腳讀取值,JTAG可以確保電路板連接正常。

          現(xiàn)在JTAG實(shí)際上由四個(gè)邏輯信號(hào)組成,分別命名為TDI、TDO、TMS和TCK。 從PC的角度來看,這是三個(gè)輸出和一個(gè)輸入。

          這四個(gè)信號(hào)需要以特定的方式連接。 首先,TMS和TCK并聯(lián)到所有JTAG IC。

          然后TDI和TDO連接起來形成鏈。 在JTAG術(shù)語中,您經(jīng)常聽到“JTAG鏈”一詞,這就是它的由來。

          如您所見,每個(gè)JTAG兼容IC都有四個(gè)用于JTAG的引腳(三個(gè)輸入和一個(gè)輸出)。 第五個(gè)名為TRST的引腳是可選的(JTAG復(fù)位)。 JTAG引腳通常是專用的(不共享用于其他目的)。

          所有大型IC都使用JTAG進(jìn)行邊界測試 - 邊界測試是創(chuàng)建JTAG的最初原因。 如今,JTAG的使用已經(jīng)擴(kuò)展到允許配置FPGA之類的事情,然后在FPGA內(nèi)核中使用JTAG進(jìn)行調(diào)試。

          JTAG 2 - JTAG的工作原理

          現(xiàn)在我們知道了如何將JTAG連接到不同的IC,讓我們?cè)敿?xì)了解JTAG是如何工作的,以及如何從PC控制它。

          從PC控制JTAG

          您可以使用“JTAG電纜”從PC控制JTAG總線。 JTAG電纜只是控制來自PC的四個(gè)JTAG信號(hào)的一種方式。 JTAG電纜可以連接到PC的并行(打印機(jī))端口,USB端口或以太網(wǎng)端口... 最簡單的是并行端口(不幸的是,僅在較舊的 PC 上可用)。 USB和以太網(wǎng)JTAG電纜也很好。 它們?cè)诹魇絺鬏敶罅繑?shù)據(jù)時(shí)速度更快,但控制起來更復(fù)雜,并且對(duì)于少量數(shù)據(jù)的開銷更大(=更慢)。

          并行端口

          并行端口可以看作是PC的74位輸出,PC的125位輸入。 JTAG只需要一個(gè)<>位輸出和一個(gè)<>位輸入,所以這沒有問題。 例如,請(qǐng)看一下 Xilinx 并聯(lián) III 電纜的原理圖。 左邊是PC的并行信號(hào),右邊是JTAG連接器,中間是幾個(gè)<>HC<>電子緩沖器。

          從軟件的角度來看,并行端口是理想的選擇,因?yàn)樗浅R子诳刂啤?br/>例如,以下C代碼顯示了如何切換Altera ByteBlaster JTAG電纜的TCK信號(hào)。

          #define lpt_addr 0x378#define TCK 0x01void toggle_TCK()
          {
          outport(lpt_addr, 0);
          outport(lpt_addr, TCK);
          outport(lpt_addr, 0);
          }

          Windows 2000/XP/Vista 的一個(gè)小問題是“outport”IO 指令受到限制,但 GiveIO 和 UserPort 是開放 IO 空間的免費(fèi)通用驅(qū)動(dòng)程序。

          JTAG TAP控制器

          我們知道PC連接到JTAG總線,如下圖所示:

          因此,我們有 4 個(gè)信號(hào)(TDI、TDO、TMS、TCK)需要處理。

          SCl的

          TCK是JTAG時(shí)鐘信號(hào)。 其他JTAG信號(hào)(TDI、TDO、TMS)與TCK同步。 因此,TCK 必須切換才能發(fā)生任何事情(通常事情發(fā)生在 TCK 的上升邊緣)。

          TMS技術(shù)

          每個(gè)JTAG IC內(nèi)部都有一個(gè)JTAG TAP控制器。 在上圖中,這意味著 CPU 中有一個(gè) TAP 控制器,F(xiàn)PGA 中有一個(gè) TAP 控制器。

          TAP控制器主要是一個(gè)具有16個(gè)狀態(tài)的狀態(tài)機(jī)。 TMS 是控制 TAP 控制器的信號(hào)。 由于TMS并聯(lián)到所有JTAG IC,因此所有TAP控制器一起移動(dòng)(到相同的狀態(tài))。

          下面是 TAP 控制器狀態(tài)機(jī):

          每個(gè)箭頭附近的小數(shù)字(“0”或“1”)是用于更改狀態(tài)的 TMS 的值。 例如,如果TAP控制器處于“選擇DR-Scan”狀態(tài),TMS為“0”,并且TCK切換,則狀態(tài)將更改為“Capture-DR”。

          為了使JTAG正常工作,JTAG鏈的抽頭控制器必須始終處于相同的狀態(tài)。 通電后,它們可能不同步,但有一個(gè)技巧。 查看狀態(tài)機(jī),請(qǐng)注意,無論您處于什么狀態(tài),如果 TMS 在五個(gè)時(shí)鐘中保持在“1”,則 TAP 控制器將返回到“Test-Logic-Reset”狀態(tài)。 它用于同步 TAP 控制器。

          因此,假設(shè)我們想在通電后轉(zhuǎn)到“Shift-IR”:

          	// first sync everybody to the test-logic-reset state
          for(i=0; i<5; i++) JTAG_clock(TMS);

          // now that everybody is in a known and identical state, we can move together to another state
          // let's go to Shift-IR
          JTAG_clock(0);
          JTAG_clock(TMS);
          JTAG_clock(TMS);
          JTAG_clock(0);
          JTAG_clock(0);
          TDI 和 TDO

          現(xiàn)在我們知道了如何更改狀態(tài),我們可以使用兩個(gè)最重要的JTAG狀態(tài),即“Shift-DR”和“Shift-IR”。

          Shift-DR 和 Shift-IR 與 TDI 和 TDO 生產(chǎn)線結(jié)合使用。
          讓我們從 Shift-IR 開始。

          每個(gè) IC TAP 控制器都有一個(gè)寄存器,稱為 IR,即“指令寄存器”。 你在這個(gè)寄存器中寫入一個(gè)值,該值與你想用JTAG做什么相對(duì)應(yīng)(每個(gè)IC都有一個(gè)可能的指令列表)。

          此外,每個(gè) IC IR 寄存器都有特定的長度。 例如,假設(shè) CPU 的 IR 為 5 位長,F(xiàn)PGA 的 IR 為 10 位長。 IR 寄存器形成一條鏈,通過 TDI 和 TDO 引腳加載。

          從 PC 的角度來看,上面的 IR 鏈長 15 位。
          要加載 IR 值,PC 必須確保 TAP 控制器處于 Shift-IR 狀態(tài),并通過 TDI 發(fā)送 15 位。 一旦移位,前 10 位實(shí)際上最終會(huì)進(jìn)入 FPGA IR,最后 5 位最終會(huì)進(jìn)入 CPU IR。 如果 PC 發(fā)送的位超過 15 位,它將開始在 TDO 上接收它發(fā)送的內(nèi)容(延遲 15 個(gè)時(shí)鐘)。

          例如,讓我們將 00100 發(fā)送到 CPU 的 IR 中,然后0000000010到 FPGA 的 IR 中。

          	// Because the bits are shifted through in a chain, we must start sending the data for the device that is at the end of the chain
          // so we send the 10 FPGA IR bits first
          JTAG_clock(0);
          JTAG_clock(1);
          JTAG_clock(0);
          JTAG_clock(0);
          JTAG_clock(0);
          JTAG_clock(0);
          JTAG_clock(0);
          JTAG_clock(0);
          JTAG_clock(0);
          JTAG_clock(0);

          // then send the 5 CPU IR bits
          JTAG_clock(0);
          JTAG_clock(0);
          JTAG_clock(1);
          JTAG_clock(0);
          JTAG_clock(0 | TMS); // last bit needs to have TMS active (to exit shift-IR)

          在我們的示例中,CPU 的 IR 長度為 5 位(即可以保存 0 到 31 之間的值)。 這意味著它可以支持多達(dá) 32 個(gè) JTAG 指令。 在實(shí)踐中,CPU 可能使用 5 到 10 條指令,其余的 IR 值未使用。

          FPGA 也是如此,它有一個(gè) 10 位長的 IR,可以容納 1024 條指令,其中大部分未使用。

          JTAG有一些強(qiáng)制性指令(這些指令的作用將在后面說明):

          • 旁路

          • EXTEST公司

          • 樣品/預(yù)加載

          • IDCODE(不是強(qiáng)制性的,但經(jīng)常實(shí)現(xiàn))

          要獲取特定 IC 支持的可能 IR 值列表,請(qǐng)查看 IC 的數(shù)據(jù)表(或 BSDL 文件 - 稍后會(huì)詳細(xì)介紹)。

          DR 寄存器

          每個(gè) TAP 控制器只有一個(gè) IR 寄存器,但有多個(gè) DR 寄存器。 DR 寄存器類似于 IR 寄存器(它們的移位方式與 IR 寄存器相同,但使用 Shift-DR 狀態(tài)而不是 Shift-IR)。

          每個(gè) IR 值選擇不同的 DR 寄存器。 因此,在我們的示例中,CPU 最多可以有 32 個(gè) DR 寄存器(如果實(shí)現(xiàn)了所有 IR 指令)。

          JTAG 3 - 查詢JTAG鏈

          計(jì)算JTAG鏈中的器件數(shù)量

          一個(gè)重要的 IR 值是“all-one”值。 對(duì)于 CPU 來說,這將是 11111,對(duì)于 FPGA,這是1111111111。 此值對(duì)應(yīng)于稱為 BYPASS 的強(qiáng)制性 IR 指令。 在旁路模式下,TAP控制器DR寄存器始終是一個(gè)觸發(fā)器,除了在輸出到TDO之前將TDI輸入延遲一個(gè)時(shí)鐘周期外,什么也做不了。

          使用這種旁路模式的一種有趣方法是計(jì)算JTAG鏈中存在的IC數(shù)量。
          如果每個(gè)JTAG IC將TDI-TDO鏈延遲一個(gè)時(shí)鐘,我們可以發(fā)送一些數(shù)據(jù)并檢查延遲了多長時(shí)間。 這為我們提供了鏈中IC的數(shù)量。

          下面是一個(gè)示例:

            // go to reset state
           for(i=0; i<5; i++) JTAG_clock(TMS);

           // go to Shift-IR
           JTAG_clock(0);
           JTAG_clock(TMS);
           JTAG_clock(TMS);
           JTAG_clock(0);
           JTAG_clock(0);

           // Send plenty of ones into the IR registers
           // That makes sure all devices are in BYPASS!
           for(i=0; i<999; i++) JTAG_clock(1);
           JTAG_clock(1 | TMS);  // last bit needs to have TMS active, to exit shift-IR

           // we are in Exit1-IR, go to Shift-DR
           JTAG_clock(TMS);
           JTAG_clock(TMS);
           JTAG_clock(0);
           JTAG_clock(0);

           // Send plenty of zeros into the DR registers to flush them
           for(i=0; i<1000; i++) JTAG_clock(0);

           // now send ones until we receive one back
           for(i=0; i<1000; i++) if(JTAG_clock(1)) break;

           nbDevices = i;
           printf("There are %d device(s) in the JTAG chainn", nbDevices);
          獲取JTAG鏈中器件的ID

          大多數(shù)JTAG IC都支持IDCODE指令。 在 IDCODE 模式下,DR 寄存器加載了一個(gè) 32 位值,該值表示設(shè)備 ID。

          與 BYPASS 指令不同,IDCODE 的 IR 值不是標(biāo)準(zhǔn)的。 幸運(yùn)的是,每次TAP控制器進(jìn)入Test-Logic-Reset時(shí),它都會(huì)進(jìn)入IDCODE模式(并將IDCODE加載到DR中)。

          下面是一個(gè)示例:

            // go to reset state (that loads IDCODE into IR of all the devices)
           for(i=0; i<5; i++) JTAG_clock(TMS);

           // go to Shift-DR
           JTAG_clock(0);
           JTAG_clock(TMS);
           JTAG_clock(0);
           JTAG_clock(0);

           // and read the IDCODES
           for(i=0; i < nbDevices; i++)
           {
             printf("IDCODE for device %d is %08Xn", i+1, JTAG_read(32));
           }

          JTAG 4 - 運(yùn)行邊界掃描

          現(xiàn)在,讓我們讓 TAP 控制器進(jìn)入邊界掃描模式,其中 DR 鏈通過每個(gè) IO 塊,可以讀取或劫持每個(gè)引腳!

          即使設(shè)備正在運(yùn)行,也可以使用邊界掃描。 例如,在FPGA上使用JTAG,您可以在FPGA運(yùn)行時(shí)判斷每個(gè)引腳的狀態(tài)。

          樣本

          讓我們嘗試讀取引腳的值。 為此,我們使用一個(gè)名為SAMPLE的JTAG指令。 每個(gè)IC指令代碼列表都不同。 您必須查看 IC 數(shù)據(jù)表或 IC BSDL 文件才能獲得代碼。

          BSDL文件實(shí)際上是描述IC邊界鏈的VHDL文件。
          以下是 Altera BSDL 文件(TQFP 1 引腳封裝的 Cyclone EP3C100)的有趣部分。

          attribute INSTRUCTION_LENGTH of EP1C3T100 : entity is 10;
          attribute INSTRUCTION_OPCODE of EP1C3T100 : entity is
           "BYPASS            (1111111111), "&
           "EXTEST            (0000000000), "&
           "SAMPLE            (0000000101), "&
           "IDCODE            (0000000110), "&
           "USERCODE          (0000000111), "&
           "CLAMP             (0000001010), "&
           "HIGHZ             (0000001011), "&
           "CONFIG_IO            (0000001101)";
           attribute INSTRUCTION_CAPTURE of EP1C3T100 : entity is "0101010101";
           attribute IDCODE_REGISTER of EP1C3T100 : entity is
           "0000"&               --4-bit Version
           "0010000010000001"&   --16-bit Part Number (hex 2081)
           "00001101110"&        --11-bit Manufacturer's Identity
           "1";                  --Mandatory LSB
           attribute BOUNDARY_LENGTH of EP1C3T100 : entity is 339;

          以下是我們從該設(shè)備的 BSDL 中學(xué)到的內(nèi)容:

          • IR 寄存器的長度(10 位長)。

          • 可能的 IR 指令列表及其 10 位代碼。SAMPLE 的代碼為 0000000101b = 0x005。

          • 部件的 IDCODE(制造商代碼為 00001101110b = 0x6E,即 Altera。Xilinx 本來是 00001001001b = 0x49)。

          • 邊界掃描鏈的長度(339 位長)。

          邊界掃描的長度為 339 位。 這并不意味著有 339 個(gè)引腳。
          每個(gè)引腳在IC芯片上使用IO焊盤。 一些 IO 焊盤使用鏈中的一位、兩位或三位(取決于引腳是僅輸入、三態(tài)輸出,還是兩者兼而有之)。 有關(guān)詳細(xì)信息,請(qǐng)參閱本頁底部的鏈接。 此外,有些寄存器對(duì)應(yīng)于可能沒有邊界的IO焊盤(它們存在于IC芯片上,但無法從外部訪問)。 這就解釋了為什么 100 引腳器件可以具有 339 位邊界掃描鏈。

          回到BSDL文件,我們也得到這個(gè):

          attribute BOUNDARY_REGISTER of EP1C3T100 : entity is
           --BSC group 0 for I/O pin 100
           "0   (BC_1, IO100, input, X)," &
           "1   (BC_1, *, control, 1)," &
           "2   (BC_1, IO100, output3, X, 1, 1, Z)," &

           --BSC group 1 for I/O pin 99
           "3   (BC_1, IO99, input, X)," &
           "4   (BC_1, *, control, 1)," &
           "5   (BC_1, IO99, output3, X, 4, 1, Z)," &

           ...
           ...
           ...

           --BSC group 112 for I/O pin 1
           "336 (BC_1, IO1, input, X)," &
           "337 (BC_1, *, control, 1)," &
           "338 (BC_1, IO1, output3, X, 337, 1, Z)" ;

          這列出了鏈的所有 339 位,以及它們的作用。 例如,位 3 是告訴我們引腳 99 的值是多少的位。

          讓我們讀取邊界掃描寄存器,并打印引腳 99 的值:

            // go to reset state
           for(i=0; i<5; i++) JTAG_clock(TMS);

           // go to Shift-IR
           JTAG_clock(0);
           JTAG_clock(TMS);
           JTAG_clock(TMS);
           JTAG_clock(0);
           JTAG_clock(0);

           // Assuming that IR is 10 bits long,
           // that there is only one device in the chain,
           // and that SAMPLE code = 0000000101b
           JTAG_clock(1);
           JTAG_clock(0);
           JTAG_clock(1);
           JTAG_clock(0);
           JTAG_clock(0);
           JTAG_clock(0);
           JTAG_clock(0);
           JTAG_clock(0);
           JTAG_clock(0);
           JTAG_clock(0 or TMS);  // last bit needs to have TMS active, to exit shift-IR

           // we are in Exit1-IR, go to Shift-DR
           JTAG_clock(TMS);
           JTAG_clock(TMS);
           JTAG_clock(0);
           JTAG_clock(0);

           // read the boundary-scan chain bits in an array called BSB
           JTAG_read(BSB, 339);
           printf("Status of pin 99 = %dn, BSB[3]);


          很簡單,對(duì)吧?

          使用JTAG做更多事情
          • JTAG可以劫持引腳。 JTAG指令是EXTEST(“外部測試”)。

          • JTAG可以執(zhí)行FPGA配置。例如,請(qǐng)參閱此文件。

          • JTAG可用作調(diào)試端口,例如Altera的SignalTap和Xilinx的ChipScope。

          輪到你來實(shí)驗(yàn)了!




          關(guān)鍵詞: FPGA JTAG接口

          評(píng)論


          相關(guān)推薦

          技術(shù)專區(qū)

          關(guān)閉
          看屁屁www成人影院,亚洲人妻成人图片,亚洲精品成人午夜在线,日韩在线 欧美成人 (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })();