Connecting External FTDI-Based JTAG Adapter to Basys2 FPGA Board

I had a task to check whether OpenOCD can program a Spartan 3 series FPGA by means of FTDI-MPSSE-based JTAG adapter. There wasn't any chip available in my hands, so I had to experiment with existing hardware. I decided to solder the FTDI-based adapter to a Basys2 development board. The board has an internal JTAG programmer based on AT90USB162. Flashing firmware on this microcontroller during assembly stage requires accessing in-system programmer (ISP) connector. Here is the schematics. Luckily, three of the JTAG pins are the same as the ISP pins:

However, TMS pin is not there. By tracing the routes on the PCB, I found where TMS's route changes the layer to the outermost one:

My soldering skills are not really good, but I could solder a tiny red cable to the TMS pin:

Now we have all the pins necessary to connect an external JTAG adapter. I used a UM232H break-out board which has FT232H chip on it. This chip has a single USB-to-UART converter and an MPSSE engine which implements JTAG protocol. By putting it on a breadboard I connected the following pins to enable self-powering mode and ensuring proper voltage levels:

Then I connected Basys2's JTAG pins to the breadboard:

Basys2 has to be connected to the computer, since the power is taken from the USB port. Same goes for UM232H, so two boards are connected only using GND, TMS, TCK, TDI and TDO pins.

Basys2's JTAG Chain

Here is the JTAG chain of the Digilent Basys2 FPGA board:

The first IC (xc3s100e) is the actual FPGA chip from the Spartan 3E family. The second chip (xcf02s) is a flash memory (PROM). Let's read the ID codes of both chips using original proprietary software, called Digilent Adept Runtime and Digilent Adept Utilities. I am using Arch Linux, so let's install the software first and read the ID codes:

These values of the ID code register will used as a reference to comparing ID codes retrieved using UrJTAG, OpenOCD and xc3sprog.

Reading ID Codes Using UrJTAG

Now let's play with UrJTAG. Firstly, install it from AUR:

For each chip the chain, JTAG-specific instructions and properties of special registers including BSR (boundary scan register) are provided in BSDL files. These files are absolutely necessary for UrJTAG and they can be retrieved from the vendor's website or from the Xilinx ISE installation. If you have Xilinx ISE already installed, check out the "xc3s100e.bsd" file located at "$XILINX_ISE_PATH/spartan3e/data/" and "xcf02s.bsd" file located at "$XILINX_ISE_PATH/xcf/data/", where $XILINX_ISE_PATH  is the installation path, e.g. "/opt/Xilinx/14.7/ISE_DS/ISE/". Create a "Basys2_BSDL" directory and copy BSDL files to it:

Connect UM232H board to USB, and make sure that it is recognized:

Now run "jtag" and execute the following commands interactively:

UrJTAG scans BSDL files, reads all opcodes and register names and automatically substitutes them when you run instruction for a specified part (chip). For example, when part "1" was selected (XC3S100E), UrJTAG substituted instruction IDCODE with 0x09 (see the xc3s100e_cp132.bsd file). For part "0", it substituted it with 0xFE.

Reading ID Codes Using OpenOCD

Open On-Chip Debugger (OpenOCD) is a powerful tool which is used to debug various chips. In order to run it with the UM232H adapter we need to specify adapter details in a configuration file. Firstly, create a directory with the name "OpenOCD":

Inside this directory, create two text files with the following content. The first file with the name "FT232H.cfg" is for the adapter:

The second file with the name "Basys2.cfg" contains expect ID codes for our chips in the chain:

Now start the OpenOCD server with the newly created files:

Both of the devices are recognized and their ID codes match the expected ones. Now open a second terminal  and login to the OpenOCD server as a client:

Low-level operator "irscan" is responsible for selecting opcode, setting other devices to bypass mode and shifting the opcode through the chain to a target device. OpenOCD cannot read BSDL definitions, so we have to provide all the instructions manually. Let's look inside of the xc3s100e_cp132.bsd file:

The IDCODE instruction has value "0b001001" = 0x09, so

means to consider only spartan3e.tap device (others are bypassed) and shift IDCODE instruction through the chain. Once this is done, the TAP select IDCODE register as the data register and we can shift 32 bits (0x20 in hexadecimal) through the chain to retrieve the content of the data register and set TAP of the device to state "0" (not sure which one it is):

Reading ID Codes Using xc3sprog

Open-source x3sprog tool is capable of flashing *.bit files, reading DNA and writing to a connected SPI Flash. Install it from AUR:

Reading ID codes is easy: