JTAG标准的状态机实现

JTAG作为一项国际标准测试协议(IEEE1149.1兼容),主要用于芯片内部测试和调试。目前的主流芯片均支持JTAG协议,如DSP、FPGA、ARM、部分单片机等。标准的JTAG接口是20Pin,但JTAG实际使用的只有4根信号线,再配合电源、地。目前常见的各种接口形式(20pin、14pin、10pin):

JTAG标准介绍

JTAG的基本原理是在器件内部定义一个TAP(Test Access Port)(测试访问口)通过专用的JTAG测试工具对内部节点进行测试。JTAG测试允许多个器件通过JTAG接口串联在一起,形成一个JTAG链,能实现对各个器件分别测试。JTAG引脚的定义如下列表所示:

  1. TCK:TCK在IEEE1149.1标准里是强制要求的。TCK为TAP的操作提供了一个独立的、基本的时钟信号,TAP的所有操作都是通过这个时钟信号来驱动的;

  2. TMS:TMS在IEEE1149.1标准里是强制要求的。TMS信号在TCK的上升沿有效,用来控制TAP状态机的转换。通过TMS信号,可以控制TAP在不同的状态间相互转换;

  3. TDI:TDI在IEEE1149.1标准里是强制要求的。TDI是数据输入的接口,所有要输入到特定寄存器的数据都是通过TDI接口一位一位串行输入的(由TCK驱动);

  4. TDO:TDO在IEEE1149.1标准里是强制要求的。TDO是数据输出的接口,所有要从特定的寄存器中输出的数据都是通过TDO接口一位一位串行输出的(由TCK驱动);

  5. TRST:可选项,TRST可以用来对TAP控制器进行复位(初始化)。因为通过TMS也可以对TAP控制器进行复位(初始化),所以有四线JTAG与五线JTAG之分;

  6. RTCK:可选项,由目标端反馈给仿真器的时钟信号,用来同步TCK信号的产生,不使用时直接接地;

  7. nSRST:可选性与目标板上的系统复位信号相连,可以直接对目标系统复位。同时可以检测目标系统的复位情况,为了防止误触发,应在目标端是哪个加上适当的上拉电阻;

JTAG标准的信号时序如下图所示:

通过JTAG连接,可以完成如下的功能:

  1. 对所有串接在一起的IC进行引脚连接性测试,确认PCB是否焊接正常;
  2. 对CPU、DSP、FPGA等进行调试;
  3. 通过JTAG对FPGA进行编程。

进行引脚连接测试的JTAG用法如下图所示,各个芯片引脚的连通状态可以一次串接通信到PC的TDO引脚中。

按照菊花链方式串接调试的JTAG用法如下图所示,多个串接在一起的CPU和FPGA都能够一起进行调试和测试。

上图可以看出JTAG的调试原理:

  1. 所有调试芯片的IR寄存器串接在一起,然后进行串行移位,最后,所有数据都进入到JTAG口的TDO中;PC通过对TDO数据的串并转换,获得每个CPU、DPS或FPGA的内部寄存器状态。
  2. PC将需要写入CPU、DSP或FAPG的数据通过并串转换放置到TDI总线上,最后通过状态移位到规定的CPU寄存器上,最后通过TMS制定生效时刻。
  3. TCK就是TDI和TDO的移位时钟,而TMS则是控制指令。

因此,JTAG通过一个标准状态机就能够将CPU/DSP/FPGA的内部状态查明,也能改变内部寄存器内容,这也是一种状态控制原理。在1990年之前,JTAG的状态机基本是由各个厂商自行定义的,但后来出现的IEEE1149.1标准对状态转移过程进行了标准化。在某种意义上讲,JTAG的状态机实现过程是最佳的FSM学习对象。

JTAG状态机设计

JTAG内部的状态转换图如下图所示,其中的状态值可以由读者自行定义,但推荐采用独热编码或者格雷码进行编码。其中连续的5个TMS为1时,就会回到Test-Logic-Reset状态。

下面的代码是实现JTAG功能的FSM部分,该代码已经应用到多款ASIC芯片中,具有较高的研究价值。

