-- Clock generation processp_clk : processbegin i_clk <= '0'; wait for c_CLK_PERIOD / 2; i_clk <= '1'; wait for c_CLK_PERIOD / 2;end process p_clk;-- Concurrent alternativei_clk <= not i_clk after c_CLK_PERIOD / 2;
Complete Testbench for Sequential Circuit
library IEEE;use IEEE.STD_LOGIC_1164.ALL;use IEEE.NUMERIC_STD.ALL;entity tb_counter isend entity tb_counter;architecture tb of tb_counter is constant c_CLK_PERIOD : time := 10 ns; signal i_clk : std_logic := '0'; signal i_rst : std_logic := '1'; signal o_cnt : std_logic_vector(3 downto 0);begin -- Clock generation i_clk <= not i_clk after c_CLK_PERIOD / 2; -- DUT DUT : entity work.counter_4bit port map ( i_clk => i_clk, i_rst => i_rst, o_cnt => o_cnt ); -- Stimuli p_test : process begin -- Reset active for 3 cycles i_rst <= '1'; wait for 3 * c_CLK_PERIOD; assert unsigned(o_cnt) = 0 report "Reset failed" severity error; -- Start counting i_rst <= '0'; wait for 5 * c_CLK_PERIOD; assert unsigned(o_cnt) = 5 report "Counting incorrect" severity error; -- Wait for overflow (16 total cycles = back to 0) wait for 11 * c_CLK_PERIOD; assert unsigned(o_cnt) = 0 report "Overflow incorrect" severity error; report "Testbench completed successfully" severity note; wait; end process p_test;end architecture tb;
Useful Simulation Instructions
Instruction
Usage
wait for 10 ns;
Wait a fixed duration
wait until rising_edge(i_clk);
Wait for a clock edge
wait until i_valid = '1';
Wait for a condition
wait;
Stop simulation
assert condition report "msg" severity level;
Verification
Severity Levels
Level
Effect
note
Informational message
warning
Warning, simulation continues
error
Error, simulation may continue
failure
Immediate simulation stop
Factor Verification
When a testbench grows, avoid repeating the same assertion everywhere. A small local procedure keeps messages consistent.
Declaration (in the testbench architecture declarative region, before begin, next to simulation constants and signals):
-- Before the begin of the tb architectureprocedure check_slv( constant i_name : in string; constant i_observed : in std_logic_vector; constant i_expected : in std_logic_vector) isbegin assert i_observed = i_expected report i_name & " expected=0x" & to_hstring(i_expected) & " observed=0x" & to_hstring(i_observed) severity error;end procedure check_slv;
Usage (inside a test process, after the architecture begin):
wait until rising_edge(i_clk);check_slv("counter after reset", o_cnt, x"0");
The testbench stays easy to read: stimuli describe the scenario, verification procedures describe the expected rules. If the procedure must be shared by several testbenches, it can later move into a package.
End Simulation with std.env
With VHDL-2008, std.env.finish cleanly terminates a simulation once the scenario is done.