Skip to content

JTAG and Debug

NANHU implements RISC-V External Debug Support Version 0.13.2.

NANHU uses components including Debug Module, Debug Module Interface, Debug Transport Module and JTAG Interface.

NANHU Debug Module supports Program Buffer (16 bytes) and System Bus Access. Abstract Commands are implemented using Program Buffer. It is connected to L3 crossbar using TileLink to support System Bus Access. It has two parts: DMInner and DMOuter. DMInner is driven by core clock while DMOuter is driven by JTAG clock. DMOuter issues debug interrupts.


NANHU CSR has a one bit register indicating whether it is in Debug Mode.

Debug mode can be entered when:

  • Debug Module issues a debug interrupt.

  • An ebreak is executed in mode X and ebreakX is executed (X is M, S, or U).

  • The hart has returned from Debug Mode, and step bit in dcsr is set. The hart enters debug mode after exactly one instruction has committed.

  • Trigger hit with action bit set to 1 in the corresponding mcontrol CSR.

NANHU implements the following debug mode registers: Debug control and status register (dcsr), Debug PC (dpc), Debug Scratch (dscratch and dscratch1).

Debug control and status register

NANHU implements optional dcsr bits ebreaks, ebreaku, mprven and step. See RISC-V External Debug Support Version 0.13.2 for more detail.

Debug PC

Debug PC stores the program counter of the exact instruction that trapped into debug mode. The pc is recovered when a dret is executed. Debug Module can modify this CSR to manipulate the path of program execution.

Debug Scratch

There are 2 debug scratch registers (dscratch and dscratch1) in NANHU. These registers are used as scratch registers by the Debug Module.


Trigger select register

Tselect selects one of the 10 triggers in NANHU. All NANHU's triggers are listed below.

No. Type Timing bit Chain bit Select bit Match bit
0 execute/store/load Wired to 0 Y Y* 0, 2 or 3
1 execute/store/load Y Y*
2 execute/store/load Y Y*
3 execute/store/load Y Y*
4 execute/store/load Y Y*
5 execute/store/load Y Y*
6 execute/store/load Y Y*
7 execute/store/load Y Y*
8 execute/store/load Y Y*
9 execute/store/load Wired to 0 Y*

*: If type is store or load, select bit will be WARL as 0.

Trigger data status register

All triggers in NANHU are match control triggers. Each has a mcontrol (tdata1), data (tdata2) and info (tinfo) register.


NANHU supports using ebreak instruction as software breakpoint. To use this in privileged mode X, ebreakX bit in dcsr should be set. Hardware breakpoints are implemented using triggers.

Debug memory map

Debug Module uses address space (0x3802_0000, 0x3802_0fff).

Debug Module Interface

DMI has a bus width of 7 bits.

JTAG Interface

Nanhu’s JTAG interface supports asynchronous reset TRSTn.

Connecting to Debug Module

First, riscv-openocd needs to be compiled. See Github README on how to compile riscv-openocd.

Run simv with options: ./difftest/simv [+workload=WorkloadName.bin] +no-diff +enable-jtag

Then in another terminal, run: ./openocd -f XS.cfg

The content of an example openocd config file XS.cfg is shown as below:

adapter driver remote_bitbang
remote_bitbang host localhost
remote_bitbang port 23334

set _CHIPNAME riscv
jtag newtap $_CHIPNAME cpu -irlen 5

target create $_TARGETNAME riscv-chain-position $_TARGETNAME

reset halt
echo "reset and halt at the reset vector"

To connect to GDB, remove the “exit” command shown above. In another terminal, launch riscv64-unknown-elf-gdb and run command: target extended-remote:3333