研究 Rocket Chip 的 BSCAN 调试原理
前言最近 @jsteward 在研究如何通过 JTAG 对 FPGA 里的 Rocket Chip 进行调试。之前 @sequencer已经做了一些实践,我们在重复他的工作,同时也研究了一下这是怎么工作的。
原理
我们从 @sequencer 得到了一份可用的 Scala 代码 和 OpenOCD配置,并且了解到:
可以通过 openocd 找到并调试 Rocket Chip
openocd 是通过 JTAG 向 FPGA 的 TAP 的 IR 写入 USER4,然后往 DR 写入特定格式的数据,然后控制 Rocket Chip 的 JTAG。
这里涉及到一个“封装”的过程,在一个仅可以控制 DR 的 JTAG 中控制另一个 JTAG。首先可以找到 OpenOCD 端的操作代码:
tunneled_ir.num_bits = 3;
tunneled_ir.out_value = bscan_zero;
tunneled_ir.in_value = NULL;
tunneled_ir.num_bits = bscan_tunnel_ir_width;
tunneled_ir.out_value = ir_dtmcontrol;
tunneled_ir.in_value = NULL;
tunneled_ir.num_bits = 7;
tunneled_ir.out_value = tunneled_ir_width;
tunneled_ir.in_value = NULL;
tunneled_ir.num_bits = 1;
tunneled_ir.out_value = bscan_zero;
tunneled_ir.in_value = NULL;
如果画成图,大概是这个样子(IR):
3 bits IR Width bits 7 bits 1 bit TDI Data Register TDO
0 Payload Tunneled IR Width 0 -> Rocket Chip TAP ->
DR:
3 bits DR Width bits 7 bits 1 bit TDI Data Register TDO
0 Payload Tunneled DR Width 1 -> Rocket Chip TAP ->
这里 TDI 和 TDO 是直接接到 Rocket Chip 的 JTAG 中的,所以我们期望,当 Rocket Chip TAP 在 Shift-IR/Shift-DR 阶段的时候,刚好通过的是 Payload 部分。而控制 TAP 状态机,需要控制 TMS,这个则是通过一段 HDL 来完成的:
always@(*) begin
if (counter_neg == 8'h04) begin
jtag_tms = TDI_REG;
end else if (counter_neg == 8'h05) begin
jtag_tms = 1'b1;
end else if ((counter_neg == (8'h08 + shiftreg_cnt)) || (counter_neg == (8'h08 + shiftreg_cnt - 8'h01))) begin
jtag_tms = 1'b1;
end else begin
jtag_tms = 1'b0;
end
end
这里 TDI_REG 取的是第一个 bit 的反(也就是上面 IR 对应 0 ,DR 对应 1 的那一位),shiftreg_cnf 则是之后 7 个 bit,对应上面的 Tunneled IR/DR Width。那么,在选择 IR 时 TMS 的序列为:
4 cycles 1 cycle 1 cycle 2 cycles shiftreg_cnt-1 cycles 2 cycles rest cycles
0 1 1 0 0 1 0
Run-Test/Idle Select-DR-Scan Select-IR-Scan Capture-IR, Shift-IR Shift-IR Exit1-IR, Update-IR Run-Test/Idle
类似地,如果是选择 DR:
4 cycles 1 cycle 1 cycle 2 cycles shiftreg_cnt-1 cycles 2 cycles rest cycles
0 0 1 0 0 1 0
Run-Test/Idle Run-Test/Idle Select-DR-Scan Capture-DR, Shift-DR Shift-DR Exit1-DR, Update-DR Run-Test/Idle
这样,刚好在 Shift-IR/DR 状态下,Payload 会被写入 IR/DR,从而完成了期望的操作。通过规定一个特定格式的 Data Register,可以实现嵌套的 TAP 的 IR 和 DR 的操作。
参考
1)JTAG Standard
2)sequencer/rocket-playground
3)SiFive’s JTAG Tunnel: https://github.com/sifive/fpga-shells/blob/c099bd9b4f916bc0ba88030939a9614d0b0daf2d/src/main/scala/ip/xilinx/Xilinx.scala#L13
4)https://github.com/watz0n/arty_xjtag
5)https://github.com/riscv/riscv-openocd/blob/7cb8843794a258380b7c37509e5c693977675b2a/src/target/riscv/riscv.c#L361
6)UG740:7 Series FPGAs Configuration
本帖来自:杰哥的{运维,编程,调板子}小笔记
页:
[1]