新闻中心

EEPW首页 > 嵌入式系统 > 设计应用 > FPGA:JTAG接口

FPGA:JTAG接口

作者:时间:2024-01-08来源:EEPW编译收藏

大多数都支持JTAG。

本文引用地址:http://www.eepw.com.cn/article/202401/454547.htm

JTAG 1 - 什么是JTAG?

JTAG 是 1149 年代开发的 IEEE 标准 (1.1980),用于解决电子板制造问题。 如今,它更多地用作编程、调试和探测端口。

但首先,让我们看看JTAG的原始用途,边界测试。

边界测试

这是一个简单的电子板(也称为“PCB”,意为“印刷电路板”),带有两个 IC(“集成电路”)、一个 CPU 和一个 。典型的电路板可能有更多的IC。

IC可以有很多引脚。 因此,当然,IC通过许多连接(PCB走线)连接在一起。

我们在这里只展示四个。 但是你可以很容易地在PCB上有几千个。

现在,如果你构建了一千个板子,每个板子都有几千个连接,你不可避免地会有一些坏板子。 您如何测试所有这些电路板?您必须确保所有这些连接都正常。 您不能只手动测试所有这些连接。于是JTAG诞生了。

JTAG可以控制(或劫持)所有IC的引脚。 从图上看,也许JTAG将使所有CPU引脚输出,所有引脚输入。 然后,通过从CPU引脚发送一些数据,并从FPGA引脚读取值,JTAG可以确保电路板连接正常。

现在JTAG实际上由四个逻辑信号组成,分别命名为TDI、TDO、TMS和TCK。 从PC的角度来看,这是三个输出和一个输入。

这四个信号需要以特定的方式连接。 首先,TMS和TCK并联到所有JTAG IC。

然后TDI和TDO连接起来形成链。 在JTAG术语中,您经常听到“JTAG链”一词,这就是它的由来。

如您所见,每个JTAG兼容IC都有四个用于JTAG的引脚(三个输入和一个输出)。 第五个名为TRST的引脚是可选的(JTAG复位)。 JTAG引脚通常是专用的(不共享用于其他目的)。

所有大型IC都使用JTAG进行边界测试 - 边界测试是创建JTAG的最初原因。 如今,JTAG的使用已经扩展到允许配置FPGA之类的事情,然后在FPGA内核中使用JTAG进行调试。

JTAG 2 - JTAG的工作原理

现在我们知道了如何将JTAG连接到不同的IC,让我们详细了解JTAG是如何工作的,以及如何从PC控制它。

从PC控制JTAG

您可以使用“JTAG电缆”从PC控制JTAG总线。 JTAG电缆只是控制来自PC的四个JTAG信号的一种方式。 JTAG电缆可以连接到PC的并行(打印机)端口,USB端口或以太网端口... 最简单的是并行端口(不幸的是,仅在较旧的 PC 上可用)。 USB和以太网JTAG电缆也很好。 它们在流式传输大量数据时速度更快,但控制起来更复杂,并且对于少量数据的开销更大(=更慢)。

并行端口

并行端口可以看作是PC的74位输出,PC的125位输入。 JTAG只需要一个<>位输出和一个<>位输入,所以这没有问题。 例如,请看一下 Xilinx 并联 III 电缆的原理图。 左边是PC的并行信号,右边是JTAG连接器,中间是几个<>HC<>电子缓冲器。

从软件的角度来看,并行端口是理想的选择,因为它非常易于控制。
例如,以下C代码显示了如何切换Altera ByteBlaster JTAG电缆的TCK信号。

#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 的一个小问题是“outport”IO 指令受到限制,但 GiveIO 和 UserPort 是开放 IO 空间的免费通用驱动程序。

JTAG TAP控制器

我们知道PC连接到JTAG总线,如下图所示:

因此,我们有 4 个信号(TDI、TDO、TMS、TCK)需要处理。

SCl的

TCK是JTAG时钟信号。 其他JTAG信号(TDI、TDO、TMS)与TCK同步。 因此,TCK 必须切换才能发生任何事情(通常事情发生在 TCK 的上升边缘)。

TMS技术

每个JTAG IC内部都有一个JTAG TAP控制器。 在上图中,这意味着 CPU 中有一个 TAP 控制器,FPGA 中有一个 TAP 控制器。

TAP控制器主要是一个具有16个状态的状态机。 TMS 是控制 TAP 控制器的信号。 由于TMS并联到所有JTAG IC,因此所有TAP控制器一起移动(到相同的状态)。

下面是 TAP 控制器状态机:

每个箭头附近的小数字(“0”或“1”)是用于更改状态的 TMS 的值。 例如,如果TAP控制器处于“选择DR-Scan”状态,TMS为“0”,并且TCK切换,则状态将更改为“Capture-DR”。

为了使JTAG正常工作,JTAG链的抽头控制器必须始终处于相同的状态。 通电后,它们可能不同步,但有一个技巧。 查看状态机,请注意,无论您处于什么状态,如果 TMS 在五个时钟中保持在“1”,则 TAP 控制器将返回到“Test-Logic-Reset”状态。 它用于同步 TAP 控制器。

