How to make a VHDL design in Ubuntu/Debian
This tutorial describes how to install all the necessary tools to develop simple designs under Ubuntu for the Armadeus Project.
As Ubuntu is a Debian based distribution, all the informations on this page should work with Debian too.
Contents
Editing VHDL
To edit VHDL code all standard editing softwares like Vim, Emacs or others can be used. But Emacs has a really good vhdl-mode used by lots of designers. If you hate Emacs, you can use the xilinx-embedded editor or vim with a VHDL-plugin under development.
Making a simple project
It's a good idea to make a ?proper? project tree for your design, because different software are used and each generates a large amount of files.
Here is an example of a VHDL project tree :
- MySimple_project/
- src/ for all sources files (.vhd,.ucf,.xcf)
- testbench/ VHDL sources files for testing your design
- ise/ Xilinx web pack will work in this directory
- simu/ All files generated by the simulator
Simulation
To stay in the Free Software spirit, the best method to simulate is to use GHDL (based on GCC).
To install it on Ubuntu you just have to type :
$ sudo apt-get install ghdl
You can find a good tutorial for using GHDL here and on the official website. It's supposed that the project tree used is this one described previously.
Analysing files:
$ ghdl -i --ieee=synopsys --warn-no-vital-generic --workdir=simu --work=work src/*.vhdl testbench/testb_file.vhd
And compile:
$ ghdl -m --ieee=synopsys --warn-no-vital-generic --workdir=simu --work=work testb_file
After that a binary file named testb_file is created; to launch simulation we just have to:
$ ./testb_file --stop-time=500ns --vcdgz=testb_file.vcdgz
The stop time option sets the simulation time and the vcdgz option will generate a gunzip compressed wave file to visualize the result.
Visualizing the result can be done with gtkwave:
$ sudo apt-get install gtkwave
We can launch it with the following command :
$ gunzip --stdout testb_file.vcdgz | gtkwave --vcd
It can be a good idea to make a Makefile instead of typing all this commands, here is a little Makefile:
# project name PROJECT=bus_led_top # vhdl files FILES = src/bus_led.vhd src/bus_led_top.vhd # testbench SIMTOP = led_top_tb SIMFILES = testbench/led_top_tb.vhd # Simu break condition GHDL_SIM_OPT = --assert-level=error #GHDL_SIM_OPT = --stop-time=500ns SIMDIR = simu SYNTHFILES = bin/bus_led_ise/netgen/synthesis GHDL_CMD = ghdl GHDL_FLAGS = --ieee=synopsys --warn-no-vital-generic VIEW_CMD = /usr/bin/gtkwave ghdl-compil : mkdir -p simu $(GHDL_CMD) -i $(GHDL_FLAGS) --workdir=simu --work=work $(SIMFILES) $(FILES) $(GHDL_CMD) -m $(GHDL_FLAGS) --workdir=simu --work=work $(SIMTOP) @mv $(SIMTOP) simu/$(SIMTOP) ghdl-run : @$(SIMDIR)/$(SIMTOP) $(GHDL_SIM_OPT) --vcdgz=$(SIMDIR)/$(SIMTOP).vcdgz ghdl-view: gunzip --stdout $(SIMDIR)/$(SIMTOP).vcdgz | $(VIEW_CMD) --vcd ghdl-clean : $(GHDL_CMD) --clean --workdir=simu
to use it, just write :
$ make ghdl-compile
to compile, then:
$ make ghdl-run
to run the design, then:
$ make ghdl-view
to launch gtkwave and visualize the results.
Syntesis, place & route
GUI installation
To synthesize the design it is mandatory to use Xilinx tools (It's not exactly true, others tools can be used for synthesize like Mentor tools, but at the end to make the bitstream Xilinx tools are necessary), fortunately Xilinx provide his webpack for linux here (you have to register). You "just" have to download (1.7Go) it.
Before launching the installer, some packages are necessary :
sudo apt-get install libmotif3 libxp6 libcurl3 portmap
Then launch the installer
./Webpack_full.sh
To launch the floorplanner, DISPLAY has to be change :
export DISPLAY=:0
After this installation, ise can be found in the directory $(Xilinx_root_dir)/bin/lin. To avoid retype export, a little script launch_ise.sh can be made in bin/lin/ directory:
#!/bin/bash export DISPLAY=:0 ~/Xilinx92i/bin/lin/ise
Then make launch click :
There is a good tutorial on harded.free.fr.
Using Xilinx tools in command line
See Using Xilinx Webpack-8.1i on grml Linux in scripted mode, without GUI for an introduction.
First of all, library files has to be copied in library directory :
sudo -s mkdir /usr/local/lib/xilinx/ cp Xilinx_directory/bin/lin/*.so /usr/local/lib/xilinx/ echo /usr/local/lib/xilinx >> /etc/ld.so.conf ldconfig
Then modify your .bashrc adding at the end:
PLATFORM=lin XILINX=Xilinx_directory export XILINX PATH=Xilinx_directory/bin/lin:$PATH export PATH
Then ise can be used in command line (xst, ngdbuild, map, bit,...). To avoid typing very long commands it can be a good idea to use a Makefile, xess.com provide a full Makefile to do this and a basic Makefile for simulation and synthesis can be found below :
# Makefile for VHDL synthesis and simulation # version 1.0 # Fabien Marteau # project name PROJECT=bus_led_top # vhdl files FILES = src/bus_led.vhd src/bus_led_top.vhd # pin configuration UCF_FILE = src/bus_led.ucf # Synthesis constraints file XCF_FILE = # testbench SIMTOP = led_top_tb SIMFILES = ../apf_pkg/apf_test_pkg.vhd testbench/led_top_tb.vhd # Simu break condition GHDL_SIM_OPT = --assert-level=error #GHDL_SIM_OPT = --stop-time=500ns # FPGA options PART = xc3s200-4-tq144 ############################ # Personnals options ############################ CAT=../Xtools/catcolor BRIEF=../Xtools/brief.py ############################ # Xilinx options ############################ BIN = bin WORK = work SYNTH = xst NGDBUILD = ngdbuild MAP = map PAR = par TRACE = trce BITGEN = bitgen ifdef $(XCF_FILE) XCF = -uc $(XCF_FILE)\n endif ############################## # GHDL options ############################## SIMDIR = simu SYNTHFILES = bin/bus_led_ise/netgen/synthesis GHDL_CMD = ghdl GHDL_FLAGS = --ieee=synopsys --warn-no-vital-generic #GHDL_FLAGS = --ieee=synopsys -P~/Xilinx92i/coregen/ip/xilinx/primary/com/xilinx/ip/unisim --warn-no-vital-generic VIEW_CMD = /usr/bin/gtkwave OBJS_FILES = $(patsubst %.vhd, %.o, $(notdir $(FILES)) ) OBJS_SIMFILES = $(patsubst %.vhd, %.o, $(notdir $(SIMFILES)) ) ################################# # Synthesis with xst ################################# messages : bit $(BRIEF) $(BIN)/$(PROJECT) bit : $(BIN)/$(PROJECT).ncd trace -$(BITGEN) -intstyle xflow -w \ -g DebugBitstream:No \ -g Binary:no \ -g CRC:Enable \ -g ConfigRate:6 \ -g CclkPin:PullUp \ -g M0Pin:PullUp \ -g M1Pin:PullUp \ -g M2Pin:PullUp \ -g ProgPin:PullUp \ -g DonePin:PullUp \ -g TckPin:PullUp \ -g TdiPin:PullUp \ -g TdoPin:PullUp \ -g TmsPin:PullUp \ -g UnusedPin:PullDown \ -g UserID:0xFFFFFFFF \ -g DCMShutdown:Disable \ -g DCIUpdateMode:AsRequired \ -g StartUpClk:CClk \ -g DONE_cycle:4 \ -g GTS_cycle:5 \ -g GWE_cycle:6 \ -g LCK_cycle:NoWait \ -g Match_cycle:Auto \ -g Security:None \ -g DonePipe:No \ -g DriveDone:No \ $(BIN)/$(PROJECT).ncd > $(BIN)/$(PROJECT).bitlog $(CAT) $(BIN)/$(PROJECT).bitlog cp $(BIN)/$(PROJECT).bit /tftpboot/ trace: $(BIN)/$(PROJECT).ncd $(BIN)/$(PROJECT).pcf -$(TRACE) -intstyle xflow -e 3 -l 3 -s 5 -xml $(BIN)/$(PROJECT) $(BIN)/$(PROJECT).ncd -o $(BIN)/$(PROJECT).twr $(BIN)/$(PROJECT).pcf > $(BIN)/$(PROJECT).tracelog $(CAT) $(BIN)/$(PROJECT).tracelog $(BIN)/$(PROJECT).ncd : par par : $(BIN)/$(PROJECT)_map.ncd $(BIN)/$(PROJECT).pcf - sh -c 'pid=$$$$; $(PAR) -w -intstyle xflow -ol std -t 1 $(BIN)/$(PROJECT)_map.ncd $(BIN)/$(PROJECT).ncd $(BIN)/$(PROJECT).pcf | (sed "/^PAR done/q";kill $$pid)' > $(BIN)/$(PROJECT).parlog $(CAT) $(BIN)/$(PROJECT).parlog - killall -9 par $(BIN)/$(PROJECT).pcf $(BIN)/$(PROJECT)_map.ncd : map map : $(BIN)/$(PROJECT).ngd - sh -c 'pid=$$$$ ; $(MAP) -intstyle xflow -p $(PART) -cm area -pr b -k 4 -c 100 -o $(BIN)/$(PROJECT)_map.ncd $(BIN)/$(PROJECT).ngd $(BIN)/$(PROJECT).pcf | (sed "/^See MAP report file/q" ; kill $$pid ) ' > $(BIN)/$(PROJECT).maplog $(CAT) $(BIN)/$(PROJECT).maplog - killall -9 map $(BIN)/$(PROJECT).ngd : ngdbuild ngdbuild : $(BIN)/$(PROJECT).ngr $(BIN)/$(PROJECT).ngc $(BIN)/$(PROJECT).lso -$(NGDBUILD) -intstyle xflow -dd _ngo -nt timestamp -p $(PART) $(BIN)/$(PROJECT).ngc $(BIN)/$(PROJECT).ngd -uc $(UCF_FILE) > $(BIN)/$(PROJECT).ngdlog $(CAT) $(BIN)/$(PROJECT).ngdlog $(BIN)/$(PROJECT).ngc $(BIN)/$(PROJECT).ngr $(BIN)/$(PROJECT).lso : synthesis synthesis : $(BIN)/$(PROJECT).prj $(BIN)/$(PROJECT).xst $(SYNTH) -ifn $(BIN)/$(PROJECT).xst -ofn $(BIN)/$(PROJECT).log \ | sed "s/^ERROR/�[01\;31mERROR�[00m/"\ | sed "s/^WARNING/�[01\;33mWARNING�[00m/"\ | sed "s/^INFO/�[01\;32mINFO�[0m/" $(BIN)/$(PROJECT).xst $(BIN)/$(PROJECT).prj : @mkdir -p $(BIN) @touch $(BIN)/$(PROJECT); @for f in $(FILES); do \ echo vhdl $(WORK) \"$$f\" >> $(BIN)/$(PROJECT).prj;\ done @echo work > $(BIN)/$(PROJECT).lso @mkdir -p ./bin/xst/projnav.tmp @echo " \ set -tmpdir "./bin/xst/projnav.tmp" \n\ set -xsthdpdir "./bin/xst" \n\ run \n\ -ifn $(BIN)/$(PROJECT).prj \n\ -ifmt mixed \n\ -ofn $(BIN)/$(PROJECT) \n\ -ofmt NGC \n\ -p $(PART) \n\ -top $(PROJECT) \n\ -opt_mode Speed \n\ -opt_level 1 \n\ $(XCF)\ -iuc NO \n\ -lso $(BIN)/$(PROJECT).lso \n\ -keep_hierarchy NO \n\ -rtlview Yes \n\ -glob_opt AllClockNets \n\ -read_cores YES \n\ -write_timing_constraints NO \n\ -cross_clock_analysis NO \n\ -hierarchy_separator / \n\ -bus_delimiter <> \n\ -case maintain \n\ -slice_utilization_ratio 100 \n\ -bram_utilization_ratio 100 \n\ -verilog2001 YES \n\ -fsm_extract YES -fsm_encoding Auto \n\ -safe_implementation No \n\ -fsm_style lut \n\ -ram_extract Yes \n\ -ram_style Auto \n\ -rom_extract Yes \n\ -mux_style Auto \n\ -decoder_extract YES \n\ -priority_extract YES \n\ -shreg_extract YES \n\ -shift_extract YES \n\ -xor_collapse YES \n\ -rom_style Auto \n\ -auto_bram_packing NO \n\ -mux_extract YES \n\ -resource_sharing YES \n\ -async_to_sync NO \n\ -mult_style auto \n\ -iobuf YES \n\ -max_fanout 500 \n\ -bufg 8 \n\ -register_duplication YES \n\ -register_balancing No \n\ -slice_packing YES \n\ -optimize_primitives NO \n\ -use_clock_enable Yes \n\ -use_sync_set Yes \n\ -use_sync_reset Yes \n\ -iob auto \n\ -equivalent_register_removal YES \n\ -slice_utilization_ratio_maxmargin 5\n\ " >> $(BIN)/$(PROJECT).xst clean : rm -rf $(BIN) ######################## # Simulation with GHDL ######################## ghdl-compil : mkdir -p simu $(GHDL_CMD) -i $(GHDL_FLAGS) --workdir=simu --work=work $(SIMFILES) $(FILES) $(GHDL_CMD) -m $(GHDL_FLAGS) --workdir=simu --work=work $(SIMTOP) @mv $(SIMTOP) simu/$(SIMTOP) #TODO: make it working ! ghdl-simsynth : $(GHDL_CMD) -i $(GHDL_FLAGS) --workdir=simu --work=work $(SYNTHFILES) $(SIMFILES) $(GHDL_CMD) -m $(GHDL_FLAGS) --workdir=simu --work=work $(SIMTOP) @mv $(SIMTOP) simu/$(SIMTOP) ghdl-run : @$(SIMDIR)/$(SIMTOP) $(GHDL_SIM_OPT) --vcdgz=$(SIMDIR)/$(SIMTOP).vcdgz ghdl-view: gunzip --stdout $(SIMDIR)/$(SIMTOP).vcdgz | $(VIEW_CMD) --vcd ghdl-clean : $(GHDL_CMD) --clean --workdir=simu