WZab's animated logo

Fpgadbg - a tool for FPGA debugging

Fpgadbg (should be pronounced as "FPGA debug") is a tool allowing for relatively easy debugging of your digital designs implemented in the FPGA chips.
I have decided to write the fpgadbg, when I had to debug the system consisting of many FPGA chips produced by different manufacturers. Some of them was manufactured by Altera, and some of them - by Xilinx. I could use the vendor provided tools - SignalTap for Altera and ChipScope for Xilinx, but I needed a uniform solution for all my chips. Additionally I wanted to be able to read the debug data via the VME bus - and so I started to write fpgadbg.
Fpgadbg may work with different communication interfaces. The provided sources show how to communicate with it using the 16-bit wide interface, or using the 8-bit wide UART-based interface. I hope, that someone will be able to prepare extensions allowing to use fpgadbg over the SPI or JTAG interface.
When working with VME-like 16-bit interface fpgadbg occupies only 3 registers (1 for status/control signals. 1 for setting of number of data acquired after the trigger and 1 for reading of recorded data). Fpgadbg allows you to record the signals available inside of FPGA, and then transmit recorded waveforms outside the chip to view them with a graphical viewer.
Fpgadbg is similar to the commercially available debug tools offered by different FPGA vendors, and in fact it is much less powerfull than its commercial counterparts. But on the other hand it is a free, open source solution, available under the GPL license, with an additional exception, allowing you to link it with any other HDL code to obtain a IP core or configuration bitstream, which you can distribute without disclosing your sources.
So fpgadbg may be suited to your particular needs, and may be distributed with the rest of your debugged IP core, not forcing you to disclose sources of your design.
Fpgadbg consists of two parts. The first one is the small IP core (fpgadbg_core), available as a VHDL source, which you can connect to the rest of your design. You need to complement it with a communication interface e.g. connecting it to the asynchronous bus, or using the fpgadbg_uart to communicate via serial line.
The second one is the small program (fpgadbg_conv) written in the Python programming language, used to convert the data recorded by the fpgadbg_core into the LXT file, used by the gtkwave waveform viewer.

fpgadbg_core - the signal recorder

The fpgadbg entity is defined as:
entity fpgadbg is
  generic (
    outwidth    : integer := 16;
    width       : integer := 35;
    log2samples : integer := 10);
  port (wr_clk             : in  std_logic;
        trigger         : in  std_logic;
        wr_init             : in  std_logic;
        data_in         : in  std_logic_vector((width-1) downto 0);
        post_tr_samples : in  integer range 0 to 65535;
        triggered       : out std_logic;
        completed       : out std_logic;
        rd_init         : in  std_logic;
        rd_finished     : out std_logic;
        rd_clk          : in  std_logic;
        out_data        : out std_logic_vector((outwidth-1) downto 0)
        );
end fpgadbg;
    
The entity uses the following generics: The entity uses also the following signals: To help you understand how to use the fpgadbg, I have prepared a simple fpgadbg_tb.vhd file, which shows how to connect fpgadbg to signals in your design, how to initiate signal recording, and how to read the recorded data. The data read back from the fpgadbg contain the following words:

fpgadbg_uart

This is the wrapper around the fpgadbg, allowing to use the UART protocol to communicate with the fpgadbg.
entity fpgadbg_uart is
  generic (
    brg_div     : integer := 50000000/16/115200;
    width       : integer := 35;
    log2samples : integer := 10);
  port (
    wr_clk  : in  std_logic;
    trigger : in  std_logic;
    data_in : in  std_logic_vector((width-1) downto 0);
    rs_rx   : in  std_logic;
    rs_tx   : out std_logic;
    xconf   : out std_logic_vector(2 downto 0);
    sys_clk : in  std_logic;
    nrst    : in  std_logic
    );
end fpgadbg_uart;
To initialize fpgadbg_uart, you should send to it three bytes:
byte numberb7b6b5b4b3b2b1b0
1st byte00t5t4t3t2t1t0
2nd byte01t11t10t9t8t7t6
3rd byte0x2x1x0t15t14t13t12
Bits t15...t0 encode the post_tr_samples value. Bits x2...x0 encode the xconf value - you may use it to select one of a few available configurations - they may use different triggers or connect different signals to the data_in input. So you can debug different parts of your system without recompilation of the core.
After fpgadbg_uart receives the 3rd byte, it starts recording of the data, and waits for trigger. After the trigger is received, fpgadbg records yet post_tr_samples of data samples, and then sends the data via UART to the PC. The format of the data is as described previously. The outwidth for the fpgadbg_uart is set to 8. See the fpgadbg_s3sb_demo.py source to see, how implement the communication with fpgadbg_uart on the PC side.

fpgadbg_conv - the signal converter

I assume, that you are able to receive the data from the fpgadbg_core and put it into the Python list or tuple. I've prepared the fpgadbg_demo.py file, which reads the file written by the fpgadbg_tb.vhd testbench. Similarly, the fpgadbg_s3sb_demo.py reads the data from the fpgadbg_uart.
If you have read the recorded data, then you can use the fpgadbg_conv.py module, to convert this data into the LXT file, which can be easily displayed with the gtkwave wiever.
To use the fpgadbg_conv, you need first to create the signal assignment description:
assgn=((20,11,"counter_nb"),
   (10,10,"Clk"),
   (9,0,"lsr"))
Each entry in the description tuple contains: number of the MSB bit of the particular signal in the recorded word, number of the LSB bit, and the name of the signal. You can also use entry with five data fields. Two additional fields contain the MSB number, and the LSB number in the signal itself.
If you have a signal "addr(10 downto 2)" stored in the bits 22 to 14 in the recorded word, then the assignment entry should have a following form: (22,14,"addr",10,2)
The assignment description should be created automatically from the VHDL source, but the appropriate tool is not ready yet.
After the assignment description is created, you should create the conversion object:
cnv=fpgadbg_conv.fpgadbg_conv(assgn,16,125,-10,"test.lxt")
The parameters passed to the constructor of the fpgadbg_conv object are: After the converter is created, you can convert the received data into the LXT file.
cnv.conv(data)
In the current implementation the converter object is "single use" only. If you want to convert the next set of recorded data, you need to create a new converter object. (It may be changed in the next implementation).

Description of the sources

The sources of the version 1.1 can be downloaded here. After unpacking of the archive, you'll get five directories:

Old version

The sources of the first version can be downloaded here.

Disclaimer

Fpgadbg is provided for free "as is", without any warranty. All I can say is that it worked for me, and hasn't blown up my FPGAs. I don't know if ot can destroy yours FPGAs in some specific conditions.
Especially you should double check what are you doing, if you are going to use the fpgadbg_s3sb demo. I've tried to automate the process of building of the demo core, and it works with my demo board, however I don't know if it will generate the correct core when used with other set of Xilinx tools. Especially check if the unused pins are set to "float".
I don't know anything about the patent status of solutions used in fpgadbg, so if you are going to use it in a commercial environment you may need to check it by your own (however it highly depends on the country you live in).
Wojtek Zabolotny
Last modified: Fri Jul 28 16:37:15 CEST 2006