Wednesday, March 27, 2013

JTAG Configuration by Java

To drive the nail home, now let’s try configuration (rewriting the circuit) of FPGA by JTAG.
In JTAG configuration, we use SVF files output by Quartus II.  A SVF file, consisting of a kind of script language, enables circuit reconstruction by executing raw JTAG operations described in it.

Firstly, please have a try to download the Jar file (jtag_demo.jar) and execute while keeping DE0-Nano in connection with USB cable.  This is supposed to be compatible to 64-bit environment, which is not tested yet though.

jtag_demo.png

The above image shows the result of executing 4 commands of “Reset FPGA,” “IDCODE,” “Config FPGA” and “Start Demo” one after another, for example.

“Reset FPGA” is a command to forcefully configure FPGA, and, in case of DE0-Nano, loads the circuit in the EPCS64 on the board.  “IDCODE” is a command to read 32-bit IDCODE of the device “EP4CE22.”

“Config FPGA” is to execute a SVF file and configure FPGA.
The SVF file, compressed up to 30k bytes from an original file bigger than 1M bytes, is stored as resource in Jar file.  In fact, most capacity of Jar file is occupied by Jar file of bundled JNA.

The SVF player has only crucial minimal capabilities, while many other functions such as checking TDO are left out.
Please make sure NOT to execute this file on other devices than DE0-Nano.

The last “Start Demo” enables observing I/O data via JTAG communication demonstration (except changing speed and halting by pushing buttons) which appeared in the previous article.  To tell you the truth, this command can work with no error even before configuration, but then the output data cast no impact on LED.

As this operation requires complicated processing such as execution of SVF and GUI, it would be all the less readable to combine all processes into single Java code.  Therefore, I split it into three parts, JTAG library and basic GUI (JTAG.java) as a relatively generic part, execution of SVF (SVFPlayer.java) and demo application (JTAG_Demo.java).

With a split library, the demo application part has a very simple design.  A button appears in display upon the creation of a JTAG.GUI class instance.  While having to describe what you’d like to run in onClick() method, you have little need to write down raw data by write() method thanks to additional methods: state() method to transit JTAG state for SVF execution and shift() method for SHIFT_DR/SHIFT_IR.

SVFPlayer class is a derived class of JTAG.GUI, which requires appointing button name and resource name of SVF as generation parameters.

import info.relm.JTAG;
import info.relm.SVFPlayer;
public class JTAG_Demo extends JTAG {
    public static void main(String[] args) {
        GUI.title("JTAG Demo for DE0-Nano");
        new GUI("Reset FPGA") {
            public void onClick() {
                reset();
                state("RESET", "IRSHIFT");
                shift(10, 0x1);
                state("IREXIT1", "IRUPDATE");
                text.append("Reconfiguration done.n");
            }
        };
        new GUI("IDCODE") {
            public void onClick() {
                reset();
                state("RESET", "IRSHIFT");
                shift(10, 0x6);
                state("IREXIT1", "DRSHIFT");
                readBytes(4, 0);
                text.append("IDCODE: " +
                    Long.toBinaryString(0xffffffff00000000L |
                    read(4)[0]).substring(32) + 'n');
            }
        };
        new SVFPlayer("Config FPGA", "jtag_led.svf");
        new GUI("Start Demo", "Stop Demo") {
            public void onClick() {
                reset();
                state("RESET", "IRSHIFT");
                shift(10, 0xe);
                state("IREXIT1", "DRSHIFT");
                shift(9, 0x100);
                state("DREXIT1", "DRSHIFT");
                flush();
                try {
                    for (int lfsr = 1; ; Thread.sleep(10)) {
                        readBytes(1, lfsr);
                        shift(1, 1);
                        state("DREXIT1", "DRSHIFT");
                        text.append("out: " +
                            Integer.toBinaryString(lfsr | 256).substring(1) +
                            "tin: " +
                            Integer.toBinaryString(read(1)[0] | 256).substring(1) +
                            'n');
                        if (((lfsr <<= 1) & 256) != 0) lfsr ^= 0x171;
                    }
                } catch (InterruptedException e) {}
                shift(9, 0x100);
                state("DREXIT1", "DRUPDATE");
            }
        };
    }
}

It enables FPGA configuration without setting up Quartus II.
I would like to disclose configuration data in this format from now on unless it causes any problem.

Tuesday, March 19, 2013

JTAG Communication by Java

The new target board DE0-Nano enables JTAG communication using download cable to communicate with host PC only by its embedded functions.
Currently, however, somehow it’s hard to get well-organized information on JTAG communication.  No technical document seems available even about DE0-Nano’s attached demo application surely able to communicate with host PC.
Based on this reality, I am disclosing the result of my study:

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.
Therefore, information on accessing hardware is available in an indirect form as a document of 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
Now let’s design a circuit.

jtag_led_bdf.png

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.
Allocate LED pins (A15, A13, B13, A11, D1, F3, B1, L3) on the board to the led[7..0], while for the key[7..0], we only use 2-bit push-buttons (E1, J15), and so assign other pins freely to DIP switches (M15, B9, T8, M1) and GPIO input pins (B8, A8).

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.
If you don’t want to install JNA or compile Java scripts, just run the Jar file (jtag_led.jar) which bundles JNA.

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.

de0nano_jtag.jpg

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.
As VIR allows data length up to 32 bit, this technique would have no problem in exchanging data within the length.  A more conventional way is to specify a channel by VIR and then to communicate data by virtual data register (VDR), which sets no limit on data length but requires the implementation of shift register otherwise.

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.
While receiving data coincides sending data, the channel choice is reflected only in the next data reception and on.  Therefore, it is necessary to settle the channel by sending dummy data once at first transmission.
While this sample is so simple that leaves almost all tasks to megafunction, actual communication would require protocol-level implementation such as FIFO and flow control.

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.

Saturday, March 16, 2013

Target Board DE0-Nano

Now I’d rather stop carrying logics on and on, and go for making a real circuit.
I’ve been looking for a target board, and found one right in point: DE0-Nano by Terasic Technologies Inc.
This cheap board costing below 80 dollars employs Cyclone IV, which can accommodate a relatively large circuit, probably with 8 or more up to 16 cores.  Also accompanying A/D converter, acceleration sensor and SDRAM, it allows users to try many gadgets without any external tools.

The few but crucial shortcomings of this board are that it has only on-board 8 LEDs for displaying and that it allows access from the JTAG configuration cable as the basically only way to communicate with host PC.
JTAG-UART will help that communication, if you use it, but SOPC Builder is the last choice for me to use, because I am introducing such a technique to be compatible with Xilinx in the future.

Compare to Arduino enabling serial communication just with a download cable….

As logic synthesis for multi-core processor takes a certain amount of time, it makes no sense if we have to do it again from the beginning every time we renew a software — the free Web Edition doesn’t support incremental compilation yet.

If the board can communicate with host PC, it enables downloading software without logic synthesis, greatly enhancing efficiency in development work.  Furthermore, if the board can communicate with custom application software in real-time, it will expand the sphere of what we can apply this technology to.

Once I was almost disappointed at finding only such desperate efforts as to forcefully redirect console I/O of the integrated environment through the web.
It looked so impossible until I found a free JTAG tool, UrJTAG, enables access to the board.  Taking it as a clue, I’ve reached how to control USB Blaster by Java with JNA (though it is tested only with equivalent capabilities of DE0-Nano, and not with a real USB Blaster yet).

I’m going to upload this kind of information from time to time….