ghdl
ghdl copied to clipboard
gtkwave does not run for the expected time within a testbench
When I run python run.py -g
I am expecting to see the output of my unit test displayed within gtkwave.
Test Bench
LIBRARY vunit_lib;
CONTEXT vunit_lib.vunit_context;
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
LIBRARY src;
USE src.mux_2i_1o;
ENTITY tb_mux_2i_1o IS
GENERIC (runner_cfg : STRING);
END ENTITY;
ARCHITECTURE tb OF tb_mux_2i_1o IS
SIGNAL button : std_logic := 'X';
SIGNAL input_1 : std_logic := '0';
SIGNAL input_2 : std_logic := '1';
SIGNAL output : std_logic;
BEGIN
mux : ENTITY mux_2i_1o PORT MAP (
button => button,
input_1 => input_1,
input_2 => input_2,
output => output
);
main : PROCESS
BEGIN
test_runner_setup(runner, runner_cfg);
WHILE test_suite LOOP
IF run("button press to switch inputs") THEN
button <= '0';
check(output = input_1);
wait for 20 ns;
button <= '1';
wait for 20 ns;
check(output = input_2, "Input did not change when button was pressed");
END IF;
END LOOP;
test_runner_cleanup(runner); -- Simulation ends here
WAIT;
END PROCESS;
END ARCHITECTURE;
As you can see, there are two 20ns waits within the test bench. Which means I am expecting the gtkwave gui to show me a sim for a total of 40ns. But when I run python run.py -g
I get the following output.
Steps to reproduce on Linux desktop environment
cd $HOME
git clone https://github.com/seanybaggins/ben_eaters_8_bit_computer.git
cd ben_eaters_8_bit_computer
docker run --volume="$HOME/.Xauthority:/root/.Xauthority:rw" --volume="$HOME/ben_eaters_8_bit_computer/:$HOME/ben_eaters_8_bit_computer" -w="$HOME/ben_eaters_8_bit_computer" --env="DISPLAY" --net=host ghdl/ext python run.py -g
docker start -a <default name>
I can reproduce. If you add a wait;
statement in the end of your main process (after the last check), 40ns of waveform are shown. However, I don't know if this is because of GHDL, VUnit and/or GtkWave. It would be useful to reproduce it without VUnit.
That's because there are no new signal events after 20ns.
You'd like to see a waveform until 40 ns, but if the simulation goes until time'last (which is not unusual), you will have a very very long waveform).
I agree that the output could be improved, but I haven't yet found the best one.
Fair enough. I guess we can add some note to the docs (in https://ghdl.readthedocs.io/en/latest/using/Simulation.html#cmdoption-ghdl-wave?) so that users are aware. Remembering to end all the sims with some signal event is straightforward.
@eine putting the wait statement just after the check manage to solve my issue. Thank you. Should the ticket remain open until a comment is put into documentation?
I'm glad it worked! Yes, I think we can keep this open until we update the docs.
Hang on. While adding these wait statements do improve the output of the timing diagram, it also causes the unit tests to fail.
Steps to reproduce
cd $HOME
git clone https://github.com/seanybaggins/ben_eaters_8_bit_computer.git
cd ben_eaters_8_bit_computer
git checkout 95c213e668d550416d6683aa18043910816a9b83
docker run --volume="$HOME/.Xauthority:/root/.Xauthority:rw" --volume="$HOME/ben_eaters_8_bit_computer/:$HOME/ben_eaters_8_bit_computer" -w="$HOME/ben_eaters_8_bit_computer" --env="DISPLAY" --net=host ghdl/ext python run.py
docker start -a <default name>
That makes sense, because the simulation does not reach test_runner_cleanup(runner);
. It is related to how VUnit decides whether a test failed. Hence, it is a false negative.
Instead of adding a wait, you can create any dummy signal and do assign it. See, for example, the usage of start
, done
and saved
in https://github.com/VUnit/vunit/blob/master/examples/vhdl/array_axis_vcs/src/test/tb_axis_loop.vhd#L60-L66 So, you would create signal done
, assign it to 0
and set it to 1
when you want to have a last event triggered before closing the sim.
@eine thank you. That was extremely well explained. I now have reliable unit tests and can debug them in gtkwave.