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:
- outwidth - the width of the output port.
- width - the length of the input port, and the width of the debug memory.
- log2samples - this parameters describes the depth of the debug memory.
Number of samples is equal to 2**log2samples
The entity uses also the following signals:
- wr_clk - this is the clock used to sample the recorded data
- trigger - this is the trigger used to start the data acquisition
- wr_init - this is the active low reset signal, preparing the fpgadbg to recording
of data
- data_in - this is the vector of the recorded signals
- post_tr_samples - this is the amount of samples to be taken after the trigger
- triggered - this output informs if fpgadbg has been triggered
- completed - this output informs if fpgadbg has completed to record the data (i.e. has
recorded post_tr_samples after the trigger went high
- rd_init - this input starts the process of receiving data
- rd_finished - this output informs that all data have been succesfully received
- rd_clk - this is the clock used to read the recorded data
- out_data - this is the output of the recorded data. When
width > outwidth
(the typical situation) a single recorded vector is splitted between a few consecutive
output words.
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:
- log2samples - binary logarithm of the maximum number of samples (the real number
of acquired samples may be smaller, if the buffer has not been filled completely - e.g.
when trigger occured right after initiating of recording, and the post_tr_samples
value was small
- width - length of the recorded words. You should use this value to calculate how
many output words uses a single sample.
- trig_pos - IMPORTANT! when outwidth is less than 16, this information is transmitted as 2 words.
informs on which position in the buffer has the trigger occured.
- stop_pos - IMPORTANT! when outwidth is less than 16, this information is transmitted as 2 words.
informs what is the position of the last sample written into the buffer
(in fact the trig_pos, stop_pos and post_tr_samples values are correlated, but it was more
convenient to have such redundant information in the data record)
- Next words, starting from the 5th (or 7th if the outwidth is less than 16)
contain the recorded samples.
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;
- brg_div - divider needed to obtain the UART clock frequency (16x baud rate)
from the system clock. Default has been selected for Spartan 3 Starter Board and
baud rate 115200.
- wr_clk, trigger, data_in - as in fpgadbg
- rs_rx - UART RX line
- rs_tx - UART TX line
- xconf - additional bits, sent from the PC, which may be used to select
one of available configurations.
- sys_clk - system clock
- nrst - reset line (active low)
To initialize fpgadbg_uart, you should send to it three bytes:
byte number | b7 | b6 | b5 | b4 | b3 | b2 | b1 | b0 |
1st byte | 0 | 0 | t5 | t4 | t3 | t2 | t1 | t0 |
2nd byte | 0 | 1 | t11 | t10 | t9 | t8 | t7 | t6 |
3rd byte | 0 | x2 | x1 | x0 | t15 | t14 | t13 | t12 |
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:
- assignments - signal assignment description
- nbits - number of bits in the fpgadbg_core communication interface.
In fact it shouldn't be less than 16. Otherwise you can have problems with passing of some
values like: trig_pos, stop_pos
- timestep - this should be an integer associated with the sampling clock period.
Tsmp=timestep*10^timescale
- timescale - explained above
- filename - Name of the output LXT file
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:
- fpgadbg_core
This directory contains the VHDL sources of the fpgadbg component
(fpgadbg.vhd, fpgadbgmem.vhd) which should be connected to your design.
Here you can also find sources of the fpgadbg_uart interface
(fpgadbg_uart.vhd, smalluart.vhd). In this directory there is also a functional testbench
fpgadbg_tb.vhd - used for simulation.
- fpgadbg_conv
This directory contains the sources of the conversion utilities,
which receive the data from the fpgabdg_core, and store it in the LXT file (used by the
gtkwave viewer)
Some of these sources are not written by me, but have been taken from the gtkwave sources
(the gtkwave's license allows for it).
Execute "make" command in this directory to build necessary extension modules.
- demo_sim
This directory contains a build environment to create a functional demo
showing operation of fpgadbg in the simulated environment. To build this demo, execute the
"make" command in this directory. (However to do it you'll need
the Swig tool and the
GHDL compiler and simulator.)
- s3sb
This directory contains the VHDL sources specific for Spartan 3 Starter Board.
They are used to build a demo showing how fpgadbg works in a real hardware.
- demo_s3sb
This directory contains a build environment to create a working
demo of fpgadbgf for Spartan 3 Starter Board.
To build this example
execute the "make" command in this directory. (However you need the Xilinx tools - e.g. WebPack
version 8.2 installed, and XILINX environment variable correctly set; additionally you'll
need the XC3Sprog utility,
or you should modify makefile to use impact instead)
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