How should I create a clock in a testbench? I already have found one answer, however others on stack overflow have suggested that there are alternative or better ways of achieving this:
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
ENTITY test_tb IS
END test_tb;
ARCHITECTURE behavior OF test_tb IS
COMPONENT test
PORT(clk : IN std_logic;)
END COMPONENT;
signal clk : std_logic := '0';
constant clk_period : time := 1 ns;
BEGIN
uut: test PORT MAP (clk => clk);
-- Clock process definitions( clock with 50% duty cycle is generated here.
clk_process :process
begin
clk <= '0';
wait for clk_period/2; --for 0.5 ns signal is '0'.
clk <= '1';
wait for clk_period/2; --for next 0.5 ns signal is '1'.
end process;
END;
(source here)
Concurrent signal assignment:
Simulators simulate processes and it would be transformed into the equivalent process to your process statement. Simulation time implies the use of wait for or after when driving events for sensitivity clauses or sensitivity lists.
If multiple clock are generated with different frequencies, then clock generation can be simplified if a procedure is called as concurrent procedure call. The time resolution issue, mentioned by Martin Thompson, may be mitigated a little by using different high and low time in the procedure. The test bench with procedure for clock generation is:
The time resolution is printed on the terminal for information, using the concurrent assert last in the test bench.
If the
clk_gen
procedure is placed in a separate package, then reuse from test bench to test bench becomes straight forward.Waveform for clocks are shown in figure below.
An more advanced clock generator can also be created in the procedure, which can adjust the period over time to match the requested frequency despite the limitation by time resolution. This is shown here:
Again reuse through a package will be nice.
How to use a clock and do assertions
This example shows how to generate a clock, and give inputs and assert outputs for every cycle. A simple counter is tested here.
The key idea is that the
process
blocks run in parallel, so the clock is generated in parallel with the inputs and assertions.The counter would look like this:
Related: https://electronics.stackexchange.com/questions/148320/proper-clock-generation-for-vhdl-testbenches
My favoured technique:
I usually extend this with a
finished
signal to allow me to stop the clock:Gotcha alert: Care needs to be taken if you calculate
half_period
from another constant by dividing by 2. The simulator has a "time resolution" setting, which often defaults to nanoseconds... In which case,5 ns / 2
comes out to be2 ns
so you end up with a period of 4ns! Set the simulator to picoseconds and all will be well (until you need fractions of a picosecond to represent your clock time anyway!)