VHDL: What is a Testbench and how do I use it?

Once you finish writing code for your design, the next step would be to test it. One method of testing your design is by writing a testbench code. A testbench is used for testing the design and making sure it works as per your specified functionalities. 

Using a testbench, we can pass inputs of our choice to the design to be tested. The outputs coming out of our design can be viewed on a simulation waveform or text file or even on console screen.

Lets see how this works with an example.

VHDL code for a 4 bit counter with reset:

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity adder is
port (clk : in std_logic;
      reset :in std_logic;
      count : out unsigned(3 downto 0)  --output of the design. 4 bit count value.
     );
end adder;

architecture behavioral of adder is

--initializing the count to zero.
signal c : unsigned(3 downto 0) :=(others => '0');  

begin

count <= c;

process(clk,reset)
begin
    if(reset = '1') then    --active high reset for the counter.
        c <= (others => '0');
    elsif(rising_edge(clk)) then
    -- when count reaches its maximum(that is 15) reset it to 0
        if(c = 15) then
            c <= (others => '0');
        else    
            c <= c + 1;  --increment count at every positive edge of clk.
        end if;
    end if; 
end process;

end behavioral;

The design above is a 4 bit UP counter with active high asynchronous reset. The design has 2 inputs - a clock and reset and one output which is the count value.

In order to write a good testbench we need to first understand the design. At least we should know, what kind of errors might be there and what kind of input combinations can bring out these errors. The design we have here is a very simple one, so it shouldn't be too complicated.

Let me show you a sample testbench for this design.

VHDL testbench for 4 bit UP counter:

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

-- entity declaration for your testbench. 
--Notice that the entity port list is empty here.
entity tb_adder is
end tb_adder;

architecture behavior of tb_adder is

-- component declaration for the unit under test (uut)
component adder is
port (clk : in std_logic;
      reset :in std_logic;
      count : out unsigned(3 downto 0)
     );
end component;

--declare inputs and initialize them to zero.
signal clk : std_logic := '0';
signal reset : std_logic := '0';

--declare outputs
signal count : unsigned(3 downto 0);

-- define the period of clock here.
-- It's recommended to use CAPITAL letters to define constants.
constant CLK_PERIOD : time := 10 ns;

begin

    -- instantiate the unit under test (uut)
   uut : adder port map (
            Clk => Clk,
            reset => reset, 
            count => count
        );      

   -- Clock process definitions( clock with 50% duty cycle is generated here.
   Clk_process :process
   begin
        Clk <= '0';
        wait for CLK_PERIOD/2;  --for half of clock period clk stays at '0'.
        Clk <= '1';
        wait for CLK_PERIOD/2;  --for next half of clock period clk stays at '1'.
   end process;
    
   -- Stimulus process, Apply inputs here.
  stim_proc: process
   begin        
        wait for CLK_PERIOD*10; --wait for 10 clock cycles.
        reset <='1';                    --then apply reset for 2 clock cycles.
        wait for CLK_PERIOD*2;
        reset <='0';                    --then pull down reset for 20 clock cycles.
        wait for CLK_PERIOD*20;
        reset <= '1';               --then apply reset for one clock cycle.
        wait for CLK_PERIOD;
        reset <= '0';               --pull down reset and let the counter run.
        wait;
  end process;

end;

The code is self explanatory with plenty of comments.

When these codes were simulated in Xilinx ISE 14.6, I got the following waveform. 

Simulation waveform:


I would summarize few points here,
  1. The entity port list of a testbench is always empty. 
  2. All the designs which you want to test, declare them as components in the testbench code. 
  3. The clock process part in the code, is only required for testing designs with a clock( sequential designs).
  4. Declare all the inputs and outputs in the design to be tested. Make sure you initialize all the inputs to zero ,in the system.
  5. Instantiate the design by any one of the Instantiation methods described available here. Note that this instantiation is written after the begin statement.
This post is for beginners to get an overview on writing testbenches. As you discover more in VHDL, you will need and learn to write more complicated testbenches. There are lot of example designs in this blog, and almost every design comes with a testbench.

Post a Comment

6 Comments

  1. Inspecting the waveforms works for simple testbenchs, but it's easier to use VHDL asserts;
    You can put them at any given point in the test bench, to check whether the received values are as expected. This way you don't need to inspect waveforms (except when inspecting, when asserts tell you something is wrong)

    ReplyDelete
  2. This comment has been removed by a blog administrator.

    ReplyDelete
  3. In ModelSim, at least for me the "time := 1 ns;" doesn't work, but, with 10 ns is just fine.
    Which software did you use?

    ReplyDelete
  4. @Raphael : thanks for pointing out the mistake.I used xilinx ISE version 10.1.
    VHDL asserts are used to write intelligent testbenches. For these testbenches you need not see the waveform for seeing whether the code is working or not.They are used to alert the user of some condition inside the model. When the expression in the ASSERT statement evaluates to FALSE, the associated text message is displayed on the simulator console.Assertion statements can be used for complex designs where inputs and outputs have complex relation.
    I will put a post on assertion statements in some time, for now see this link(under the E4 heading):
    http://www.vhdl.org/comp.lang.vhdl/html3/gloss_example.html

    ReplyDelete
  5. hello can i get a link for the modified random number generator in open cores website.

    thanks in advance

    ReplyDelete
  6. @Divya : The link is available in this post.
    http://vhdlguru.blogspot.com/2010/08/random-number-generator-in-vhdlcont.html

    Just go to the project page and click on the download option.

    ReplyDelete