JTAG標(biāo)準(zhǔn)的狀態(tài)機(jī)實(shí)現(xiàn)
JTAG作為一項(xiàng)國(guó)際標(biāo)準(zhǔn)測(cè)試協(xié)議(IEEE1149.1兼容),主要用于芯片內(nèi)部測(cè)試和調(diào)試。目前的主流芯片均支持JTAG協(xié)議,如DSP、FPGA、ARM、部分單片機(jī)等。標(biāo)準(zhǔn)的JTAG接口是20Pin,但JTAG實(shí)際使用的只有4根信號(hào)線,再配合電源、地。目前常見(jiàn)的各種接口形式(20pin、14pin、10pin):

JTAG標(biāo)準(zhǔn)介紹
JTAG的基本原理是在器件內(nèi)部定義一個(gè)TAP(Test Access Port)(測(cè)試訪問(wèn)口)通過(guò)專(zhuān)用的JTAG測(cè)試工具對(duì)內(nèi)部節(jié)點(diǎn)進(jìn)行測(cè)試。JTAG測(cè)試允許多個(gè)器件通過(guò)JTAG接口串聯(lián)在一起,形成一個(gè)JTAG鏈,能實(shí)現(xiàn)對(duì)各個(gè)器件分別測(cè)試。JTAG引腳的定義如下列表所示:
TCK:TCK在IEEE1149.1標(biāo)準(zhǔn)里是強(qiáng)制要求的。TCK為T(mén)AP的操作提供了一個(gè)獨(dú)立的、基本的時(shí)鐘信號(hào),TAP的所有操作都是通過(guò)這個(gè)時(shí)鐘信號(hào)來(lái)驅(qū)動(dòng)的;
TMS:TMS在IEEE1149.1標(biāo)準(zhǔn)里是強(qiáng)制要求的。TMS信號(hào)在TCK的上升沿有效,用來(lái)控制TAP狀態(tài)機(jī)的轉(zhuǎn)換。通過(guò)TMS信號(hào),可以控制TAP在不同的狀態(tài)間相互轉(zhuǎn)換;
TDI:TDI在IEEE1149.1標(biāo)準(zhǔn)里是強(qiáng)制要求的。TDI是數(shù)據(jù)輸入的接口,所有要輸入到特定寄存器的數(shù)據(jù)都是通過(guò)TDI接口一位一位串行輸入的(由TCK驅(qū)動(dòng));
TDO:TDO在IEEE1149.1標(biāo)準(zhǔn)里是強(qiáng)制要求的。TDO是數(shù)據(jù)輸出的接口,所有要從特定的寄存器中輸出的數(shù)據(jù)都是通過(guò)TDO接口一位一位串行輸出的(由TCK驅(qū)動(dòng));
TRST:可選項(xiàng),TRST可以用來(lái)對(duì)TAP控制器進(jìn)行復(fù)位(初始化)。因?yàn)橥ㄟ^(guò)TMS也可以對(duì)TAP控制器進(jìn)行復(fù)位(初始化),所以有四線JTAG與五線JTAG之分;
RTCK:可選項(xiàng),由目標(biāo)端反饋給仿真器的時(shí)鐘信號(hào),用來(lái)同步TCK信號(hào)的產(chǎn)生,不使用時(shí)直接接地;
nSRST:可選性與目標(biāo)板上的系統(tǒng)復(fù)位信號(hào)相連,可以直接對(duì)目標(biāo)系統(tǒng)復(fù)位。同時(shí)可以檢測(cè)目標(biāo)系統(tǒng)的復(fù)位情況,為了防止誤觸發(fā),應(yīng)在目標(biāo)端是哪個(gè)加上適當(dāng)?shù)纳侠?a target="_blank">電阻;
JTAG標(biāo)準(zhǔn)的信號(hào)時(shí)序如下圖所示:

通過(guò)JTAG連接,可以完成如下的功能:
對(duì)所有串接在一起的IC進(jìn)行引腳連接性測(cè)試,確認(rèn)PCB是否焊接正常;
對(duì)CPU、DSP、FPGA等進(jìn)行調(diào)試;
通過(guò)JTAG對(duì)FPGA進(jìn)行編程。
進(jìn)行引腳連接測(cè)試的JTAG用法如下圖所示,各個(gè)芯片引腳的連通狀態(tài)可以一次串接通信到PC的TDO引腳中。

按照菊花鏈方式串接調(diào)試的JTAG用法如下圖所示,多個(gè)串接在一起的CPU和FPGA都能夠一起進(jìn)行調(diào)試和測(cè)試。

