VHDL · Chapter 14.3 · Testbench Development
Clock and Reset Generation
Two signals underpin every synchronous testbench: the clock and the reset. A clock is a free-running process that toggles the signal every half period to set the frequency, and you can shape its duty cycle, run multiple clocks, and stop it to end the simulation. A reset is a short sequence: assert it at time zero, hold it for a few cycles so the design under test initializes, then release it, ideally synchronized to a clock edge but not right on the active edge, which avoids recovery and removal issues. Getting these right gives the rest of the testbench a clean, deterministic time base. This lesson covers generating clocks with a given period, duty, and count, sequencing reset assert and release, and stopping the clock to terminate the run.
Foundation14 min readVHDLTestbenchClockResetVerificationSimulation
1. Engineering intuition — a heartbeat and a clean start
A synchronous design needs a heartbeat and a known starting point. The clock is the heartbeat: a signal that flips at a steady rate so every flip-flop has edges to act on — in a testbench you make it by hand, toggling a signal every half period. The reset is the clean start: hold the design in a known state long enough for it to initialize, then let go. The subtlety is how you let go — release reset near a clock edge but not exactly on it, so the DUT's flip-flops see a settled reset before the first real edge. Get the clock period and the reset hold/release right and everything downstream — stimulus, checking — has a solid, repeatable time base.
2. Formal explanation — clock and reset processes
constant TCLK : time := 10 ns; -- 100 MHz period
-- CLOCK: a free-running process, toggling every HALF period (50% duty).
clk_gen : process begin
clk <= '0'; wait for TCLK/2;
clk <= '1'; wait for TCLK/2; -- (or: clk <= not clk; wait for TCLK/2;)
end process;
-- RESET: assert at t=0, hold a few cycles, release away from the active edge.
rst_gen : process begin
rst_n <= '0'; -- assert (active-low) at time zero
wait for 5*TCLK; -- hold for ~5 clocks so the DUT initializes
wait until rising_edge(clk); -- align to a clock edge...
wait for TCLK/4; -- ...then release OFF the edge (avoid recovery issues)
rst_n <= '1'; -- release
wait; -- reset done
end process;A clock is a process that toggles the signal every half period (the constant TCLK sets the frequency;
unequal wait for values give a non-50% duty cycle). A reset process asserts at time zero, holds
for several cycles, then releases synchronized near — but deliberately off — the active clock edge to avoid
removal/recovery problems.
3. Production usage — duty cycle, multiple clocks, and stopping the run
-- NON-50% duty cycle: unequal high/low times.
clk_gen : process begin
clk <= '1'; wait for 6 ns; -- 60% high
clk <= '0'; wait for 4 ns; -- 40% low
end process;
-- MULTIPLE clocks (different frequencies / phase) for multi-domain DUTs.
clkA : process begin clkA_s <= not clkA_s; wait for 5 ns; end process; -- 100 MHz
clkB : process begin clkB_s <= not clkB_s; wait for 7 ns; end process; -- ~71 MHz
-- STOP the clock to end the simulation deterministically.
signal running : boolean := true;
clk_stop : process begin
clk <= '0'; wait for TCLK/2;
clk <= '1'; wait for TCLK/2;
if not running then wait; end if; -- park when the test signals completion
end process;
-- (or simply std.env.stop; from a control process — VHDL-2008)What hardware does this become? None — clock and reset generation are simulation stimulus, not hardware. The DUT's internal clocking/reset are real; the generators here merely supply clk and reset to the harness. Their value is a clean, controllable time base: a precise period and duty, several clocks for multi-domain tests, and a definite way to stop so the run terminates instead of toggling forever. Everything else in the testbench times itself against these two signals.
4. Structural interpretation — clock and reset feeding the DUT
5. Simulation interpretation — clock toggling and reset release
Free-running clock with reset asserted at t=0, released after several cycles
10 cycles6. Debugging example — reset released on the active edge
Expected: the DUT starts cleanly from reset. Observed: the first cycle after reset is unpredictable, or the design occasionally misses reset entirely, with behavior that changes under tiny timing tweaks. Root cause: reset was released exactly on the active clock edge (or asynchronously at an arbitrary time), creating a recovery/removal race so flip-flops saw reset deasserting right as they sampled (Module 8); or reset was not held long enough for the DUT to initialize. Fix: hold reset for several clocks, then release it synchronized near but deliberately off the active edge (e.g. a quarter period after it), so the deassertion is settled before the next sampling edge. Engineering takeaway: never release reset on the active clock edge — hold it long enough and deassert off the edge to avoid recovery races and guarantee a clean start.
-- BUG: releasing reset right on the rising edge → recovery/removal race.
-- wait until rising_edge(clk); rst_n <= '1';
-- FIX: align to the edge, then release a fraction of a period LATER.
wait until rising_edge(clk); wait for TCLK/4; rst_n <= '1';7. Common mistakes & what to watch for
- Releasing reset on the active edge. Deassert off the edge (small skew) to avoid recovery/removal races.
- Reset held too briefly. Hold for several clocks so the DUT fully initializes before stimulus.
- A clock that never stops. Provide a stop (a
runningflag orstd.env.stop) so the simulation terminates. - Wrong half-period math. Period = 2 × (
wait for); set the constant so the frequency is what you intend (and split unevenly for a duty cycle). - Unsynchronized multiple clocks treated as related. Independent clocks drift in phase; for CDC tests model them as genuinely asynchronous.
8. Engineering insight & continuity
Clock and reset generation give a testbench its time base: a free-running clock toggling every half period (with controllable duty and multiple domains) and a reset that asserts at time zero, holds for several cycles, and releases cleanly off the active edge — plus a way to stop the clock and end the run. With a solid clock and a clean reset, stimulus has something to step against and the DUT starts from a known state. The remaining piece is deciding whether the DUT's responses are correct automatically — the subject of the next lesson, Self-Checking Testbenches.
Standards & specifications
- Governing standard
- IEEE Std 1076 (VHDL)(opens IEEE in a new tab)
Defines the VHDL language — types, the simulation cycle, and the semantics a conforming analyser and simulator must implement. Synthesis restrictions and vendor coding rules are tool behaviour, not language rules.
This page also covers RTL structure, verification approach and debugging technique. Those are engineering practice built on the standard, not requirements the standard itself imposes.
Where this fits
Part of VHDL Testbenches — Stimulus, Checking & Self-Checking Design.