//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;elsestate<=next_s;always @(*)case(state)TEST_LOGIC_RESET: if(tms)next_s=TEST_LOGIC_RESET;elsenext_s=RUN_TEST_IDLE;RUN_TEST_IDLE: if( tms )next_s=SELECT_DR_SCAN;elsenext_s=RUN_TEST_IDLE;SELECT_DR_SCAN: if(tms)next_s=SELECT_IR_SCAN;elsenext_s=CAPTURE_DR;CAPTURE_DR: if(tms)next_s=EXIT1_DR;elsenext_s=SHIFT_DR;SHIFT_DR: if(tms)next_s=EXIT1_DR;elsenext_s=SHIFT_DR;EXIT1_DR: if(tms)next_s=UPDATE_DR;elsenext_s=PAUSE_DR;PAUSE_DR: if(tms)next_s=EXIT2_DR;elsenext_s=PAUSE_DR;EXIT2_DR: if(tms)next_s=UPDATE_DR;elsenext_s=SHIFT_DR;UPDATE_DR: if(tms)next_s=SELECT_DR_SCAN;elsenext_s=RUN_TEST_IDLE;SELECT_IR_SCAN:if(tms)next_s=TEST_LOGIC_RESET;elsenext_s=CAPTURE_IR;CAPTURE_IR: if(tms)next_s=EXIT1_IR;elsenext_s=SHIFT_IR;SHIFT_IR: if(tms)next_s=EXIT1_IR;elsenext_s=SHIFT_IR;EXIT1_IR: if(tms)next_s=UPDATE_IR;elsenext_s=PAUSE_IR;PAUSE_IR: if(tms)next_s=EXIT2_IR;elsenext_s=PAUSE_IR;EXIT2_IR: if(tms)next_s=UPDATE_IR;elsenext_s=SHIFT_IR;UPDATE_IR: if(tms)next_s=SELECT_DR_SCAN;elsenext_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 )beginif ( !tck && ( state == CAPTURE_DR || state == SHIFT_DR ))clockDR = 0;elseclockDR = 1;if ( !tck && ( state == UPDATE_DR ))updateDR = 1;elseupdateDR = 0;if ( !tck && ( state == CAPTURE_IR || state == SHIFT_IR ))clockIR = 0;elseclockIR = 1;if ( !tck && ( state == UPDATE_IR ))updateIR_a = 1;elseupdateIR_a = 0;endalways  @( negedge tck )if ( state == SHIFT_IR || state == SHIFT_DR )tdo_en <= 1;elsetdo_en <= 0;always  @( negedge tck ) if ( state == TEST_LOGIC_RESET )rst_n <= 0;elserst_n <= 1;always @(negedge tck or negedge trst_n)if ( !trst_n )shiftDR <= 0;else if ( state == SHIFT_DR )shiftDR <= 1;elseshiftDR <= 0;always @(negedge tck or negedge trst_n)if ( !trst_n )shiftIR <= 0;else if ( state == SHIFT_IR )shiftIR <= 1;elseshiftIR <= 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;elsesel <= ~(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

对于上述代码,还有一种非常简洁的描述,同样是三段式描述风格,但最重要的组合电路部分可通过手工推导,直接将always描述的组合电路化简为最小逻辑实现代码。

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 Inoutput reg tdo, // Test Data Out
output reg tdo_enb,//Test Data Out tristate enableoutput  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_proctck_r3 <= tck_r2; tck_r2 <= tck_r1;   //synchronizers for edge detectiontck_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)beginstate <= {d_nxt, c_nxt, b_nxt, a_nxt};   endalways @(posedge clk)  if (trst_n == 1'b0)tdi_f_local <= 1'b0;  else if (itck_rise == 1'b1 ) begintdi_f_local <= tdi;    endalways @(posedge clk)if (trst_n == 1'b0)begintdo <= 1'b0;   tdo_enb <= 1'b0;   endelse if (tck_fall == 1'b1 ) begintdo <= tdo_nxt;  tdo_enb <= tdo_enb_nxt; endendmodule // module vjtag

JTAG接口除了标准的4信号引脚外,TI还定义了一种叫做SBW-JTAG的接口,仅用两根引脚(SBWTCK、SBWTDIO)即可实现JTAG功能,通常用于引脚受限的芯片上。ARM的Cortex-M系列CPU均包含SW-JTAG定义标准。

有限状态机小结

学习有限状态机的关键是理解有限状态机的运行原理,知道通通过有限状态机能够将一个复杂的逻辑流程简化为有限的几个状态,所有的输出相应都是与状态对应的输出。有限状态机的编写风格当采用三段式编码,并尽量采用Moore型状态机

参考

本文主要内容来自《通信IC设计》,仅用于学习参考。

2021-04-07.

