JTAG and Tcl – twin rabbitholes!

2022-03-29

I’ve been experimenting with the QMTech Kintex7 board, which provides a huge FPGA for a less huge amount of money. The one thing that prevents my existing projects from running on it without deep changes is the lack of SDRAM, but since I’ve been wanting to get more familiar with the Xilinx ecosystem for a while, this was a good opportunity to dive in.

Firstly, it should be noted that the Kintex 7 XC7K325T part on this board is *not* supported by the free version of Vivado – which means if you want an out-of-the-box experience you need to use ISE. If you’re willing to ride the bleeding edge, then Project X-Ray already has initial support for this chip – so the future of this board with the Open Source toolchain should be very interesting! (See https://github.com/kintex-chatter for a collection of works-in-progress.)

For now, though, I’m going to turn my attention to ISE. The last version released was 14.7, and the WebPack Edition also doesn’t support the XC7K325T – however, Embedded Edition does, and at the time of writing, it’s also free.

It requires some finessing to make it work on a modern Linux distro – something which can also be said about the older versions of Quartus required for Cyclone II and III support – I’ve been collecting together some information on this subject here: https://github.com/robinsonb5/FPGAToolchainQuirks

The last time I had any real exposure to Xilinx devices I was using the venerable “Platform Cable USB”, and surprise no. 1 was the discovery that this device isn’t well supported outside of Xilinx’s own software: OpenOCD doesn’t support it, OpenFPGALoader doesn’t support it, URJTAG has support which it describes as “Slow, experimental – don’t use.”

There’s an alternative firmware which can be uploaded into the Platform Cable to make it behave like a USB Blaster – but I haven’t yet had any success with this, using either a Platform Cable DLC9, or a Platform Cable II DLC10.

XC3SProg *does* support the Platform Cable USB, however.

For the EightThirtyTwo CPU I have a rudimentary Debug interface which works by transmitting 32-bit words over an Intel Virtual JTAG interface, and bridging that to TCP/IP by way of a Tcl script. I wanted to be able to do the same with a Xilinx chip. Tcl isn’t a necessary part of the equation – simply bridging directly from JTAG to TCP/IP would be sufficient to use the 832 debugger – however, Tcl does allow some interesting things to be done with Tk (for instance, I have a demo which allows the colour of an FPGA-controlled VGA screen to be set using sliders on a GUI running on the PC.) So Tcl support is filed under “Nice to have”.

Surprise no. 2 was the discovery that Tcl extensions are *ridiculously* easy to write!

I started with a copy of the source to the xc3sprog executable, to create a libtcljtag.so shared library, which can be loaded using Tcl’s load command. I set it to build with -fPIC (required to avoid relocation issues when building theshared library) and created a simple class to wrap the JTAG manipulation functions, exposing them as Tcl commands.

So far the following commands are defined (all under the jtag:: namespace):

  • get_cables – returns a Tcl list of cables supported by xc3sprog.
  • open_cable cablename – opens the specified cable (for example: “jtag::open_cable xpc” will open the Xilinx Platform Cable). Returns the number of devices found on the JTAG chain if successful.
  • close_cable – closes and releases the currently-open cable, if any.
  • select_device – addresses shift_ir and shift_dr commands to the specified device in the chain.
  • get_device_id device – return a 32-bit integer device ID of the specified device in the chain.
  • get_device_description device – looks up the device ID of the specified device in the devlist.txt file and returns the name of the device, if found.
  • detect_chain – re-scans the JTAG chain
  • shift_ir value – shifts the specified value in the Instruction Register of the currently selected device in the chain, passing through the Update_IR JTAG state when done.
  • shift_dr value length – Passes through the Capture_DR JTAG state, then shifts the specified value and number of bits into the Data Register of the currently selected device in the chain, passing through the Update_DR state when done. Returns the captured value.

Using the TclJTAG extension to talk to a design on an FPGA might look something like this:

# Load the extension
load "/path/to/libtcljtag.so"

# Open the cable
jtag::open_cable xpc

# Fetch a description of the first device in the chain...
set desc [jtag::get_device_description 0]

# Is it a Xilinx Series 7 FPGA?
if { [string match "XC7*" $desc] } {

	# Select the USER3 register
	jtag::shift_ir 0x22

	# Shift a 32-bit value into the USER3 register, and fetch its captured contents.
	set d [jtag::shift_dr 0x12345678 32]

	# Print the fetched value
	puts [format 0x%x d]
}

# And finally close the cable
jtag::close_cable

This works from the systemwide tclsh environment, and just for fun I tried doing the same from a “quartus_stp -s” session. I had to remove the libstdc++ library from the Quartus installation, to make it use the systemwide one instead – and yes, it works!

I’m sure I shall find other uses for this in future, but for now it means that that EightThirtyTwo debug interface can be used on Xilinx chips (Tested on Spartan6, Artix7 and Kintex7 – defined but not tested for Spartan 3, too.) as well as Altera/Intel chips.

It’s entirely possible I’m the only person on the planet who actually wants this – but just in case anyone else does, the TclJTAG extension can be found here: https://github.com/robinsonb5/xc3sprog !

Have fun!

Leave a Reply

Your email address will not be published. Required fields are marked *