Wednesday, December 28, 2011

FPGA JTAG Debug

Hey, I'm still alive. Even if I'm not writing every day (hmm, once per year?). Anyway...
With my resurrected interest in programmable logic, I wanted to find a better way to debug my FPGA designs. I know that design verification with the simulator helps, but there's no better test than the real device working on your bench (and sometimes it's even preferable, compared to working with Xilinx's ISE WebPack). The major event that pushed me into the direction of searching for my own solution was the fact that Xilinx provide ChipScope Pro in the WebPack distribution, but during the design compilation ChipScope Pro just moaned about my license (it's a free WebPack license) and the design build failed. I won't lie that I had some thoughts about just finding a key-generator for the ISE and to start working with the full version, but... This won't help me in the long-run, and neither will help to the general public. A second and still important factor is that I'm quite curious about what FPGA companies are actually offering these days as free downloadable design software - is it a big piece of crap or it's really usable thing than can actually attract people to this engineering field? My current observation is that things are really improving, there's still a lot of space for improvement. Can you guess why? These companies are selling HARDWARE, not software, so why are they artificially limiting the popularity of their devices by limiting the access to their design tools? For example Microchip maybe is not the best engineering company in the world, maybe their products are not the best products, but the software has always been available for free (except C-language toolchain). So, to summarize - gents, if you sell hardware don't skimp software.
Back to the problem - I wanted to debug my design without usign ChipScope Pro. I found out that ChipScope uses 2 commands for the JTAG TAP (Test Access Port) controller to access 2 user-defined (or design-defined) registers - USER1 & USER2. The JTAG TAP is available in your design as a macro called BSCAN_SPARTAN3 (actually this is only valid for Spartan-3 and Spartan-3E devices, which I'm interested in). Here is how this macro is declared (OK, at least this is my estimation):

module BSCAN_SPARTAN3 (
    output reg TDI,
    output reg RESET,
    output reg SHIFT,
    output reg CAPTURE,
    output reg UPDATE,
    output reg DRCK1,
    output reg SEL1,
    input wire TDO1,
    output reg DRCK2,
    output reg SEL2,
    input wire TDO2
);

What's not obvious is how this module is used actually.
TODO - add Verilog code to show BSCAN module usage.
TODO - add scope captured waveforms to show how this design works.

Next thing I wanted to do was to connect the FPGA to the PC with JTAG interface. Generally I wanted to use OpenOCD, because it's (relatively) easy to play with this JTAG tool. I check around how to compile it for Win32 but it turned out that OpenOCD authors rely mostly on Cygwin - a compromise I'm not ready to make (did I mentioned that I hate Cygwin?). My only choice was to build it for Linux - my test box is a small 600MHz VIA EPIA miniITX, running Debian Lenny (kernel 2.6.26-2-486, gcc-4.3.2). Please note that in order to have useful OpenOCD tool, you have to choose what JTAG interfaces have to be supported. I have currently Amontec USB JTAGkey-Tiny (it's partially broken - nTRST buffer is blown but I'm still too lazy to fix it), and also I have Digilent Parallel Port JTAG cable (I think it's compatible with Xilinx JTAG Cable 3). In order to add support for JTAGkey-Tiny, I had to download and compile the latest libftdi-0.19 library (the Debian-provided package was just too old). Next I had to download and compile OpenOCD-0.5.0 JTAG tool:

$ ./configure --enable-parport --enable-ft2232_libftdi && make

Please pay attention to configure's output - there's a possibility that the script can't find the header/library for libftdi (you'll have to fix this). Now you can build OpenOCD. After it's compiled, you can move the binary in your favourite working directory (it's available in src directory). You can also remove the unneeded fat from the ELF application, if you want:

$ strip --strip-unneded openocd