Verilog——JTAG标准的状态机实现相关推荐

  1. JTAG 标准IEEE STD 1149.1-2013学习笔记(三)Test data registers

    文章目录 一.TDR的实现 二.Bypass Register 三.Boundary-scan register 注:转载请注明出处 参考JTAG标准第九章测试数据寄存器(Test data regi ...

  2. JTAG 标准IEEE STD 1149.1-2013学习笔记(二)Instruction register

    文章目录 一.D型扫描触发器 二.IR 电路结构 三.指令寄存器的操作 注:转载请注明出处 参考JTAG标准第七章指令寄存器(Instruction register) 记录下学习过程,个人水平有限, ...

  3. verilog一二三段式状态机的标准区别和示例

    状态机标准 状态机描述时关键是要描述清楚前面提到的几个状态机的要素,即如何进行状态转移:每个状态的输出是什么:状态转移是否和输入条件相关等. 具体描述时方法各种各样,有的设计者习惯将整个状态机写到1 ...

  4. JTAG的TAP状态机介绍

    来自 嵌入式系统Linux内核开发实战指南   http://book.chinaunix.net/showart.php?id=3258  JTAG简介 JTAG接口的基本工作原理是:在芯片内部定义 ...

  5. verilog 自动售货机状态机实现_Verilog HDL自动售货机系统设计与仿真实验报告

    前言 随着电子技术和计算机技术的飞速发展,电子线路的设计工作也日益显得重要.经过人工设计.制作实验板.调试再修改的多次循环才定型的传统产品设计方法必然被计算机辅助设计所取代,因为这种费时费力又费资源的 ...

  6. verilog 自动售货机状态机实现_基于Verilog语言的简单自动售货机-数电课设报告(最终版)最新版...

    <基于Verilog语言的简单自动售货机-数电课设报告.docx>由会员分享,可免费在线阅读全文,更多与<基于Verilog语言的简单自动售货机-数电课设报告(最终版)>相关文 ...

  7. 基于verilog的三段式状态机

    三段式状态机的优势:三段式描述方法与一段式和两段式状态机描述相比,虽然代码结构复杂了一些,但是换来的优势是使FSM(Finite State Machine)做到了同步寄存器输出,消除了组合逻辑输出的 ...

  8. 【Verilog基础】为什么状态机中多使用独热码,而不是二进制码或者格雷码?

    为什么例子中我们使用的是独热码而非二进制码或格雷码呢? 那就要从每种编码的特性上说起了,首先独热码因为每个状态只有 1bit 是不同的,例如在执行到(state== TWO)这条语句时,综合器会识别出 ...

  9. Unity 抗锯齿Antialiasing

    直接放到相机上用即可,可以有效降低锯齿(相对于其他插件而言),另外这个脚本跟NatCorder录制视频冲突,具体原因后续再详查. 最近突然发现PC端用Antialiasing修改窗口分辨率时会黑屏,后 ...

最新文章

  1. python pyqt5 窗体自适应_Pyqt5自适应布局实例
  2. SCP传输文件和断点续传
  3. CTreeCtrl展开树形所有节点
  4. foreach 循环详解
  5. unity5.4.3p2里面的AssetBundle打包流程
  6. ReactOS 对象的结构,创建,使用,删除
  7. 如何获取kindle资源
  8. matlab画直方图并拟合泊松分布,将泊松分布拟合为数据(直方图+直线)
  9. 显微镜下的大明——第一个故事
  10. np.array的axis进行横向纵向的求和运算
  11. 分布式软总线模块总结
  12. 淘宝网店应该怎么样去做好宝贝SEO优化?
  13. Lightroom Classic 9.0安装教程
  14. 【网络流】【二分图最大匹配】Buaacoding1043 难题·Beihang Couple Pairing Comunity 2017
  15. 思维导图怎么画?思维导图快速绘制教程
  16. 在阿里云5年后被裁员,历经100场面试,我终于拿到了4个offer
  17. 优化函数SGD/AdaGrad/AdaDelta/Adam/Nadam
  18. 用c#每日更换“必应背景图片”为“桌面壁纸”
  19. 文件查找失败:‘@escook/request-miniprogram‘ at main.js:10
  20. C++木马破坏MBR病毒

热门文章

  1. Win7/10 64位电脑上如何使用TASM指令
  2. html中改变字体的大小
  3. java cookie实现自动登录
  4. SVN解决冲突命令resolve和resolved
  5. linux golang安装
  6. Wear OS手表应用开发教程之-手腕手势-上下甩动手表事件
  7. JAVA获取当前时间并作比较
  8. 数据结构(一)——线性链表的原理以及应用
  9. Python代码练习
  10. 企业信用等级认证的意义有哪些?