上圖可以看出JTAG的調(diào)試原理:
所有調(diào)試芯片的IR寄存器串接在一起,然后進(jìn)行串行移位,最后,所有數(shù)據(jù)都進(jìn)入到JTAG口的TDO中;PC通過(guò)對(duì)TDO數(shù)據(jù)的串并轉(zhuǎn)換,獲得每個(gè)CPU、DPS或FPGA的內(nèi)部寄存器狀態(tài)。
PC將需要寫(xiě)入CPU、DSP或FAPG的數(shù)據(jù)通過(guò)并串轉(zhuǎn)換放置到TDI總線上,最后通過(guò)狀態(tài)移位到規(guī)定的CPU寄存器上,最后通過(guò)TMS制定生效時(shí)刻。
TCK就是TDI和TDO的移位時(shí)鐘,而TMS則是控制指令。
因此,JTAG通過(guò)一個(gè)標(biāo)準(zhǔn)狀態(tài)機(jī)就能夠?qū)PU/DSP/FPGA的內(nèi)部狀態(tài)查明,也能改變內(nèi)部寄存器內(nèi)容,這也是一種狀態(tài)控制原理。在1990年之前,JTAG的狀態(tài)機(jī)基本是由各個(gè)廠商自行定義的,但后來(lái)出現(xiàn)的IEEE1149.1標(biāo)準(zhǔn)對(duì)狀態(tài)轉(zhuǎn)移過(guò)程進(jìn)行了標(biāo)準(zhǔn)化。在某種意義上講,JTAG的狀態(tài)機(jī)實(shí)現(xiàn)過(guò)程是最佳的FSM學(xué)習(xí)對(duì)象。
JTAG狀態(tài)機(jī)設(shè)計(jì)
JTAG內(nèi)部的狀態(tài)轉(zhuǎn)換圖如下圖所示,其中的狀態(tài)值可以由讀者自行定義,但推薦采用獨(dú)熱編碼或者格雷碼進(jìn)行編碼。其中連續(xù)的5個(gè)TMS為1時(shí),就會(huì)回到Test-Logic-Reset狀態(tài)。

