Overview

This tutorial covers how to get started with the gHDL simulator, using a simple counter example.

Software

This tutorial uses the following software and versions, but should work with out any problems on both older an newer versions:

Gedit 2.28, Text editor,
gHDL 0.28, VHDL compiler and simulator
GTKWave 3.2.0, Waveform viewer
make, to run helper script (optional)

To install the software needed for this tutorial click the box below or see the Getting Started page.

Install the software for this Tutorial

ghdl, gtkwave,make

Setup

For this tutorial we will use Gedit, the default text editor in Gnome, to edit the VHDL code. Ubuntu has a number of different text editors available as shown on the HDL Editors page.

To make Gedit easier to use we will use a number of plugins. Plugins are small extensions to Gedit to allow Gedit to do some extra tricks. Alternatively use external programs instead of the plugins if desired.

Start Gedit (Accessories -> Text Editor) and select Edit -> Preferences and click the Plugins Tab. Click the box next to Code Comment, File Browser Pane and Embedded Terminal and Code Comment to active these plugins.

In the Left side panel of Gedit click the File Browser tab, this usually has a filing cabinet icon. Use the file browser (or if you wish use another file browser) to create a directory for this project and create three sub-directories: src, testbench and simulation.

To make using GHDL easier to use copy the following Makefile into Gedit and save it to the project directory and as a file named Makefile.

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
43
# vhdl files
FILES = src/*
VHDLEX = .vhd
 
# testbench
TESTBENCHPATH = testbench/${TESTBENCH}$(VHDLEX)
 
#GHDL CONFIG
GHDL_CMD = ghdl
GHDL_FLAGS  = --ieee=synopsys --warn-no-vital-generic
 
SIMDIR = simulation
# Simulation break condition
#GHDL_SIM_OPT = --assert-level=error
GHDL_SIM_OPT = --stop-time=500ns
 
WAVEFORM_VIEWER = gtkwave
 
all: compile run view
 
new :
	echo "Setting up project ${PROJECT}"
	mkdir src testbench simulation	
 
compile :
ifeq ($(strip $(TESTBENCH)),)
		@echo "TESTBENCH not set. Use TESTBENCH=value to set it."
		@exit 2
endif                                                                                             
 
	mkdir -p simulation
	$(GHDL_CMD) -i $(GHDL_FLAGS) --workdir=simulation --work=work $(TESTBENCHPATH) $(FILES)
	$(GHDL_CMD) -m  $(GHDL_FLAGS) --workdir=simulation --work=work $(TESTBENCH)
	@mv $(TESTBENCH) simulation/$(TESTBENCH)                                                                                
 
run :
	@$(SIMDIR)/$(TESTBENCH) $(GHDL_SIM_OPT) --vcdgz=$(SIMDIR)/$(TESTBENCH).vcdgz                                      
 
view :
	gunzip --stdout $(SIMDIR)/$(TESTBENCH).vcdgz | $(WAVEFORM_VIEWER) --vcd                                               
 
clean :
	$(GHDL_CMD) --clean --workdir=simulation

Writing Code

Create a new file and save it in the the src directory as counter.vhd in and copy the following VHDL code into the file and save the file. This file describes a simple 8-bit counter with a up / down selection, input, output and reset.

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
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
 
entity up_down_counter is
port (
     cout    :out std_logic_vector (7 downto 0);
     up_down :in  std_logic;               -- up_down control for counter
     clk     :in  std_logic;                   -- Input clock
     reset   :in  std_logic                   -- Input reset
   );
end entity;
 
architecture rtl of up_down_counter is
	signal count :std_logic_vector (7 downto 0);
	begin
		process (clk, reset) begin
			if (reset = '1') then
				count <= (others=>'0');
			elsif (rising_edge(clk)) then
				if (up_down = '1') then
					count <= count + 1;
				else
					count <= count - 1;
				end if;
			end if;
		end process;
		cout <= count;
end architecture;

Create another new file and save it in the testbench directory as counter_tb.vhd and copy the code below into the file and save the file. This file is a simple test bench to test the counter.

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
43
44
45
46
47
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
 
entity counter_tb is
end entity;
 
architecture TB of counter_tb is
 
    component up_down_counter
    port( cout:		out std_logic_vector(7 downto 0);
	    up_down:	in std_logic;
	    reset:		in std_logic;
	    clk:		in std_logic
 
    );
    end component;
 
    signal cout:    std_logic_vector(7 downto 0);
    signal up_down: std_logic;
    signal reset:   std_logic;
    signal clk:     std_logic;
 
begin
 
    dut: up_down_counter port map (cout, up_down, reset, clk);
 
    process
    begin
		clk <= '0';
		wait for 5 ns;
		clk <= '1';
		wait for 5 ns;
    end process;
 
	process
	begin
		up_down <= '1';
		reset <= '1';
		wait for 10 ns;
		reset <= '0';
		wait for 100 ns;
 
		up_down <= '0';
		wait for 100 ns;
	end process;
end;

Simulation and Viewing the result

Now we have created a simple counter and testbench it is time to simulate the design.
Select the terminal tab at the bottom of the Gedit window. To simulate the design first change to the top level project directory using the cd command, as shown below.

cd /path/to/project/dir

To simulate a design with gHDL three steps are needed, these are included in the Makefile given above, shown below, as we are using the make file don’t run GHDL directly use the make commands shown below.

ghdl -i  FILES
ghdl -m  TESTBENCH_NAME
ghdl -r TESTBENCH_NAME

First GHDL is ran with the -i option and a list of all files in the design. This analysis all units in the design in the correct order, and will check for and errors in the VHDL code. Next GHDL is ran with the -m option and the name of the top unit which will usually be a testbench. This analysis and elaborates the design and creates an executable to run the simulation. The simulation is ran executing ghdl with the -r option.

The above flow is included in the Makefile to make it easier to simulate designs and view the result, as shown below. The first line runs the Ghdl twice once with -i and then with -m, the second line runs Ghdl -r and the final line shows results in the waveform viewer GTKWave.

make compile TESTBENCH=counter_tb
make run TESTBENCH=counter_tb
make view TESTBENCH=counter_tb

All three steps above can be ran with the command

make all TESTBENCH=counter_tb
The Makefile is designed to make your life easier. But to do this it makes some assumptions, which are

  • The design files are in a sub-directory src.
  • The testbench is in a sub-directory called testbench.
  • The testbench entity has the same name as the testbench file.

These assumptions are met in the above example, so if you have done everything right you should have no trouble.

After running the above commands GTKWave should open. To view signals from the design select the design from the top left side pane and select a signal from the bottom left side pane and click Insert at the bottom left of the GTKWave window.

Further Information

For more information on using GHDL and GTKWave see the project websites.

http://ghdl.free.fr/
http://gtkwave.sourceforge.net/