0
0
VhdlHow-ToBeginner · 4 min read

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 entity with no ports.
  • Not instantiating the DUT correctly inside the architecture.
  • Missing clock generation process, so the DUT never receives clock edges.
  • Not using wait statements 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 wait statements.
  • 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.