This page is meant as a (hopefully) short tutorial to using hdlmake
for both synthesis and simulation. For a first-time user, it is
recommended to go through the whole tutorial step by step. This will
show you (based on a reference project):
how to create manifest files to ensure design modularity
how to create simulation manifests
create manifests for local synthesis
how to use IP cores uploaded on a version control system (in our
example we use both Git and SVN).
Once you've done this, you can migrate to your own project(s), using
this page and the rest of the documentation as a reference. You may skip
directly to the Simulation or
Synthesis sections, for quick reference on
each topic. The summary at the end provides
the steps you need to take.
For the moment, this tutorial is written for Linux systems, and for
Xilinx FPGAs using Xilinx ISE. While hdlmake does support Altera
tools, a tutorial on this is deferred for later.
Before we begin, a few words on the test system. This can be summarized
PC running Ubuntu 12.04 Precise Pangolin;
Linux kernel: 3.2.0-31-generic-pae;
Xilinx ISE v14.2;
hdlmake built from the latest (as of 2012-04-10) master
There is no need to build hdlmake. It is entirely written in Python and
the code gets interpreted on the fly. To get the code you have two
choices: you might clone the repository, which contains the most recent
changes (more features, more bugs too...) or download a frozen version
in a form of a "binary" file.
Downloading the compiled executable
For downloading the compiled executable, click
here and choose one of
the files without extension. Download to a location of choice, and
you're almost ready to use it! You can jump directly to the final
Cloning the repository
If you prefer to get the source code, you need to have the popular Git
version control system installed on your machine; if you don't, this
offers details on how you can configure Git to clone our repositories.
Assuming you have Git installed, running the following will clone
(download all files in the) repository to a folder named hdlmake under
your /home/user_name/ folder:
Now you're almost ready to go. You can run hdlmake by changing directory
to a desired location and running
$ python path/to/hdlmake/hdlmake
The sample project
For this tutorial, we have a sample project called play. This is a
design which lights some LEDs on the SPEC board's front panel and can be
used to play with controlling registers from a PC using the SPEC driver
and (optionally) PTS (Production Test
Suite). You can see a simplified
block diagram of the design
It contains a number of design blocks, each defined in a separate VHDL
file with the name of the block. The folder hierarchy for the project is
as presented below:
The relevant folders in our case are:
hdl/, where all source files are held; the tb/ folder contains
testbenches for the design, and the design/ folder contains the
rest of the files relevant to the design;
sim/ is the folder where files relevant to the simulation part of
the design, such as Makefiles for simulation, simulation scripts,
etc., are stored;
syn/ is the folder where files relevant to design synthesis are
stored. The folder is also where the ISE project file is created.
And that is about as much detail about the sample project as is relevant
for the purpose of this tutorial. More details about the sample project
can be found in the project description .pdf, under play/doc/.
In order to download the design files for the tutorial, clone the
project repository by running the following command in your
$ git clone --depth=1 -b play git:https://www.ohwr.org/fmc-projects/fmc-adc-100m14b4cha.git
The command creates a new folder in your current folder and downloads
all files from the play branch of the fmc-adc-100m14b4cha OHWR
repository to this new folder. The output of this command should be
You should now have the project files, nicely stored following the
folder structure we just described, under a new folder called play.
If you don't, you probably don't have git installed correctly. Check
for more information.
Now let's go on and generate a makefile for simulation!
This part of the tutorial shows you how to run hdlmake for simulation.
Note that hdlmake does not handle creation of simulation scripts, nor
does it run the simulation tool for you; it simply creates all settings
necessary to run simulation. Therefore, you will need to write your own
simulation scripts and run Modelsim to run simulation. hdlmake will
try to detect which version of modelsim you're running. Make sure that
your modelsim executable is in the PATH before running hdlmake.
In our case, let's say we want to see how the design behaves with only
the led_ctrl, addr_dec and irq_controller blocks in the design.
Remember that the HDL files for these components are located under
(assuming you are in the play/ folder) hdl/design/. We need to
create a few very simple Python scripts which tell the tool where to
look for files and what action it should perform. Let's see how this is
Design file manifests
First, create a file called Manifest.py, containing the following
lines of Python code:
files = [ "led_ctrl.vhd", "irq_controller_regs.vhd", # a sub-module of irq_controller "irq_controller.vhd", "addr_dec.vhd",]
When hdlmake reads this manifest, it will know that the design files
to look for under the current folder are the ones stated in the files
Next, create another Manifest.py, this time under hdl/tb/, with the
As before, the files variable tells hldmake that within this
folder, it should look for the file testbench.vhd and that it should
for further modules (design files) under ../design/ (which as you
might tell, is play/hdl/design/)
Now, cd to the play/sim/ folder and create yet another Manifest.py
here, with the following contents:
Again, we see the modules variable, which tells it to look for modules
under ../hdl/tb/. Additionally, the manifest tells the tool that the
action to be performed is simulation, the target is xilinx and the
simulation tool is modelsim.
Okay, now you should be able to run the tool and generate a makefile for
From the play/sim/ folder, run (normal outputs shown under each
$ hdlmakeINFO: Running automatic flowINFO: Generating makefile for simulation.$ makecp /opt/modelsim_10.0d/modeltech/modelsim.ini .(vlib work && vmap -modelsimini modelsim.ini work && touch work/.work )|| rm -rf work Reading modelsim.ini"work" maps to directory ./work. (Default mapping)vcom -quiet -modelsimini modelsim.ini -work work ../hdl/tb/testbench.vhd vcom -quiet -modelsimini modelsim.ini -work work ../hdl/design/led_ctrl.vhd vcom -quiet -modelsimini modelsim.ini -work work ../hdl/design/irq_controller_regs.vhd vcom -quiet -modelsimini modelsim.ini -work work ../hdl/design/irq_controller.vhd vcom -quiet -modelsimini modelsim.ini -work work ../hdl/design/addr_dec.vhd
Let's see what happened on the previous command. When you run hdlmake
with no arguments, the tool parses the manifest under the current
folder. Since the manifest told it to look for modules in ../hdl/tb/,
the tool goes and parses the manifest there. Here, it is told to add the
file testbench.vhd and to look for additional modules under
../design/. Finally, by parsing the play/hdl/design/Manifest.py
file, hdlmake can add the final files needed for simulation. In a nice
visual manner, here's how it
Assuming you've followed the steps up to here and you've written your
simulation script, you should be able to run Modelsim now to simulate
this simple design. From play/sim, run:
and in the Modelsim command line (using the provided scripts):
should bring up a window similar to
If it does, and all of the signals have definite values (i.e., no 'X'-s,
or 'U'-s), then congratulations, you have just performed a working
Okay, so now that you've simulated your design and are sure it works
properly, you can proceed to synthesis. Using hdlmake for synthesis is
as easy as using it for simulation. All you needed is a synthesis
manifest (assuming the manifests for design files are already there),
and you are good to go. Synthesis manifests tell the tool how to prepare
your project file: what FPGA model to use, what package and speed grade
it has, along with some additional information.
Considering our example project, cd to the play/hdl/design/ folder
and edit Manifest.py so that it contains the following:
You can see a number of extra things as opposed to the simulation case.
First, we have more design files in the current folder (you might have
noticed it when you cloned the design repository). Next, this manifest
also contains a modules variable. This variable tells hdlmake that
we are using some IP cores (in our case, the GN4124 interface core, and
some other cores it depends on) which are stored on version control
systems using both Git and SVN servers. Last, there is a fetchto
variable; this tells hdlmake where to store the files retrieved from
the repository, in case the files are not present.
Now, you should create a manifest in the synthesis folder, telling
hdlmake where to look for modules and what it should do. In our case,
we cd to the synthesis folder (play/syn/) and create the following
The following extra variables appear in the manifest:
target: informs the tool that the target architecture is from
action: synthesis is to be performed;
syn_device: the FPGA device to perform synthesis for;
syn_grade: the speed grade of the FPGA;
syn_top: the top-level entity for the design;
syn_project: the target ISE project file.
Assuming everything is right up to now, running hdlmake without any
arguments should download the missing files from the repository (note:
this might take quite some time, so get ready for a coffee break),
create a project file and a makefile for synthesis:
$ hdlmakeINFO: Running automatic flowINFO: Fetching needed modules.------------------INFO: Fetching module: git:https://www.ohwr.org/hdl-core-lib/general-cores.git [parent: /home/tstana/Projects/play/hdl/design]INFO: [git] Fetching to /home/tstana/Projects/ip_coresCloning into 'general-cores'...remote: Counting objects: 2144, done.remote: Compressing objects: 100% (1262/1262), done.remote: Total 2144 (delta 1242), reused 1485 (delta 813)Receiving objects: 100% (2144/2144), 6.79 MiB | 7.96 MiB/s, done.Resolving deltas: 100% (1242/1242), done.INFO: The manifest inside /home/tstana/Projects/ip_cores/general-cores/modules/genrams/Manifest.py tried to print something:> [genrams] creating workdir /home/tstana/Projects/ip_cores/general-cores/modules/genrams/coregen_ip> [genrams] copying ISE files...> ------------------INFO: Fetching module: http://svn.ohwr.org/gn4124-core/trunk/hdl/common/rtl [parent: /home/tstana/Projects/play/hdl/design]INFO: [svn] Fetching to /home/tstana/Projects/ip_coresA gn4124-core/trunk/hdl/common/rtl/dummy_ctrl_regs.vhdA gn4124-core/trunk/hdl/common/rtl/dummy_stat_regs.vhdA gn4124-core/trunk/hdl/common/rtl/wb_addr_decoder.vhdA gn4124-core/trunk/hdl/common/rtl/Manifest.pyChecked out revision 195.------------------INFO: Fetching module: http://svn.ohwr.org/gn4124-core/trunk/hdl/gn4124core/rtl [parent: /home/tstana/Projects/play/hdl/design]INFO: [svn] Fetching to /home/tstana/Projects/ip_coresA gn4124-core/trunk/hdl/gn4124core/rtl/dma_controller.vhdA gn4124-core/trunk/hdl/gn4124core/rtl/l2p_arbiter.vhdA gn4124-core/trunk/hdl/gn4124core/rtl/p2l_decode32.vhdA gn4124-core/trunk/hdl/gn4124core/rtl/dma_controller_wb_slave.vhdA gn4124-core/trunk/hdl/gn4124core/rtl/l2p_dma_master.vhdA gn4124-core/trunk/hdl/gn4124core/rtl/p2l_dma_master.vhdA gn4124-core/trunk/hdl/gn4124core/rtl/wbmaster32.vhdA gn4124-core/trunk/hdl/gn4124core/rtl/spartan3[...]Checked out revision 108.INFO: Generating/updating ISE projectINFO: Generating makefile for local synthesis.WARNING: Connection data is not given. Accessing environmental variables in the makefileINFO: Generating makefile for remote synthesis.
As in the simulation case, the tool parses through each manifest that it
is pointed to (via modules variables) and recursively adds files to
the project. When parsing the manifest under play/hdl/design/ and it
encounters the "git" and "svn" keys, hdlmake searches for design
manifests in the folder the fetchto variable points to. If it can find
manifests there, it will continue adding files in a manner similar to
before. Otherwise, hdlmake will try to fetch the repositories listed
in the manifest. In a
Additionally, hdlmake will create an ISE project file and a makefile.
Running make now, the Generate Programming File flow from the
Xilinx ISE tool is run. Before that, one can edit the flow in Xilinx ISE
to adjust for custom settings or steps. The final result of the flow
would be a programming file one can download to the FPGA RAM. (Btw,
you should get ready for another coffee break, since this flow might
take some time as well).
And that's it! That is how you use hdlmake for keeping track of your
project files. A summary of what needs to be done is listed below:
Create one manifest file for each folder where you have design
files. A manifest is a Python script (therefore, following Python
language conventions) defining variables relevant to hdlmake when
it generates your design project. When you run hdlmake, the
manifests get read by the Python interpreter, so if need be, you can
write more advanced Python code in the manifest. A simple manifest
such as those we've shown here will however suffice in most cases.
Splitting design files into folders in a logical manner keeps your
design modular and maintanable. One such design folder is called a
module (in hdlmake parlance), and is indicated via the modules
variable in the manifest; the module variable is a Python
dictionary and the keys can have three different values:
"local": the modules are located on the current machine
"git": the modules are located on a git version control
"svn": the modules are located on a svn version control
Edit the manifest files if you add, remove, or modify any of your
designs. In this case, you should run hdlmake to update your ISE
project file and/or your simulation makefile.
For simulation, create a manifest file in the simulation folder,
where you specify simulation as the action variable of the
For synthesis, create a manifest file in the synthesis folder,
where you specify synthesis as the action variable, along with
the rest of the relevant variables.
Run make in your simulation or synthesis folder to prepare the
design for simulation, or respectively to run the Generate
Programming File flow. This step is not needed; if you are more
comfortable with double-clicking Generate Programming File in
the Project Navigator's flow pane, you are free to do so. Just make
sure you do not switch to automatic compile order in Project
Navigator. If you do, you will lose the settings made by hdlmake.
Running hdlmake with the --list option is a pretty useful way of
checking if your design manifests have been written correctly. The
option runs hdlmake without creating makefiles or fetching anything,
instead it shows you all design files you defined in your manifests. For
example, the following is a sample of a correct output:
If hdlmake had to download some files from the repository, an
#unfetched message would appear under each of the repository links. If
something is however wrong with your manifest(s), hdlmake will exit
with an error and usually tell you where the problem is. You can use
this output to debug your manifests. Running hdlmake --verbose can
also help in debugging what you did wrong in your manifests.