Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
on
1 Introduction 4
1.1 Prerequisites . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
1.1.1 AHIR V2 Tool-Chain . . . . . . . . . . . . . . . . . . . 5
1.1.2 RIFFA 2.0 . . . . . . . . . . . . . . . . . . . . . . . . . 7
1.1.3 Additional tools . . . . . . . . . . . . . . . . . . . . . . 8
1.1.4 Xilinx ISE Design suite . . . . . . . . . . . . . . . . . . 8
1.1.5 Connection of the FPGA Card to the Host Computer . 8
1.2 Conclusion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
1
4.4 Use of Xilinx iMPACT: From Bit-file to Physical Hardware on
the FPGA . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
4.5 Conclusion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
6 References 31
2
Abstract
We describe a complete pathway using which an algorithm described in C can
be implemented in FPGA hardware. The initial specification and verification
of the algorithm is done in C (using standard C-compilers and debuggers).
Once verified, the C description of the algorithm is converted to VHDL using
the AHIR-V2 tool-chain (developed at IIT Bombay). The generated VHDL
is then verified using the same test infrastructure which was used for algo-
rithm verification at the C level. After successful verification, the AHIR-V2
generated VHDL is mapped to an FPGA target using standard FPGA syn-
thesis tools. In this particular case, we use the ML605 card from Xilinx as
the target platform. The ML605 card uses a Virtex 6 FPGA from Xilinx,
and has a PCI-express interface through which it can be connected to a host
computer. In order to communicate between the card and the host computer,
we use the RIFFA 2.0 infrastructure (developed at UCSD). The final hard-
ware implementation of the algorithm can then be accessed from the host
in real-time. We illustrate the entire pathway by taking an application from
the algorithm level to the final hardware level.
3
Chapter 1
Introduction
1.1 Prerequisites
We need AHIR V2 tool-chain and RIFFA 2.0 installed in our system. Addi-
tionaly, Xilinx ISE 13.2 (which includes iMPACT and XST) must be installed
in the system. Some additional tools are also needed, and downloaded as a
package named addonsAHIR from the VLSI consortium website of IIT Bom-
4
bay (Will be discussed in details later). The ML605 card also needs to be
connected to the host computer thriugh PCI-e interface.
Installation Prerequisites
Two packages- llvm-2.8, clang-2.8 must be installed before installing AHIR
V2. ( In order to use llvm 2.8, gcc 4.2 is also needed which was already
present in Ubuntu 12.04). All these packages can be downloaded from the
following link.
http://llvm.org/releases/download.html
These packages get downloaded as zip-files. Upon extraction they create two
directories named ’llvm-2.8’ and ’clang-2.8’. clang-2.8 directory is copied
to llvm-2.8/tools directory. The entire llvm-2.8 directory is kept inside a
directory named ’llvm’. Now inside the ’llvm’ directory, following commands
are run.
mkdir build
cd build
../llvm-2.8/configure
make
These commands, installs the llvm-2.8 and clang-2.8 packages upon successful
execution. Inside build directory, a directory named ’Release’ is created. In-
side ’Release’ directory, two directories named ’bin’ and ’lin’ must be present.
THe ”bin” directory’s path is added to PATH environment variable, and the
”lib” directory’s path is added to LD-LIBRARY-PATH variable. For that,
bashrc file is opened using following command.
vim ~/.bashrc
5
PATH=$PATH:/full-path-of-the-bin-directory-as-stated-above
export PATH
LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/path of bin directory
Installation Procedure
AHIR V2 is an open source tool available for download from github. The
following command is run to download it from git repository.
By this, a directory titled ’ahir’ will be created in the workspace which will
contain all necessary files,libraries and scripts. The following commands are
then executed in the given order
cd ahir/v2
source build_bashrc
scons
cd ahir/v2
make -f ReleaseMakefile
After a release for AHIR V2 is made, the bashrc file needs to be modified.
This file is opened by following command.
vi ~/.bashrc
The following lines are added to this file. The AHIR RELEASE path will
change according to the user-name
6
export AHIR_RELEASE=/home/the- path-of-the-ahir-release- directory
#in this case the path was /home/pratt/ahir/release
export PATH=$AHIR_RELEASE/bin:$PATH
export LD_LIBRARY_PATH=$AHIR_RELEASE/iolib/lib:$LD_LIBRARY_PATH
export LD_LIBRARY_PATH=$AHIR_RELEASE/CtestBench/lib:$LD_LIBRARY_PATH
export LD_LIBRARY_PATH=$AHIR_RELEASE/pipeHandler/lib:$LD_LIBRARY_PATH
export LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH
Installation Prerequisites
The system must be using a Linux kernel version 2.6 or higher. If this criteria
is not meet, the operating system must be updated before installing RIFFA
2.0. Since, we are describing the installation preocedure for an Ubuntu
12.04 operating system(that uses kernel version 3.2) no further upgradation
is needed.
Installation Procedure
First, RIFFA 2.0 distribution needs to be downloaded from the following
link.
https://sites.google.com/a/eng.ucsd.edu/matt-jacobsen/riffa/
riffa_2_0/download/
This command actually installs the kernel headers against the current kernel
version of the operating system. The following commands are then executed.
make
sudo make install
7
These commands build and install the drivers and the libraries. The system
gets configured to load the driver at boot time. It is recommended to reboot
the system once after RIFFA 2.0 driver installation.
8
http://www.xilinx.com/support/documentation/boards_and_kits/ug533.pdf
Figure 1.2: Conncetion between FPGA board and computer through USB
JTAG connector
9
1.2 Conclusion
In this chapter we have described the overall picture of the current work and
also discussed the software and hardware requirments before starting work.
In the next chapters we will take up an example algorithm and illustrate how
it is taken from C algorithm to FPGA hardware on ML605 board.
10
Chapter 2
2.1 Introduction
In the previous chapter, we have described the tools required to take a C-
algorithm to FPGA-based physical hardware(using our scheme). Once, we
have all those tools successfully installed in the system and the FPGA card
is properly connected to the system through PCI-e interface, we are ready to
take an algorithm to FPGA hardware and verify it.
In this chapter, we take up a small example algorithm. Then we explain
how to describe that algorithm in C. We also describe how to write a test-
infrastructure in C for our example design. Then we will discuss how to
validate our design with that C test-infrastructure.
11
2.3 C Programming of the Example
In chapter 1, we had created AHIR release. Inside this release directory, we
create a directory named example. Inside this example directory, we create
another directory named src. This src directory will contain our C algorithm
and its testbench. As mentioned, we started by describing an addition-
algorithm in C(Inside the src directory said above). We need to write both
the algorithm and its test-infrastructure in C.
#include <stdlib.h>
#include <stdint.h>
#include <Pipes.h>
#include <stdio.h>
#include "prog.h"
#define ORDER 20
unsigned int y;
double x1[ORDER],x2[ORDER];
double x3[ORDER];
void recvd()
{
while(1)
{
12
int idx,i;
for( idx=0 ; idx < ORDER ; idx++)
{
x1[idx] = read_float64("input_port_0");
x2[idx] = read_float64("input_port_1");
}
#include <pthread.h>
#include <stdio.h>
#include <stdint.h>
#include <pthreadUtils.h>
#include <Pipes.h>
#include <pipeHandler.h>
#include "prog.h"
#ifndef SW
#include "vhdlCStubs.h"
#endif
13
#define ORDER 20
#ifdef SW
DEFINE_THREAD(recvd)
#endif
#ifdef SW
init_pipe_handler();
register_pipe("input_port_0",20,64,0);
register_pipe("input_port_1",20,64,0);
register_pipe("output_port_0",20,64,0);
PTHREAD_DECL(recvd);
PTHREAD_CREATE(recvd);
#endif
double result[ORDER] ;
uint32_t idx;
uint8_t jdx;
14
}
#ifdef SW
PTHREAD_CANCEL(recvd);
close_pipe_handler();
#endif
return(0);
In this code, we have written a function Sender 0. This function sends data
through two pipes and receives data back from one pipe. Inside the main
function, this function is called and it sends and receives data. When SW is
defined, the two C programs get executed in parallel and talk to each other.
15
PTHREADUTILS_INCLUDE=$(AHIR_RELEASE)/pthreadUtils/include
SRC=./src
PROGDEFS=
#Stage 2 - this part actually carries out the software level verification
#using gcc compiler.
# -g option enables debugging.
# -c option enables compilation.
# -DSW option enables the use of #ifdef SW segments. These macros will be
#executed only during software level verification, i.e. when SW is defined.
2.5 Conclusion
In this chapter, we described how to write an example algorithm and its
test-infrastructure in C. We wrote a small example and discussed how to
verify it using C test-infrastructure. In the next chapters, we will convert
this C algorithm into VHDL design and generate hardware on FPGA from
that VHDL design.
16
Chapter 3
3.1 Introduction
In the last chapter, we described how to write hardware descriptions in C and
verify them in software level. We took an example algorithm, and explained
how to write and test it in software, using a standard C compiler(in our
case gcc). In this chapter, we will show how a C-algorithm is converted to
synthesizable VHDL design using AHIR V2. We will also describe, how to
use the same C- test-bench to validate this AHIR generated VHDL.
17
#step 1:we declared some paths
in the makefile for Software level verification.
# following paths are added to the list of existing
paths inside the makefile.
#AHIR_RELEASE must be an environment variable .
SOCKETLIB_INCLUDE=$(AHIR_RELEASE)/CtestBench/include
%FUNCTIONLIB=$(AHIR_RELEASE)/functionLibrary/
%PTHREADUTILS_INCLUDE=$(AHIR_RELEASE)/pthreadUtils/include
VHDL_LIB=$(AHIR_RELEASE)/vhdl
SOCKETLIB_LIB=$(AHIR_RELEASE)/CtestBench/lib
LLVM2AAOPTS=-extract_do_while=true --storageinit=true -
pipedepths=pipedepths.txt
SRC=./src
TOPMODULES=-T addition
# there are 5 intermediate steps between C files and VHDL designs. Those
five steps will be executed in sequence when HW is defined, as mentioned in
the following line.
18
#stage 2 - Generation of AHIR assembly(Aa) codes from llvm byte codes.
llvmbc2aa: prog.opt.o
llvm2aa $(LLVM2AAOPTS) prog.opt.o | vcFormat > prog.aa
aa2vc: prog.linked.opt.aa
Aa2VC -O -C prog.linked.opt.aa | vcFormat > prog.vc
vc2vhdl: prog.vc
vc2vhdl -O -S 4 -I 2 -v -a -C -e ahir_system -w -s ghdl $(TOPMODULES) -f
prog.vc -L $(FUNCTIONLIB)/fpu.list
vhdlFormat < ahir_system_global_package.unformatted_vhdl >
ahir_system_global_package.vhdl
vhdlFormat < ahir_system.unformatted_vhdl > ahir_system.vhdl
vhdlFormat < ahir_system_test_bench.unformatted_vhdl >
ahir_system_test_bench.vhdl
19
ghdl -i --work=work ahir_system_test_bench.vhdl
ghdl -m --work=work -Wl,-L$(SOCKETLIB_LIB)
-Wl,-lVhpi ahir_system_test_bench
make HW
If this command runs successfully, then ahir VHDL files are generated inside
our working directory(in this case the ’example’ directory). One executable
named testbench hw is also created which will be used for the verification of
these newly generated VHDL files.
./testbench_hw
Now, a new terminal is to be opened and from that terminal the ahir system testbench
executable is run by running the following command.
./ahir_system_testbench
20
Figure 3.1: Hardware Simulation of the Design, Two Processes in Two Dif-
ferent Windows Interact with Each-other
3.4 Conclusion
In this chapter, we described how to convert the C algorithm into VHDL
descriptions and how to validate them. In the next chapter we will describe
how to map those validated VHDL descriptions on the FPGA hardware and
test the hardware.
21
Chapter 4
4.1 Introduction
In the last chapter, we took the example C algorithm and converted it to
VHDL description. We also showed, how to verify those VHDL desgins. In
this chapter, we will take those VHDL descriptions and generate the bit-file
out of them. We will then map the bit-file on the FPGA to get the physical
hardware.
22
named addonsAHIR)
cd addonsAHIR/ahirWrapper_gen
xilperl wrapgen.pl
This will ask for number of pipes and their names before generating the
wrapper. It will also ask for whether it is to be used for communication
through PCI-e interface or ethrnet interface. All these informations are to
be given correctly. The pipe names are as those specified in the C algorithm.
This will generate a verilog code titled chnl tester.v , which is the wrapper.
This file will be used along with the AHIR VHDL files for bit-file generation.
xilperl compile.pl
23
Upon successful execution, a new file named routed.bit will be created inside
synthesis tools/scripts/results directory(inside the addonsAHIR package).
Figure 4.1: The iMPACT software detects the card, Virtex 6 FPGA is de-
noted by the xc6vlx240t symbol
In the GUI, the software will ask the user to assign configuration files
to the RAM and the FPGA. We shall bypass this step for the RAM. Then,
we need to browse through the file system and chose the newly generated
routed.bit file as the cofiguration file. Then we need to right-click on the
FPGA symbol and program it. Once, the programming is done, the hardware
is generated on the FPGA. However, before starting to use it, we must reboot
our system once (keeping the switch in the ML605 board turned on). Upon
restart, the hardware on FPGA is ready for use and testing.
4.5 Conclusion
In this chapter, we have generated physical hardware from our AHIR VHDL
files generated from some initial C-specifications. This hardware on FPGA
24
needs to be validated. In the next chapter, we will describe how to validate
the hardware on the FPGA using RIFFA 2.0 test-infrastructure.
25
Chapter 5
5.1 Introduction
In the end of the last chapter, we had our hardware ready on the FPGA.
This hardware is generated from the initial algorithmic specification in C.
But this hardware is yet not validated. In this chapter, we will describe the
process of writing the RIFFA test-infrastructure and verifying the hardware
using it.
#include <stdio.h>
#include <stdlib.h>
#include <riffa.h>
26
int fid = 0; // FPGA id
int channel = 0; // FPGA channel
fpga = fpga_open(fid);
fpga_send(fpga, channel, (void *)buf, BUF_SIZE, 0, 1, 0);
fpga_recv(fpga, channel, (void *)buf, BUF_SIZE, 0);
fpga_close(fpga);
return 0;
}
In general, the fpga is opened, some data are sent to it(using fpga send
function), some data are received from it(using fpga recv function), and then
it is closed using fpga close function. The details of these functions, their
uses, and the their arguments are explained in the following link.
https://sites.google.com/a/eng.ucsd.edu/matt-
jacobsen/riffa/riffa_2_0/c-interface
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include "timer.h"
#include <riffa.h>
fpga_t * fpga;
int beginSend = 0;
int beginRecv = 0;
27
int end = 0;
int numWords = 80000;
int fid=0;
void * sender_fxn(void *)
{
unsigned int * sendbuf;
unsigned int * sendbuf2;
sendbuf = (unsigned int *)malloc(numWords<<2);
for (int i = 0; i<numWords; i++){
sendbuf[i] = 10*i;
}
sendbuf2 = (unsigned int *)malloc(numWords<<2);
for (int i = 0; i<numWords; i++){
sendbuf2[i] = i;
}
int sent;
int sent2;
while(beginRecv){}
sent = fpga_send(fpga, 0,sendbuf, numWords, 0, 1, 2000);
sent2 = fpga_send(fpga, 1,sendbuf2, numWords, 0, 1, 2000);
beginSend = 1;
for (int i=0; i<10; i++){
cout << "sent word " << i << " is "<< sendbuf[i] << endl;
}
while(!end);
if (sendbuf != NULL)
sendbuf = NULL;
28
for (int i = 0; i<numWords; i++){
recvbuf[i] = 0;
}
int rc;
while (!beginSend){;};
beginRecv = 1;
rc = fpga_recv(fpga, 0, recvbuf, numWords, 2000);
GET_TIME_VAL(1);
for (int i=0; i<10; i++){
cout << "received word " << i << " is " << recvbuf[i] << endl;
}
if (recvbuf != NULL)
recvbuf = NULL;
}
if (argc<2){
fprintf(stderr, "supply fpga number. Format ./tb <index>\n");
return 1;
}
fpga = fpga_open(atoi(argv[1]));
if(fpga == NULL){
cerr << "ERROR: Could not open FPGA " << atoi(argv[1]) << "!" << endl;
return -1;
}
fpga_reset(fpga);
pthread_create(&sender, NULL, sender_fxn, NULL);
pthread_create(&receiver, NULL, receiver_fxn, NULL);
pthread_join(sender, NULL);
pthread_join(receiver, NULL);
fpga_close(fpga);
return 0;
}
29
computed data. In this particular test-infrastrcture we print first 10 input
and output data-sets for verification.
g++ -c new_edit.cpp
g++ -o tb new_edit.o -lriffa -lpthread
However, a Makefile can also be written, that contains these two lines. So,
only the ’make’ command will be sufficient to build the executable. The
executable(named tb in this case) is run with the command below.
5.4 Conclusion
Upon successful validation, we have a working hardware which actually was
specified in C ! Besides designing the hardware in C, initial debugging is
also carried out using C testbenches and C compilers. Since it is easier to
code and debug in C language, designing and debugging of hardware in this
scheme is much easier compared to the traditional methods. Although we
showed the flow of this work with a simple example, this same technique can
be used to design much complex systems.
30
Chapter 6
References
31