因此,假设我们想在通电后转到“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

现在我们知道了如何更改状态,我们可以使用两个最重要的JTAG状态,即“Shift-DR”和“Shift-IR”。

Shift-DR 和 Shift-IR 与 TDI 和 TDO 生产线结合使用。
让我们从 Shift-IR 开始。

每个 IC TAP 控制器都有一个寄存器,称为 IR,即“指令寄存器”。 你在这个寄存器中写入一个值,该值与你想用JTAG做什么相对应(每个IC都有一个可能的指令列表)。

此外,每个 IC IR 寄存器都有特定的长度。 例如,假设 CPU 的 IR 为 5 位长,FPGA 的 IR 为 10 位长。 IR 寄存器形成一条链,通过 TDI 和 TDO 引脚加载。

从 PC 的角度来看,上面的 IR 链长 15 位。
要加载 IR 值,PC 必须确保 TAP 控制器处于 Shift-IR 状态,并通过 TDI 发送 15 位。 一旦移位,前 10 位实际上最终会进入 FPGA IR,最后 5 位最终会进入 CPU IR。 如果 PC 发送的位超过 15 位,它将开始在 TDO 上接收它发送的内容(延迟 15 个时钟)。

例如,让我们将 00100 发送到 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 之间的值)。 这意味着它可以支持多达 32 个 JTAG 指令。 在实践中,CPU 可能使用 5 到 10 条指令,其余的 IR 值未使用。

FPGA 也是如此,它有一个 10 位长的 IR,可以容纳 1024 条指令,其中大部分未使用。

JTAG有一些强制性指令(这些指令的作用将在后面说明):

  • 旁路

  • EXTEST公司

  • 样品/预加载

  • IDCODE(不是强制性的,但经常实现)

要获取特定 IC 支持的可能 IR 值列表,请查看 IC 的数据表(或 BSDL 文件 - 稍后会详细介绍)。

DR 寄存器

每个 TAP 控制器只有一个 IR 寄存器,但有多个 DR 寄存器。 DR 寄存器类似于 IR 寄存器(它们的移位方式与 IR 寄存器相同,但使用 Shift-DR 状态而不是 Shift-IR)。

每个 IR 值选择不同的 DR 寄存器。 因此,在我们的示例中,CPU 最多可以有 32 个 DR 寄存器(如果实现了所有 IR 指令)。

JTAG 3 - 查询JTAG链

计算JTAG链中的器件数量

一个重要的 IR 值是“all-one”值。 对于 CPU 来说,这将是 11111,对于 FPGA,这是1111111111。 此值对应于称为 BYPASS 的强制性 IR 指令。 在旁路模式下,TAP控制器DR寄存器始终是一个触发器,除了在输出到TDO之前将TDI输入延迟一个时钟周期外,什么也做不了。

使用这种旁路模式的一种有趣方法是计算JTAG链中存在的IC数量。
如果每个JTAG IC将TDI-TDO链延迟一个时钟,我们可以发送一些数据并检查延迟了多长时间。 这为我们提供了链中IC的数量。

下面是一个示例:

  // 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

大多数JTAG IC都支持IDCODE指令。 在 IDCODE 模式下,DR 寄存器加载了一个 32 位值,该值表示设备 ID。

与 BYPASS 指令不同,IDCODE 的 IR 值不是标准的。 幸运的是,每次TAP控制器进入Test-Logic-Reset时,它都会进入IDCODE模式(并将IDCODE加载到DR中)。

下面是一个示例:

  // 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 - 运行边界扫描

现在,让我们让 TAP 控制器进入边界扫描模式,其中 DR 链通过每个 IO 块,可以读取或劫持每个引脚!

即使设备正在运行,也可以使用边界扫描。 例如,在FPGA上使用JTAG,您可以在FPGA运行时判断每个引脚的状态。

样本

让我们尝试读取引脚的值。 为此,我们使用一个名为SAMPLE的JTAG指令。 每个IC指令代码列表都不同。 您必须查看 IC 数据表或 IC BSDL 文件才能获得代码。

BSDL文件实际上是描述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;

以下是我们从该设备的 BSDL 中学到的内容:

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

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

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

  • 边界扫描链的长度(339 位长)。

边界扫描的长度为 339 位。 这并不意味着有 339 个引脚。
每个引脚在IC芯片上使用IO焊盘。 一些 IO 焊盘使用链中的一位、两位或三位(取决于引脚是仅输入、三态输出,还是两者兼而有之)。 有关详细信息,请参阅本页底部的链接。 此外,有些寄存器对应于可能没有边界的IO焊盘(它们存在于IC芯片上,但无法从外部访问)。 这就解释了为什么 100 引脚器件可以具有 339 位边界扫描链。

回到BSDL文件,我们也得到这个:

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]);


很简单,对吧?

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

  • JTAG可以执行FPGA配置。例如,请参阅此文件。

  • JTAG可用作调试端口,例如Altera的SignalTap和Xilinx的ChipScope。

轮到你来实验了!




关键词: FPGA JTAG接口

评论


相关推荐

技术专区

关闭