Tuesday 5 June 2012

How to write a testbench?

Once you finish writing code for your design,you need to test whether it is working or not.One method of testing your design is by writing a testbench code.Without going much into the details I will give you an example.
     Below is a program for a basic 4 bit counter with reset input :


library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity test is
port (clk : in std_logic;
      count : out std_logic_vector(3 downto 0);
      reset :in std_logic
     );
end test;

architecture Behavioral of test is
signal c : std_logic_vector(3 downto 0) :=(others => '0');  --initializing count to zero.
begin
count <= c;
process(clk,reset)
begin
if(clk'event and clk='1') then
-- when count reaches its maximum(that is 15) reset it to 0
if(= "1111") then
<="0000";
end if;
<= c+'1';  --increment count at every positive edge of clk.
end if;
if(reset='1') then  --when reset equal to '1' make count equal to 0.
<=(others => '0');  -- c ="0000"
end if;
end process;

end Behavioral;


Now I will give a sample test bench for the above code:

LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.std_logic_unsigned.all;

-- entity declaration for your testbench.Dont declare any ports here
ENTITY test_tb IS
END test_tb;

ARCHITECTURE behavior OF test_tb IS
   -- Component Declaration for the Unit Under Test (UUT)
    COMPONENT test  --'test' is the name of the module needed to be tested.
--just copy and paste the input and output ports of your module as such. 
    PORT(
         clk : IN  std_logic;
         count : OUT  std_logic_vector(3 downto 0);
         reset : IN  std_logic
        );
    END COMPONENT;
   --declare inputs and initialize them
   signal clk : std_logic := '0';
   signal reset : std_logic := '0';
   --declare outputs and initialize them
   signal count : std_logic_vector(3 downto 0);
   -- Clock period definitions
   constant clk_period : time := 1 ns;
BEGIN
    -- Instantiate the Unit Under Test (UUT)
   uut: test PORT MAP (
         clk => clk,
          count => count,
          reset => reset
        );      

   -- Clock process definitions( clock with 50% duty cycle is generated here.
   clk_process :process
   begin
        clk <= '0';
        wait for clk_period/2;  --for 0.5 ns signal is '0'.
        clk <= '1';
        wait for clk_period/2;  --for next 0.5 ns signal is '1'.
   end process;
   -- Stimulus process
  stim_proc: process
   begin        
        wait for 7 ns;
        reset <='1';
        wait for 3 ns;
        reset <='0';
        wait for 17 ns;
        reset <= '1';
        wait for 1 ns;
        reset <= '0';
        wait;
  end process;

END;

I think the code is self explanatory.I have given comments so that you can easily follow it. Now add these programs to your project and compile them.Once compilation is over click on "simulate Behavioral Model".You will get the following waveform.
    As you can see,whenever my reset=1,count value is zero.Otherwise count increments upto 15 and then get reset to zero.
Now a little more explanation about the test bench code:
    1) wait for 7 ns; means the simulator doesn't do anything for 7 nano second.If you want 7 ms delay instead of  7 ns then just replace ns with ms.
    2)The process named "clock_process" is  must in any test bench because it is used to generate clock for your module.Any main module always work with this clock.The period and duty cycle of the clock can be changed by editing this process.
    3)Your main module has to be given as a component in your test bench program inside "architecture".
    4)Your module has to be instantiated after the 'begin' statement.

0 comments:

Post a Comment