This reduced the size of the binary from 4.3MB to 1.2MB.
Now's the time to connect your JTAGkey to the Linux box. It's useful to observe the connection process just to be sure everything goes as expected (you'll have to perform this command as root or any user, member of the adm group):

# tail -f /var/log/syslog

And here's the output:

Dec 28 16:22:50 epia kernel: [ 6802.200057] usb 1-1: new full speed USB device using uhci_hcd and address 2
Dec 28 16:22:50 epia kernel: [ 6802.404726] usb 1-1: configuration #1 chosen from 1 choice
Dec 28 16:22:50 epia kernel: [ 6802.419605] usb 1-1: New USB device found, idVendor=0403, idProduct=cff8
Dec 28 16:22:50 epia kernel: [ 6802.419627] usb 1-1: New USB device strings: Mfr=1, Product=2, SerialNumber=3
Dec 28 16:22:50 epia kernel: [ 6802.419643] usb 1-1: Product: Amontec JTAGkey
Dec 28 16:22:50 epia kernel: [ 6802.419655] usb 1-1: Manufacturer: Amontec
Dec 28 16:22:50 epia kernel: [ 6802.419668] usb 1-1: SerialNumber: XXXXXXXX

In order to use this USB JTAG interface, you'll have to instruct OpenOCD what's the interface, what are the attached devices, etc... This is done via a OpenOCD configuration file. Here's my initial file for playing with Digilent Spartan-3 Starter Kit board:

# spartan3.cfg
# OpenOCD commands

telnet_port 4444
gdb_port 3333

interface ft2232
ft2232_device_desc "Amontec JTAGkey Tiny"
ft2232_layout jtagkey
ft2232_vid_pid 0x0403 0xcff8
adapter_khz 6000

# JTAG TAPs
# TODO

Please note that initially I didn't have any clue about how to define the devices in the boundary scan chain. I just remembered that the Digilent ExPort & Xilinx Impact programs are detecting 2 devices in the scan chain - Spartan-3 1000 and XCF04S platform flash. For some unknown reason the device order in the vendor-provided software is the opposite to the way OpenOCD shows these devices. And just for the curios - here's what I saw initially on the console, while trying to understand how to configure my scan chain:

$ ./openocd -f spartan3.cfg
Open On-Chip Debugger 0.5.0 (2011-12-28-00:51)
Licensed under GNU GPL v2
For bug reports, read
http://openocd.berlios.de/doc/doxygen/bugs.html
Info : only one transport option; autoselect 'jtag'6000 kHz
Info : clock speed 6000 kHz
Warn : There are no enabled taps.  AUTO PROBING MIGHT NOT WORK!!
Warn : AUTO auto0.tap - use "jtag newtap auto0 tap -expected-id 0x05046093 ..."
Warn : AUTO auto1.tap - use "jtag newtap auto1 tap -expected-id 0x11428093 ..."
Warn : AUTO auto0.tap - use "... -irlen 8"
Warn : AUTO auto1.tap - use "... -irlen 2"
Error: IR capture error at bit 10, saw 0x03FFFFFFFFFFFFFFFFFFFFFFFFFFF501 not 0x...3
Warn : Bypassing JTAG setup events due to errors
Warn : gdb services need one or more targets defined

It's generally hard to automatically recognize "who's who" on the boundary scan chain, thanks to standard deviations and mis-interpretations. So here we're seeing that at least OpenOCD sees "something" on the scan chain. If we add "newtap" lines to define the length of JTAG TAP instruction registers for these 2 devices:

# JTAG TAPs
jtag newtap unknown0 tap -irlen 8jtag newtap unknown1 tap -irlen 6

...things are starting to get a better shape:

$ ./openocd -f spartan3.cfg
...
Info : JTAG tap: unknown0.tap tap/device found: 0x05046093 (mfg: 0x049, part: 0x5046, ver: 0x0)
Warn : JTAG tap: unknown0.tap       UNEXPECTED: 0x05046093 (mfg: 0x049, part: 0x5046, ver: 0x0)
Info : JTAG tap: unknown1.tap tap/device found: 0x11428093 (mfg: 0x049, part: 0x1428, ver: 0x1)
Warn : JTAG tap: unknown1.tap       UNEXPECTED: 0x11428093 (mfg: 0x049, part: 0x1428, ver: 0x1)
Error: Trying to use configured scan chain anyway...

You can ask me how I found out the IR length? Please check here. On this site you can also get the DEVICE_ID codes for these chips, so we can complete our scan chain configuration:

# JTAG TAPs
jtag newtap xcf04s tap -expected-id 0x05046093 -irlen 8jtag newtap xc3s1000 tap -expected-id 0x11428093 -irlen 6

Now OpenOCD is much happier (so am I):

$ ./openocd -f spartan3.cfg
...
Info : JTAG tap: xcf04s.tap tap/device found: 0x05046093 (mfg: 0x049, part: 0x5046, ver: 0x0)
Info : JTAG tap: xc3s1000.tap tap/device found: 0x11428093 (mfg: 0x049, part: 0x1428, ver: 0x1)

One unpleasant point is that is that in order to use BSCAN component, the device must be already configured. This complicates the things a lot, because I'll have to program and debug the FPGA design via the same interface (which CAN be complicated, because I'm still searching for an acceptable triplet of JTAG interface/application/OS that works for all my needs), or I'll have to live-swap JTAG interfaces after programming (ugly but possible, just keep the ground wire first connected/last disconnected).
I tried to program SVF file with Linux/OpenOCD/JTAGkey-tiny with this telnet command (it uses a .svf file in the same working directory as OpenOCD binary)

