VHDL DISCUSSION

How should I generate a clock and stop the simulation in a VHDL testbench?

Started by adiono VHDL testbenchclock generationwait statementstd.env.stopassert and report
5 replies 248 views 6 participants
Latest activity · 30 Sep 2026

How should I generate a clock and stop the simulation in a VHDL testbench?

adiono VHDL Forum
#1

I am writing my first VHDL testbench. My clock line clk <= not clk after 5 ns; leaves clk at 'U' for the whole run. After I fixed that by trial and error, the simulation never ends, and my stimulus process seems to start again from the beginning after its last statement.

What is the correct way to generate a clock, apply stimulus in step with it, check results, and make the simulation stop by itself when the test is finished?

Community replies 5

Re: How should I generate a clock and stop the simulation in a VHDL testbench?

#2

The clock stays at 'U' because a std_logic signal without an initial value starts as 'U', and not 'U' is 'U', so the assignment keeps scheduling the same value. Give the signal a starting value in its declaration: signal clk : std_logic := '0';. Then clk <= not clk after 5 ns; as a concurrent statement toggles every 5 ns, a 10 ns period, which is 100 MHz.

Define the period once, constant T : time := 10 ns;, and write after T / 2, so that stimulus timing can be expressed with the same constant.

Re: How should I generate a clock and stop the simulation in a VHDL testbench?

#3

Your stimulus restarts because a process is an endless loop: after the last statement, execution continues from the first. A testbench stimulus process must end with a bare wait;, which suspends it forever.

Inside it, synchronise to the clock rather than to absolute times: wait until rising_edge(clk);, then assign the inputs. Because signal assignments take effect a delta cycle after the edge, the design's registers sample the old values on that edge and the new ones on the next, with no race. For a reset, something like rst <= '1'; wait for 3 * T; wait until rising_edge(clk); rst <= '0'; gives a clean synchronous release.

Re: How should I generate a clock and stop the simulation in a VHDL testbench?

#4

The simulator stops by itself when no more events are scheduled, and a free-running clock schedules events forever. There are two usual solutions. With VHDL-2008, call std.env.stop; or std.env.finish; at the end of the stimulus process. Without it, gate the clock with a flag: declare signal done : boolean := false;, generate the clock in a process with while not done loop clk <= '0'; wait for T / 2; clk <= '1'; wait for T / 2; end loop; wait;, and set done <= true; when the test ends. Once the clock stops, the event queue empties and the run ends cleanly.

The old trick of assert false report "end of test" severity failure; also stops the run, but it is reported as a failure, which confuses scripts that look at the exit status.

Re: How should I generate a clock and stop the simulation in a VHDL testbench?

#5

Make the testbench check results itself instead of relying on reading waveforms. After the clock edge on which an output should be valid, write assert dout = x"3C" report "dout mismatch" severity error;. The report text appears in the transcript together with the simulation time. In VHDL-2008, to_hstring(dout) lets you include the actual value in the message.

A testbench entity has no ports, and constructs such as after, wait for and file I/O are fine there because it is never synthesised. Keep the design under test free of them.

Re: How should I generate a clock and stop the simulation in a VHDL testbench?

#6

As tests grow, put repeated sequences in procedures, for example one that writes a byte to the design's bus and waits for the acknowledge, and call it with different data. That keeps the stimulus readable and the timing in one place. If you end the run with std.env.stop, add a watchdog process as well: wait for 1 ms; report "timeout" severity failure; ends a run in which the design hangs and the normal end is never reached.

Finally, initialise every testbench signal that drives a design input. An input left at 'U' propagates through the logic as 'U' or 'X', and the resulting waveform looks like a design fault when it is really a testbench omission.

TEP COMMUNITY