VHDL project template for open-source projects
written on November 18, 2020
categories: engineering
VHDL development is often associated with old and bloated (mostly proprietary) software, installations that take forever and take up a huge amount of space... what if there were a simple open-source alternative?
I do work on some VHDL projects (like this one, or this one) from time to time, so I wanted a simple, Makefile-based project template I could build upon, which would be supported at least on Linux and macOS, and which would be easy to install and setup and yet powerful and scalable. So I rolled my own VHDL open-source project template. In this blogpost I'd like to explore how it works and give a concrete example of building something with it.
It depends on GHDL and GTKWave (installation instructions for Linux and macOS are provided in the repo's README). GTKWave actually isn't strictly required, as all building/testing can be achieved with GHDL alone, but it's fun to have and it sometimes helps to visually debug an IP using a digital timing diagram.
Anyway, let's say we want to build a simple 3-input AND
gate IP. We first have to
clone the template repo:
$ git clone https://github.com/kokkonisd/vhdl-template/
We can then rename the folder to reflect our actual project name, and get rid of all the git-related stuff we don't need:
$ mv vhdl-template/ my-awesome-ip/
$ cd my-awesome-ip/
$ rm -rf .git/ LICENSE README.md
As you can see, the project template is laid out as follows:
$ tree
.
├── Makefile
├── simu
├── src
└── tb
3 directories, 1 file
There are three main folders: src
, which contains the VHDL sources (like MyIP.vhdl
),
tb
which contains the test benches associated with the sources (like MyIP_tb.vhdl
)
and finally simu
, which contains the simulation files generated based on the test
benches. These files can then be opened by GTKWave, but we'll get to that.
Let's start by building a simple 2-input AND
gate:
src/SimpleAndGate.vhdl
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
|
Very simple, just has two inputs and one output (all std_logic
), and the output is
equal to the AND
ing of the two inputs. Let's try to compile this IP by running make
:
$ make
[Compiling `SimpleAndGate.vhdl` ...]
ghdl -s --workdir=build src/SimpleAndGate.vhdl
ghdl -a --workdir=build src/SimpleAndGate.vhdl
No errors! Our simple IP is working. The first command checks the syntax of the .vhdl
file, and the second one analyzes it. It should now be ready to be used by other IPs.
Speaking of which, let's code a 3-input AND
gate IP based on the one we just
implemented:
src/AwesomeTripleAndGate.vhdl
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
|
Let's also write a simple test bench we can use to verify that it's working. Note that
the test bench file must have exactly the same name as the source IP file, plus
"_tb". So in this case, it will be tb/AwesomeTripleAndGate_tb.vhdl
:
tb/AwesomeTripleAndGate_tb.vhdl
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
|
Once again, very simple: we set up an entity to test, and then we start a "test"
process, where we set the inputs of the triple AND
gate to various values and assert
the output, triggering an error if it's incorrect.
Let's make
and see if this whole thing works:
$ make
[Compiling `AwesomeTripleAndGate.vhdl` & `AwesomeTripleAndGate_tb.vhdl` ...]
ghdl -s --workdir=build src/AwesomeTripleAndGate.vhdl tb/AwesomeTripleAndGate_tb.vhdl
src/AwesomeTripleAndGate.vhdl:18:23:error: unit "simpleandgate" not found in library "work"
src/AwesomeTripleAndGate.vhdl:19:23:error: unit "simpleandgate" not found in library "work"
make: *** [AwesomeTripleAndGate] Error 1
Whoops, that doesn't seem right. What happened? Well, I named the IPs on purpose, so that the second one would get picked up by the Makefile before the first one. That way, it tries to compile the second IP without first compiling its dependency. The simplest way to fix this is to declare the dependency in the Makefile, by replacing this:
Makefile
# Dependencies
# <my entity>: <my other entity>
with this:
Makefile
# Dependencies
AwesomeTripleAndGate: SimpleAndGate
So now that the dependencies issue is fixed, let's re-run make
:
$ make
[Compiling `SimpleAndGate.vhdl` ...]
ghdl -s --workdir=build src/SimpleAndGate.vhdl
ghdl -a --workdir=build src/SimpleAndGate.vhdl
[Compiling `AwesomeTripleAndGate.vhdl` & `AwesomeTripleAndGate_tb.vhdl` ...]
ghdl -s --workdir=build src/AwesomeTripleAndGate.vhdl tb/AwesomeTripleAndGate_tb.vhdl
ghdl -a --workdir=build src/AwesomeTripleAndGate.vhdl tb/AwesomeTripleAndGate_tb.vhdl
ghdl -e --workdir=build -o build/AwesomeTripleAndGate_tb AwesomeTripleAndGate_tb
[Running simulation of `AwesomeTripleAndGate_tb` ...]
ghdl:info: simulation stopped by --stop-time @100ns
[`AwesomeTripleAndGate` PASS]
Now the SimpleAndGate
gets built first, and then when it's AwesomeTripleAndGate
's
turn to be built, it can find the reference to SimpleAndGate
and build successfully.
Just to properly test out all of the features of this Makefile, we can open the resulting simulation in GTKWave, by running:
$ make simu
This will open up GTKWave and will allow us to visually check the test bench simulation:
And that's it! You can now build, debug and run automated tests using this lightweight VHDL project template.