-------------------------------------------------------------------------------
-- Title      :Distributed Arithmetic filter test bench
-- Project    : Arithmetic blocks
-------------------------------------------------------------------------------
-- File        : DApkg.VHD
-- Author      : Jamil Khatib  
-- Organization: OpenIPCore Project
-- Created     : 2000/04/25
-- Last update : 2000/04/25
-- Platform    : 
-- Simulators  : Modelsim 5.3XE / Windows98
-- Synthesizers: Leonardo / WindowsNT
-- Target      : 
-- Dependency  : 
-------------------------------------------------------------------------------
-- Description: Distributed Arithmetic filter test bench
-------------------------------------------------------------------------------
-- Copyright (c) 2000 Jamil Khatib
-- 
-- This VHDL design file is an open design; you can redistribute it and/or
-- modify it and/or implement it under the terms of the Openip General Public
-- License as it is going to be published by the OpenIPCore Organization and
-- any coming versions of this license.
-- You can check the draft license at
-- http://www.openip.org/oc/license.html

-------------------------------------------------------------------------------
-- Revisions  :
-- Revision Number :   1
-- Version         :   0.1
-- Date            :   25th Apr 2000
-- Modifier        :   Jamil Khatib (khatib@ieee.org)
-- Desccription    :   Created
-- Notes           :   No check for timing parameters (tsu,thd....)
-------------------------------------------------------------------------------

entity DA_tb is

  generic (
    CLKPERIOD    : time := 20 ns;       -- Clock Period
    OUTPUTSDELAY : time := 0 ns);
end DA_tb;

library ieee;

use ieee.std_logic_1164.all;


use work.dapkg.all;

use work.mempkg.all;



architecture behavior_tb of DA_tb is


  type QUEUE is array (0 to BUFFER_SIZE-1) of integer range 0 to 2**DATA_SIZE;  -- QUEUE type  

  constant FILTER_CONSTANTS : QUEUE := (1, 0, 0, 1);

  signal data_tb     : std_logic_vector(DATA_SIZE -1 downto 0);
  signal result_tb   : std_logic_vector(DATA_SIZE -1 downto 0);
  signal Clk_tb      : std_logic := '0';
  signal rst_n_tb    : std_logic;
  signal validout_tb : std_logic;
  signal overflow_tb : std_logic;

begin  -- behavior_tb


  uut : da
    generic map (
      NOINPUTS  => BUFFER_SIZE,
      WORD_SIZE => DATA_SIZE,
      CONTENTS  => CONSTANTS)
    port map (
      data      => data_tb,
      Clk       => clk_tb,
      Rst_n     => rst_n_tb,
      Result    => result_tb,
      ValidOut  => validout_tb,
      Overflow  => overflow_tb);

-- reset generation logic
  rst_n_tb <= transport '0' after 0 ns,
              '1'           after CLKPERIOD/4;

-- Clock generation  
  clk_tb <= not clk_tb after CLKPERIOD/2;

----------------------------
  logic : process

    variable samples     : QUEUE;
    variable ExpResult   : integer range 0 to 2** DATA_SIZE;
    variable ovrflow_res : std_logic;

-- Calculate equation


-- integer to std_logic_vector
-- int: integer input
-- SIZE: number of slv bits
    function int_2_slv(int : integer; SIZE : integer) return std_logic_vector is

      variable result      : std_logic_vector(SIZE-1 downto 0);
      variable TMP         : integer;
    begin

      TMP := int;

      for i in 0 to SIZE-1 loop

        if TMP mod 2 = 1 then RESULT(i) := '1';

        else result(i) := '0';

        end if;

        TMP := TMP / 2;                 -- shift left

      end loop;

      return result;

    end;


-- init samples
    procedure init_samples is

    begin

      for i in 0 to BUFFER_SIZE-1 loop
        samples(i) := 0;
      end loop;

    end;

    procedure calculate is


      variable MAC_res : integer range 0 to 2** DATA_SIZE := 0;
	  
    begin

      for i in 0 to BUFFER_SIZE -1 loop
        MAC_res := FILTER_CONSTANTS(i) * samples(i) + MAC_res;
      end loop;

      if MAC_res > 2**DATA_SIZE then
        ovrflow_res := '1';
      end if;

      ExpResult := MAC_res;

    end;

-- add sample
    procedure add_sample is

	
		variable tmp : integer := 5;

    begin

      for i in BUFFER_SIZE -1 downto 1 loop
        samples(i) := samples(i-1);
      end loop;


	  for i in 0 to BUFFER_SIZE-1  loop
	  	tmp := (i+1)*samples(i) + 2*i  +tmp;
      end loop;
      
      samples(0) := (tmp -2)mod (DATA_SIZE);                 -- This value should be generated randomly

    end;
----------------------------------------------------------------------
    variable count   : integer range 0 to DATA_SIZE-1;
    variable uponrst : boolean := false;  -- Flag upon reset

--The process
  begin

    wait on clk_tb, rst_n_tb;

    if rst_n_tb = '0' then

      uponrst := false;

      count := 0;

      init_samples;                     -- Init samples buffer

      ovrflow_res := '0';

    elsif clk_tb'event and clk_tb = '1'then

      if uponrst then

        -- Sampling new value
        if count = 1 then
          calculate;                    -- Calculate the filter equation
          add_sample;
        end if;

      end if;

      -- Checking the logic
      if count = DATA_SIZE-1 then

        uponrst := true;


        wait for OUTPUTSDELAY;          -- wait for a delay


        -- Valid signal check
        assert validout_tb = '1'
          report "Valid signal error";


        -- result check
        assert slv_2_int(result_tb) = ExpResult
          report "Bad Result";


        -- Overflow signal check
        assert overflow_tb = ovrflow_res
          report "Overflow signal error";

      end if;

      --
-- Count generation
      if count = DATA_SIZE-1 then
        --      reset The counter
        count := 0;

      else

        count := count + 1;

      end if;  -- count
      --


      data_tb <= int_2_slv(samples(0), DATA_SIZE);

    end if;


  end process logic;


end behavior_tb;

1