0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

JTAG标准的状态机实现

FPGA设计论坛 ? 来源:CSDN技术社区 ? 2025-08-21 15:12 ? 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

JTAG标准的状态机实现

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

c5ac1c30-7e58-11f0-a18e-92fbcf53809c.png

JTAG标准介绍

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

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

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

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

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

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

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

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

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

c5c6b996-7e58-11f0-a18e-92fbcf53809c.png

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

对所有串接在一起的IC进行引脚连接性测试,确认PCB是否焊接正常;

CPU、DSP、FPGA等进行调试;

通过JTAG对FPGA进行编程

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

c5deb244-7e58-11f0-a18e-92fbcf53809c.png

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

c5e88b7a-7e58-11f0-a18e-92fbcf53809c.png

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

所有调试芯片的IR寄存器串接在一起,然后进行串行移位,最后,所有数据都进入到JTAG口的TDO中;PC通过对TDO数据的串并转换,获得每个CPU、DPS或FPGA的内部寄存器状态。

PC将需要写入CPU、DSP或FAPG的数据通过并串转换放置到TDI总线上,最后通过状态移位到规定的CPU寄存器上,最后通过TMS制定生效时刻。

TCK就是TDI和TDO的移位时钟,而TMS则是控制指令。

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

JTAG状态机设计

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

c5f6c384-7e58-11f0-a18e-92fbcf53809c.png

下面的代码是实现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;

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

对于上述代码,还有一种非常简洁的描述,同样是三段式描述风格,但最重要的组合电路部分可通过手工推导,直接将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 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接口除了标准的4信号引脚外,TI还定义了一种叫做SBW-JTAG的接口,仅用两根引脚(SBWTCK、SBWTDIO)即可实现JTAG功能,通常用于引脚受限的芯片上。ARM的Cortex-M系列CPU均包含SW-JTAG定义标准。

原文链接:

https://blog.csdn.net/sinat_31206523/article/details/115495041

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 接口
    +关注

    关注

    33

    文章

    9122

    浏览量

    154410
  • JTAG
    +关注

    关注

    6

    文章

    405

    浏览量

    73659
  • 引脚
    +关注

    关注

    16

    文章

    1857

    浏览量

    53572
  • 状态机
    +关注

    关注

    2

    文章

    495

    浏览量

    28405

原文标题:JTAG标准的状态机实现

文章出处:【微信号:gh_9d70b445f494,微信公众号:FPGA设计论坛】欢迎添加关注!文章转载请注明出处。

收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    Spring状态机实现原理和使用方法

    说起 Spring 状态机,大家很容易联想到这个状态机和设计模式中状态模式的区别是啥呢?没错,Spring 状态机就是状态模式的一种
    的头像 发表于 12-26 09:39 ?2787次阅读
    Spring<b class='flag-5'>状态机</b>的<b class='flag-5'>实现</b>原理和使用方法

    玩转Spring状态机

    说起Spring状态机,大家很容易联想到这个状态机和设计模式中状态模式的区别是啥呢?没错,Spring状态机就是状态模式的一种
    的头像 发表于 06-25 14:21 ?1375次阅读
    玩转Spring<b class='flag-5'>状态机</b>

    状态机举例

    状态机举例 你可以指定状态寄存器和状态机状态。以下是一个有四种状态的普通状态机。 // Th
    发表于 03-28 15:18 ?1118次阅读

    状态机原理及用法

    状态机原理及用法状态机原理及用法状态机原理及用法
    发表于 03-15 15:25 ?0次下载

    利用状态机状态机实现层次结构化设计

    练习九.利用状态机的嵌套实现层次结构化设计目的:1.运用主状态机与子状态机产生层次化的逻辑设计;
    发表于 02-11 05:52 ?3536次阅读
    利用<b class='flag-5'>状态机</b>的<b class='flag-5'>状态机</b><b class='flag-5'>实现</b>层次结构化设计

    利用74LS161实现复杂状态机

    本文主要介绍了是如何利用74LS161实现复杂状态机的。时序逻辑电路的数学模型是有限状态机。有限状态机它把复杂的控制逻辑分解成有限个稳定状态
    发表于 01-18 09:00 ?1.1w次阅读
    利用74LS161<b class='flag-5'>实现</b>复杂<b class='flag-5'>状态机</b>

    状态机概述 如何理解状态机

    本篇文章包括状态机的基本概述以及通过简单的实例理解状态机
    的头像 发表于 01-02 18:03 ?1.1w次阅读
    <b class='flag-5'>状态机</b>概述  如何理解<b class='flag-5'>状态机</b>

    基于FPGA实现状态机的设计

    状态机有三种描述方式:一段式状态机、两段式状态机、三段式状态机。下面就用一个小例子来看看三种方式是如何实现的。
    的头像 发表于 08-29 06:09 ?3195次阅读
    基于FPGA<b class='flag-5'>实现状态机</b>的设计

    使用函数指针的方法实现状态机

    之前写过一篇状态机的实用文章,很多朋友说有几个地方有点难度不易理解,今天给大家换种简单写法,使用函数指针的方法实现状态机状态机简介 有限状态机FSM是有限个
    的头像 发表于 10-19 09:36 ?2732次阅读
    使用函数指针的方法<b class='flag-5'>实现状态机</b>

    FPGA:状态机简述

    本文目录 前言 状态机简介 状态机分类 Mealy 型状态机 Moore 型状态机 状态机描述 一段式
    的头像 发表于 11-05 17:58 ?8195次阅读
    FPGA:<b class='flag-5'>状态机</b>简述

    状态模式(状态机)

    share,作者:亚索老哥)),原来状态机还可以这么简单地玩~~亚索老哥提出的状态机六步法(1)、定义状态接口(2)、定义系统当前状态指针(3)、定义具体
    发表于 12-16 16:53 ?9次下载
    <b class='flag-5'>状态</b>模式(<b class='flag-5'>状态机</b>)

    LABVIEW的状态机实现资料合集

    LABVIEW的状态机实现资料合集
    发表于 01-04 11:18 ?51次下载

    状态机实现哪些内容

    状态机模式是一种行为模式,通过多态实现不同状态的调转行为的确是一种很好的方法,只可惜在嵌入式环境下,有时只能写纯C代码,并且还需要考虑代码的重入和多任务请求跳转等情形,因此实现起来着实
    的头像 发表于 06-22 14:26 ?1052次阅读
    <b class='flag-5'>状态机</b>要<b class='flag-5'>实现</b>哪些内容

    如何在FPGA中实现状态机

    状态机往往是FPGA 开发的主力。选择合适的架构和实现方法将确保您获得一款最佳解决方案。 FPGA 常常用于执行基于序列和控制的行动, 比如实现一个简单的通信协议。对于设计人员来说,满足这些行动
    的头像 发表于 07-18 16:05 ?1611次阅读
    如何在FPGA中<b class='flag-5'>实现状态机</b>

    什么是状态机状态机的种类与实现

    状态机,又称有限状态机(Finite State Machine,FSM)或米利状态机(Mealy Machine),是一种描述系统状态变化的模型。在芯片设计中,
    的头像 发表于 10-19 10:27 ?1.2w次阅读