How to Write Testbench in VHDL: Syntax and Example
To write a testbench in VHDL, create an entity with no ports and an architecture that instantiates the design under test (DUT). Use
process blocks to apply stimulus signals and observe outputs, simulating the behavior of your design.Syntax
A VHDL testbench typically has an entity with no ports and an architecture where you instantiate the design under test (DUT). Inside the architecture, you use signal declarations to connect to the DUT ports and process blocks to generate input stimulus and check outputs.
Key parts:
- Entity: Empty, no ports.
- Architecture: Contains signals and DUT instantiation.
- Signals: Internal wires to connect DUT ports.
- Process: Runs sequential code to apply test inputs.
vhdl
entity testbench is end entity; architecture behavior of testbench is -- Declare signals to connect to DUT signal clk : std_logic := '0'; signal reset : std_logic := '1'; signal data_in : std_logic_vector(7 downto 0) := (others => '0'); signal data_out : std_logic_vector(7 downto 0); -- Component declaration of DUT component my_design port( clk : in std_logic; reset : in std_logic; data_in : in std_logic_vector(7 downto 0); data_out : out std_logic_vector(7 downto 0) ); end component; begin -- Instantiate DUT uut: my_design port map( clk => clk, reset => reset, data_in => data_in, data_out => data_out ); -- Clock generation process clk_process: process begin while true loop clk <= '0'; wait for 10 ns; clk <= '1'; wait for 10 ns; end loop; end process; -- Stimulus process stim_proc: process begin -- Initialize reset reset <= '1'; wait for 20 ns; reset <= '0'; -- Apply test inputs data_in <= "00000001"; wait for 20 ns; data_in <= "00000010"; wait for 20 ns; -- End simulation wait; end process; end architecture;
Example
This example shows a simple testbench for a design called my_design that has a clock, reset, and 8-bit data input/output. It generates a clock signal, applies reset, and sends two data values to the DUT.
vhdl
library ieee; use ieee.std_logic_1164.all; entity testbench is end entity; architecture behavior of testbench is signal clk : std_logic := '0'; signal reset : std_logic := '1'; signal data_in : std_logic_vector(7 downto 0) := (others => '0'); signal data_out : std_logic_vector(7 downto 0); component my_design port( clk : in std_logic; reset : in std_logic; data_in : in std_logic_vector(7 downto 0); data_out : out std_logic_vector(7 downto 0) ); end component; begin uut: my_design port map( clk => clk, reset => reset, data_in => data_in, data_out => data_out ); clk_process: process begin while true loop clk <= '0'; wait for 10 ns; clk <= '1'; wait for 10 ns; end loop; end process; stim_proc: process begin reset <= '1'; wait for 20 ns; reset <= '0'; data_in <= "00000001"; wait for 20 ns; data_in <= "00000010"; wait for 20 ns; wait; end process; end architecture;
Output
Simulation runs applying clock and inputs; outputs depend on my_design implementation.
Common Pitfalls
- Forgetting to declare the testbench
entitywith no ports. - Not instantiating the DUT correctly inside the architecture.
- Missing clock generation process, so the DUT never receives clock edges.
- Not using
waitstatements in stimulus process, causing simulation to stop immediately. - Assigning signals directly in architecture without a process, which is not allowed for sequential stimulus.
vhdl
wrong: architecture behavior of testbench is signal clk : std_logic := '0'; begin clk <= '0'; -- This will not toggle clock end architecture; right: architecture behavior of testbench is signal clk : std_logic := '0'; begin clk_process: process begin while true loop clk <= '0'; wait for 10 ns; clk <= '1'; wait for 10 ns; end loop; end process; end architecture;
Quick Reference
- Testbench entity has no ports.
- Use signals to connect to DUT ports.
- Generate clock with a process and
waitstatements. - Apply stimulus inside a process with delays.
- End simulation with
wait;to keep it running.
Key Takeaways
Write a testbench entity with no ports to isolate testing.
Instantiate your design under test inside the testbench architecture.
Use processes with wait statements to generate clock and apply inputs.
Declare signals to connect testbench and DUT ports properly.
Avoid assigning signals outside processes for stimulus generation.