Using GHDL to simulate VHDL16. Oct '14

Introduction

Open-source tools for VHDL seem to be lacking, I am mainly using GHDL 1 to analyze and simulate VHDL design. Verilog on the other hand has a lot of open-source tools available 2 3. Note that VHDL is case insensitive, at least for modern compilers. Personally I think it's nice to have your code yelling at you therefore I default to lowercase. Consistency throughout any software project is of course the most important aspect.

Installing GHDL

I have used packages built by Joris van Rantwijk to install GHDL on my Debian Wheezy machine 4. These instructions should be double-checked for any other distribution of course:

wget http://sourceforge.net/projects/ghdl-updates/files/Builds/ghdl-0.31/Debian/ghdl_0.31-2wheezy1_amd64.deb
sudo dpkg -i ghdl_0.31-2wheezy1_amd64.deb

Analyzing design

I think it's a good convention to keep the entity name synchronized with the filename and also in lower case. GHDL also seems to look up components by the filename. So for example following entity should be saved to full_adder.vhd:

library ieee;
use ieee.std_logic_1164.all;

entity full_adder is
    port (
        a  : in  std_logic;
        b  : in  std_logic;
        ci : in  std_logic;
        s  : out std_logic;
        co : out std_logic);
end;

architecture behavioral of full_adder is
begin
    s <= a xor b xor ci;
    co <= (a and b) or ((a xor b) and ci);
end;

To compile binary object full_adder.o from a VHDL source file full_adder.vhd use the -a analyze command-line option:

ghdl -a full_adder.vhd

Now these object files can be referred by other entities via component declaration.

Elaborating design

Consider following testbench source code in file full_adder_testbench.vhd:

library ieee;
use ieee.std_logic_1164.all;

entity full_adder_testbench is
end full_adder_testbench;

architecture behavior of full_adder_testbench is
    component full_adder is
        port (
            a  : in  std_logic;
            b  : in  std_logic;
            ci : in  std_logic;
            s  : out std_logic;
            co : out std_logic);
    end component;
    signal input  : std_logic_vector(2 downto 0);
    signal output : std_logic_vector(1 downto 0);
begin
    uut: full_adder port map (
        a => input(0),
        b => input(1),
        ci => input(2),
        s => output(0),
        co => output(1)
    );

    stim_proc: process
    begin
        input <= "000"; wait for 10 ns; assert output = "00" report "0+0+0 failed";
        input <= "001"; wait for 10 ns; assert output = "01" report "0+0+1 failed";
        input <= "010"; wait for 10 ns; assert output = "01" report "0+1+0 failed";
        input <= "100"; wait for 10 ns; assert output = "01" report "1+0+0 failed";
        input <= "011"; wait for 10 ns; assert output = "10" report "0+1+1 failed";
        input <= "110"; wait for 10 ns; assert output = "10" report "1+1+0 failed";
        input <= "111"; wait for 10 ns; assert output = "11" report "1+1+1 failed";
        report "Full adder testbench finished";
        wait;
    end process;
end;

The object file for testbench must be compiled aswell:

ghdl -a full_adder_testbench.vhd

Running GHDL with the elaborate option -e will produce a binary and link all the related entities to the binary. Note that object file full_adder_testbench.o here is referred by the entity name full_adder_testbench:

ghdl -e full_adder_testbench

Now you have binary ready to go:

./full_adder_testbench

Which should output:

full_adder_testbench.vhd:36:9:@70ns:(report note): Full adder testbench finished

Putting it all together

Makefiles help out tracing changes to modified files:

GHDL=ghdl
GHDLFLAGS=
MODULES=\
    carry_ripple_adder.o \
    alu.o \
    full_adder.o \
    alu_testbench \
    carry_ripple_adder_testbench \
    full_adder_testbench


test: $(MODULES)
        ./full_adder_testbench --vcd=full_adder_testbench.vcd
        ./carry_ripple_adder_testbench --vcd=carry_ripple_adder_testbench.vcd
        ./alu_testbench --vcd=alu_testbench.vcd

# Binary depends on the object file
%: %.o
        $(GHDL) -e $(GHDLFLAGS) $@

# Object file depends on source
%.o: %.vhd
        $(GHDL) -a $(GHDLFLAGS) $<

clean:
        echo "Cleaning up..."
        rm -f *.o *_testbench full_adder carry_ripple_adder work*.cf e*.lst

Place the file as Makefile next to VHDL files. In this case issuing simply make in that directory would compile all necessary files and execute testbenches.

1

https://gna.org/projects/ghdl/

2

http://iverilog.icarus.com/

3

http://www.veripool.org/wiki/verilator

4

http://jorisvr.nl/ghdl_debian.html

GCC VHDL KTH GHDL