$ telnet localhost 4444
Trying 127.0.0.1...
Connected to localhost.Escape character is '^]'.
Open On-Chip Debugger
> scan_chain
TapName             Enabled  IdCode     Expected   IrLen IrCap IrMask
------------------- -------- ---------- ---------- ----- ----- ------
0 xcf04s.tap             Y     0x05046093 0x05046093     8 0x01  0x03
1 xc3s1000.tap           Y     0x11428093 0x11428093     6 0x01  0x03
> svf -tap xc3s1000.tap tralala.svf
svf processing file: "tralala.svf"...

...but at some poing OpenOCD quits with this error:
Error: ftdi_write_data: usb bulk write failed
Error: couldn't write MPSSE commands to FT2232

I didn't wanted to debug libftdi, so I used my other JTAG device, Digilent parport cable. Please note you'll have to change your OpenOCD config file for the new interface, and you'll have to ensure that your /dev/parport0 device is available (mine was not, but "modprobe ppdev" solved the problem, and also I have to add my user to the "lp" group for proper permissions). Here's the new OpenOCD config :

# spartan3.cfg
# OpenOCD commands

telnet_port 4444
gdb_port 3333

interface parport
parport_port 0
parport_cable dlc5
adapter_khz 100

# JTAG TAPs
jtag newtap xcf04s tap -expected-id 0x05046093 -irlen 8
jtag newtap xc3s1000 tap -expected-id 0x11428093 -irlen 6

This time the communication was slower but it didn't failed. Nevertheless I was still unable to program the board (it failed with some error at the end of programming). I supposed that there's a problem with OpenOCD SVF parser, but my next attempt with XSVF file was even more unsuccessful. I'll post an update if there's any progress with the programming.

Note: Here are some links to other people's work on the subject:

http://www.holmea.demon.co.uk/Frac3/Main.htm
http://www.fpgarelated.com/usenet/fpga/show/85173-1.php
http://www.xilinx.com/support/answers/10703.htm
http://www.eng.auburn.edu/~strouce/class/elec4200/lab7.pdf
http://labserver.uv.es/svn_FPGA/trunk/source/urjtag/extra/fjmem/README
http://www.eng.auburn.edu/~strouce/class/elec4200/spart_configJTAG.pdf

P.S.: I haven't blogged for a while, but Blogspot web-based editor is still the same shit - it just breaks over and over hours of my efforts to create some beautiful formatted text. Damn!