下面的代碼是實(shí)現(xiàn)JTAG功能的FSM部分,該代碼已經(jīng)應(yīng)用到多款ASIC芯片中,具有較高的研究?jī)r(jià)值。
//TAP FSM implementation
module tap_FSM #(parameter sync_mode = 1)(
input tck,
input trst_n,
input tms,
input tdi,
output byp_out,
output updateIR,reset_n,
output reg clockDR, updateDR, clockIR, tdo_en, shiftDR,shiftIR,
output selectIR, sync_capture_en, sync_update_dr, flag,
output [15:0] tap_state
);
//Inter signal declaration
reg [15:0] state;
reg [15:0] next_s;
reg scan_out_a, scan_out_s, updateIR_a;
localparam TEST_LOGIC_RESET = 16'h0001, RUN_TEST_IDLE = 16'h0002, SELECT_DR_SCAN = 16'H0004,
CAPTURE_DR= 16'h0008, SHIFT_DR = 16'h0010, EXIT1_DR = 16'h0020,PAUSE_DR = 16'h0040,
EXIT2_DR = 16'h0080, UPDATE_DR= 16'h0100, SELECT_IR_SCAN = 16'h0200,
CAPTURE_IR= 16'h0400, SHIFT_IR = 16'h0800, EXIT1_IR = 16'h1000,
PAUSE_IR = 16'h2000, EXIT2_IR = 16'h4000, UPDATE_IR= 16'h8000;
assign flag = state[10] || state[11];
wire updateIR_s = state == UPDATE_IR;
assign updateIR = sync_mode ? updateIR_s : updateIR_a;
assign tap_state= state;
always @(posedge tck or negedge trst_n)
if ( !trst_n )
state<=TEST_LOGIC_RESET;
else
state<=next_s;
always @(*)
case(state)
TEST_LOGIC_RESET: if(tms)
next_s=TEST_LOGIC_RESET;
else
next_s=RUN_TEST_IDLE;
RUN_TEST_IDLE: if( tms )
next_s=SELECT_DR_SCAN;
else
next_s=RUN_TEST_IDLE;
SELECT_DR_SCAN: if(tms)
next_s=SELECT_IR_SCAN;
else
next_s=CAPTURE_DR;
CAPTURE_DR: if(tms)
next_s=EXIT1_DR;
else
next_s=SHIFT_DR;
SHIFT_DR: if(tms)
next_s=EXIT1_DR;
else
next_s=SHIFT_DR;
EXIT1_DR: if(tms)
next_s=UPDATE_DR;
else
next_s=PAUSE_DR;
PAUSE_DR: if(tms)
next_s=EXIT2_DR;
else
next_s=PAUSE_DR;
EXIT2_DR: if(tms)
next_s=UPDATE_DR;
else
next_s=SHIFT_DR;
UPDATE_DR: if(tms)
next_s=SELECT_DR_SCAN;
else
next_s=RUN_TEST_IDLE;
SELECT_IR_SCAN:if(tms)
next_s=TEST_LOGIC_RESET;
else
next_s=CAPTURE_IR;
CAPTURE_IR: if(tms)
next_s=EXIT1_IR;
else
next_s=SHIFT_IR;
SHIFT_IR: if(tms)
next_s=EXIT1_IR;
else
next_s=SHIFT_IR;
EXIT1_IR: if(tms)
next_s=UPDATE_IR;
else
next_s=PAUSE_IR;
PAUSE_IR: if(tms)
next_s=EXIT2_IR;
else
next_s=PAUSE_IR;
EXIT2_IR: if(tms)
next_s=UPDATE_IR;
else
next_s=SHIFT_IR;
UPDATE_IR: if(tms)
next_s=SELECT_DR_SCAN;
else
next_s=RUN_TEST_IDLE;
endcase
//FSM outputs
reg rst_n;
//reg clockDR, updateDR, clockIR, tdo_en, rst_n, shiftDR, shiftIR;
//ClockDR/ClockIR - posedge occurs at the posedge of tck
//updateDR/updateIR - posedge occurs at the negedge of tck
always @( tck or state )begin
if ( !tck && ( state == CAPTURE_DR || state == SHIFT_DR ))
clockDR = 0;
else
clockDR = 1;
if ( !tck && ( state == UPDATE_DR ))
updateDR = 1;
else
updateDR = 0;
if ( !tck && ( state == CAPTURE_IR || state == SHIFT_IR ))
clockIR = 0;
else
clockIR = 1;
if ( !tck && ( state == UPDATE_IR ))
updateIR_a = 1;
else
updateIR_a = 0;
end
always @( negedge tck )
if ( state == SHIFT_IR || state == SHIFT_DR )
tdo_en <= 1;
else
tdo_en <= 0;
always @( negedge tck )
if ( state == TEST_LOGIC_RESET )
rst_n <= 0;
else
rst_n <= 1;
always @(negedge tck or negedge trst_n)
if ( !trst_n )
shiftDR <= 0;
else if ( state == SHIFT_DR )
shiftDR <= 1;
else
shiftDR <= 0;
always @(negedge tck or negedge trst_n)
if ( !trst_n )
shiftIR <= 0;
else if ( state == SHIFT_IR )
shiftIR <= 1;
else
shiftIR <= 0;
assign reset_n = rst_n & trst_n;
assign selectIR = state == SHIFT_IR;
assign sync_capture_en = ~(shiftDR | (state == CAPTURE_DR) | (state == SHIFT_DR));
assign sync_update_dr = state == UPDATE_DR;
always @( posedge clockDR )
scan_out_a <= shiftDR & tdi & ~(state == CAPTURE_DR);
wire nxt_st_3 = (state == SELECT_DR_SCAN) & ~tms;
wire nxt_st_4 = ((state == CAPTURE_DR) & ~tms) || ( state == SHIFT_DR & ~tms);
reg sel;
always @(posedge tck or negedge trst_n)
if(!trst_n )
sel <= 0;
else
sel <= ~(nxt_st_3 | nxt_st_4);
wire scan_out = sel ? scan_out_s : shiftDR & tdi;
always @(posedge tck )
scan_out_s <= scan_out & ~(state == CAPTURE_DR);
assign byp_out = sync_mode ? scan_out_s : scan_out_a;
endmodule
對(duì)于上述代碼,還有一種非常簡(jiǎn)潔的描述,同樣是三段式描述風(fēng)格,但最重要的組合電路部分可通過(guò)手工推導(dǎo),直接將always描述的組合電路化簡(jiǎn)為最小邏輯實(shí)現(xiàn)代碼。
module vjtag (
input clk, // Internal clock
input tdo_mux,// TDO before the negative edge flop
input bypass, // JTAG instruction=BYPASS
input tck, // clock input
input trst_n, // optional async reset active low
input tms, // Test Mode Select
input tdi, // Test Data In
output reg tdo, // Test Data Out
output reg tdo_enb,//Test Data Out tristate enable
output tdi_r1, // TDI flopped on TCK.
output tck_rise, // tck rate clock enable
output captureDR,// JTAG state=CAPTURE_DR
output shiftDR, // JTAG state=SHIFT_DR
output updateDR, // JTAG state=UPDATE_DR
output captureIR,// JTAG state=CAPTURE_IR
output shiftIR, // JTAG state=SHIFT_IR
output updateIR
);
reg tck_r1,tck_r2,tck_r3;
reg tdi_f_local; // local version
wire tdo_enb_nxt; // D input to TDO_ENB flop
wire tdo_nxt; // D input to TDO flop
wire itck_rise;
wire tck_fall;
reg [3:0] state; // current state
wire a,b,c,d,a_nxt,b_nxt,c_nxt,d_nxt;
assign a = state[0];
assign b = state[1];
assign c = state[2];
assign d = state[3];
assign a_nxt=(~tms & ~c & a) |(tms & ~b)|(tms & ~a)|(tms & d & c);
assign b_nxt=(~tms & b & ~a) |(~tms & ~c)|(~tms & ~d & b)|(~tms & ~d & ~a)|(tms & c & ~b)|(tms & d & c & a);
assign c_nxt=(c & ~b)|(c & a)|(tms & ~b);
assign d_nxt=(d & ~c)|(d & b)|(~tms & c & ~b)|(~d & c & ~b & ~a);
assign tdo_enb_nxt = state == 4'b0010 | state == 4'b1010 ? 1'b1 : 1'b0;
assign captureIR = state == 4'b1110 ? 1'b1 : 1'b0;
assign shiftIR = state == 4'b1010 ? 1'b1 : 1'b0;
assign updateIR = state == 4'b1101 ? 1'b1 : 1'b0;
assign captureDR = state == 4'b0110 ? 1'b1 : 1'b0;
assign shiftDR = state == 4'b0010 ? 1'b1 : 1'b0;
assign updateDR = state == 4'b0101 ? 1'b1 :1'b0;
assign tdo_nxt = bypass == 1'b1 & state == 4'b0010 ? tdi_f_local : tdo_mux;
assign tdi_r1 = tdi_f_local;
always @(posedge clk) begin : rtck_proc
tck_r3 <= tck_r2;
tck_r2 <= tck_r1;//synchronizers for edge detection
tck_r1 <= tck;
end
assign tck_rise = itck_rise;
assign itck_rise = tck_r2 & ~tck_r3;
assign tck_fall = ~tck_r2 & tck_r3;
always @(posedge clk)
if (trst_n == 1'b0)
state <= 4'b1111;
else if (itck_rise == 1'b1)begin
state <= {d_nxt, c_nxt, b_nxt, a_nxt};
end
always @(posedge clk)
if (trst_n == 1'b0)
tdi_f_local <= 1'b0;
else if (itck_rise == 1'b1 ) begin
tdi_f_local <= tdi;
end
always @(posedge clk)
if (trst_n == 1'b0)begin
tdo <= 1'b0;
tdo_enb <= 1'b0;
end
else if (tck_fall == 1'b1 ) begin
tdo <= tdo_nxt;
tdo_enb <= tdo_enb_nxt;
end
endmodule // module vjtag
JTAG接口除了標(biāo)準(zhǔn)的4信號(hào)引腳外,TI還定義了一種叫做SBW-JTAG的接口,僅用兩根引腳(SBWTCK、SBWTDIO)即可實(shí)現(xiàn)JTAG功能,通常用于引腳受限的芯片上。ARM的Cortex-M系列CPU均包含SW-JTAG定義標(biāo)準(zhǔn)。
原文鏈接:
https://blog.csdn.net/sinat_31206523/article/details/115495041
-
接口
+關(guān)注
關(guān)注
33文章
9439瀏覽量
156072 -
JTAG
+關(guān)注
關(guān)注
6文章
411瀏覽量
74579 -
引腳
+關(guān)注
關(guān)注
16文章
2078瀏覽量
55087 -
狀態(tài)機(jī)
+關(guān)注
關(guān)注
2文章
497瀏覽量
28827
原文標(biāo)題:JTAG標(biāo)準(zhǔn)的狀態(tài)機(jī)實(shí)現(xiàn)
文章出處:【微信號(hào):gh_9d70b445f494,微信公眾號(hào):FPGA設(shè)計(jì)論壇】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
Spring狀態(tài)機(jī)的實(shí)現(xiàn)原理和使用方法
玩轉(zhuǎn)Spring狀態(tài)機(jī)
狀態(tài)機(jī)舉例
利用狀態(tài)機(jī)的狀態(tài)機(jī)實(shí)現(xiàn)層次結(jié)構(gòu)化設(shè)計(jì)
基于FPGA實(shí)現(xiàn)狀態(tài)機(jī)的設(shè)計(jì)
使用函數(shù)指針的方法實(shí)現(xiàn)狀態(tài)機(jī)
FPGA:狀態(tài)機(jī)簡(jiǎn)述
什么是狀態(tài)機(jī)?狀態(tài)機(jī)5要素
狀態(tài)模式(狀態(tài)機(jī))
LABVIEW的狀態(tài)機(jī)實(shí)現(xiàn)資料合集
狀態(tài)機(jī)要實(shí)現(xiàn)哪些內(nèi)容
如何在FPGA中實(shí)現(xiàn)狀態(tài)機(jī)

JTAG標(biāo)準(zhǔn)的狀態(tài)機(jī)實(shí)現(xiàn)
評(píng)論