Developing design: moving average filter. Part 3 – testbench.

In previous posts I specified how filter should work and I described it in VHDL. Now it came time to test our filter. Below you can find very basic testbench:

library ieee;
use ieee.std_logic_1164.all;
 
entity tb_AvgFilter is
   generic (
      G_DATA_W    :integer := 16;
      G_FIL_L     :integer :=  4
   );
end entity;

architecture tb_AvgFilter_rtl of tb_AvgFilter is

component AvgFilter is
   generic (
      G_DATA_W    :integer := 16;
      G_FIL_L     :integer :=  4
   );
   port (
      clk         :in std_logic;
      rst         :in std_logic;
      en          :in std_logic;
      iv_data     :in std_logic_vector(G_DATA_W-1 downto 0);
      ov_avg      :out std_logic_vector(G_DATA_W-1 downto 0)
   );
end component;

signal clk        :std_logic := '0';
signal rst        :std_logic := '0';
signal en         :std_logic := '0';
signal iv_data    :std_logic_vector(G_DATA_W-1 downto 0);
signal ov_avg     :std_logic_vector(G_DATA_W-1 downto 0);

constant ClkGenConst  :time := 10 ns;

begin

UUT: AvgFilter
   generic map (
      G_DATA_W => G_DATA_W,
      G_FIL_L  => G_FIL_L
   )
   port map (
      clk      => clk,
      rst      => rst,
      en       => en,
      iv_data  => iv_data,
      ov_avg   => ov_avg
);

ClockGenerator: process
begin
  clk <= '0' after ClkGenConst, '1' after 2*ClkGenConst;
  wait for 2*ClkGenConst;
end process;

run_proc: process
   begin
         rst     <= '1';
         iv_data <= (others => '0');
         en      <= '0';

         wait for 100 ns;
            rst   <= '0';

         wait for  40 ns;
            iv_data <= x"000A";
            en      <= '1';
         wait for  20 ns;
            iv_data <= x"000A";
         wait for  20 ns;
            iv_data <= x"000A";
         wait for  20 ns;
            iv_data <= x"000A";
         wait for  20 ns;
            iv_data <= x"000A";
         wait for  20 ns;
            iv_data <= x"000A";
         wait for  20 ns;
            iv_data <= x"000A";
         wait for  20 ns;
            iv_data <= x"000A";
         wait for  20 ns;
            iv_data <= x"000A";
         wait for  20 ns;
            iv_data <= x"000A";
         wait for  20 ns;
         en    <= '0';
         wait;
   end process;
end architecture;

Is such test enough to be sure that our filter works as expected? Well, maybe for small projects – yes, but imagine projects where are thousands of signals and registers, where data goes through many calculations and conditional statements before it reaches the output. In big designs this is irresponsible to test only one specific case and forget about all others. This means that testbench should cover as much cases as possible (of course this is not always possible) and should contain many various input values. But how can it be done? Manually writing and planning input data step by step ? It would take much time…

There are known approaches which will be helpful here. I will try a little bit to automatize tests in next posts.

*** *** ***

All source codes used in that post you can find on gitlab.com.

*** *** ***

Leave a Reply

Your email address will not be published. Required fields are marked *