Tuesday, March 19, 2013JTAG Communication by JavaThe new target board DE0-Nano enables JTAG communication using download cable to communicate with host PC only by its embedded functions. DE0-Nano has a USB Blaster-compatible circuit in its body, and so allows host PC to access the board itself simply using the driver of USB Blaster. As this compatible circuit uses FT245BL produced by Future Technology Devices International Ltd. (FTDI), the driver of USB Blaster must be FTDI’s D2XX driver actually. As proof of this, it is possible to access the board just using a DLL file (ftd2xx.dll) attached to D2XX driver. The next point to be discussed is what type of data should be exchanged. Regarding this, details are available in a document relating to UrJTAG. In short, data are clammed in USB packets no longer than 64 bytes and sent out in two kinds of formats, either bit banging mode, which enables controlling all JTAG signals, or byte shift mode capable of high-speed data communication. Then, the next question is how to establish communication with host PC by JTAG. The simplest way is probably to use Virtual JTAG Megafunction for on-chip debugging. This figure shows connecting input and output pins to sld_virtual_jtag megafunction by schematic editor of Quartus II software. For here, we input and output 8-bit data, and so set the parameter sld_ir_width to 8 and sld_auto_instance_index to “YES” just in case. Connect the input pins key[7..0] to ir_out, and the output pins led[7..0] to ir_in. If you don’t want such a hassle to input codes, here you can have the block design file (jtag_led.bdf) and the sof file (jtag_led.sof) finished with logic synthesis. However, you need to specify the pin numbers and the device (EP4CE22F17C6) in case of the block design file. Write the above-shown circuit into the DE0-Nano beforehand, and execute the below-mentioned Java program on the JNA pre-installed environment. I confirmed the working only in the Windows XP environment, but probably it will work in any Win32 environment. Though it isn’t tested yet in a 64-bit environment, I expect it to work just by changing the DLL file name: “usbblstr32” –> “usbblstr64”.
import com.sun.jna.*; import com.sun.jna.ptr.*; public class JTAG_LED { static native int FT_OpenEx(String pArg1, int flags, PointerByReference pHandle); static native int FT_Close(Pointer ftHandle); static native int FT_Write(Pointer ftHandle, Pointer lpBuffer, int dwBytesToWrite, IntByReference lpdwBytesWritten); static native int FT_Read(Pointer ftHandle, Pointer lpBuffer, int dwBytesToRead, IntByReference lpdwBytesReturned); static { Native.register("usbblstr32"); } Pointer ftHandle = null; public JTAG_LED(String description) { PointerByReference pHandle = new PointerByReference(); if (FT_OpenEx(description, 2, pHandle) != 0) { throw new RuntimeException("FT_OpenEx failed."); } ftHandle = pHandle.getValue(); } public void close() { FT_Close(ftHandle); } Memory memory = new Memory(64); IntByReference ref = new IntByReference(); public static final short L = 0x2D2C; public static final short H = L | 0x1010; public static final short TMS = L | 0x0202; public static final short TMS_H = TMS | H; public static final short OFF = 0x0D0C; public void write(short... data) { memory.write(0, data, 0, data.length); FT_Write(ftHandle, memory, data.length << 1, ref); } public static final int WR = 0x81; public static final int RD = 0xC1; public static short byteshift(int data, int mode) { return (short) ((data << 8) | mode); } public byte read() { FT_Read(ftHandle, memory, 1, ref); return memory.getByte(0); } public static void main(String[] args) throws InterruptedException { JTAG_LED jtag = new JTAG_LED("USB-Blaster"); jtag.write(TMS, TMS, TMS, TMS, TMS); // TEST_LOGIC/RESET jtag.write(L, TMS, TMS, L, L); // SHIFT_IR jtag.write(byteshift(0x0e, WR), L, TMS); // USER1 instruction jtag.write(TMS, TMS, L, L); // SHIFT_DR jtag.write(byteshift(0, WR), TMS_H, TMS, TMS, L, L); // Dummy write int lfsr = 1; for (int b = 1; (b & 1) != 0;) { jtag.write(byteshift(lfsr, RD), TMS_H, TMS, TMS, L, L); if (((lfsr <<= 1) & 256) != 0) lfsr ^= 0x171; b = jtag.read() & 255; System.out.println(Integer.toBinaryString(b)); Thread.sleep(((b & 2) != 0) ? 10 : 100); } jtag.write(byteshift(0, WR), TMS_H, TMS, OFF); jtag.close(); } } Once the circuit works successfully, though this picture may not show it well, LED will start flickering rapidly. The flickering is patterned by LFSR, and so not totally randomized. It sometimes looks as if flowing to the left. The flickering gets slower by pushing the left push-button. The program stops and LED goes off by pushing the right push-button. When Java program is executed on the console, it displays the condition of input pins in binary to let us check the conditions of push-buttons and DIP switches. All these operations are regulated by host PC. As a proof, you will see LOAD LED (D4) on during operation, while the light is off at other times. This sample program is to apply the virtual instruction register (VIR) of sld_virtual_jtag megafunction for data communication, which is, indeed, a very extraordinary use. The actual processes of writing VIR are setting USER1 (0000001110) to instruction register (IR) of JTAG and then setting data for transmission and instance ID to data register (DR). As instance ID surely becomes one-bit-long “1” upon generating only one instance of megafunction, data plus “1” needs to be sent. Though JTAG-related circuit have individual clock domain and therefore require care to metastability, DCFIFO is just a “twofer” to clear the requirement and to mount FIFO. |