OpenCores
URL https://opencores.org/ocsvn/astron_multiplier/astron_multiplier/trunk

Subversion Repositories astron_multiplier

[/] [astron_multiplier/] [trunk/] [tb_common_complex_mult.vhd] - Rev 4

Compare with Previous | Blame | View Log

-------------------------------------------------------------------------------
--
-- Copyright 2020
-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/>
-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
-- 
-- Licensed under the Apache License, Version 2.0 (the "License");
-- you may not use this file except in compliance with the License.
-- You may obtain a copy of the License at
-- 
--     http://www.apache.org/licenses/LICENSE-2.0
-- 
-- Unless required by applicable law or agreed to in writing, software
-- distributed under the License is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-- See the License for the specific language governing permissions and
-- limitations under the License.
--
-------------------------------------------------------------------------------
-- Purpose: Verify different architectures of common_complex_mult
-- Description:
--   p_verify verifies that the instances of common_complex_mult all yield the
--   expected results and ASSERTs an ERROR in case they differ.
-- Usage:
-- > as 10
-- > run -all  -- signal tb_end will stop the simulation by stopping the clk
 
LIBRARY IEEE, common_pkg_lib, common_components_lib; --, ip_stratixiv_mult_lib;
USE IEEE.std_logic_1164.ALL;
USE IEEE.numeric_std.ALL;
--USE technology_lib.technology_select_pkg.ALL;
USE common_pkg_lib.common_pkg.ALL;
USE common_pkg_lib.common_lfsr_sequences_pkg.ALL;
USE common_pkg_lib.tb_common_pkg.ALL;
 
 
ENTITY tb_common_complex_mult IS
  GENERIC (
    g_in_dat_w         : NATURAL := 4;
    g_out_dat_w        : NATURAL := 8;       -- g_in_dat_w*2 for multiply and +1 for adder
    g_conjugate_b      : BOOLEAN := FALSE;   -- When FALSE p = a * b, else p = a * conj(b)
    g_pipeline_input   : NATURAL := 1;
    g_pipeline_product : NATURAL := 0;
    g_pipeline_adder   : NATURAL := 1;
    g_pipeline_output  : NATURAL := 1
  );
END tb_common_complex_mult;
 
 
ARCHITECTURE tb OF tb_common_complex_mult IS
 
  CONSTANT clk_period        : TIME := 10 ns;
  CONSTANT c_pipeline        : NATURAL := g_pipeline_input + g_pipeline_product + g_pipeline_adder + g_pipeline_output;
 
  CONSTANT c_max             : INTEGER :=  2**(g_in_dat_w-1)-1;
  CONSTANT c_min             : INTEGER := -2**(g_in_dat_w-1);
 
  CONSTANT c_technology      : NATURAL := 0;
 
  SIGNAL tb_end              : STD_LOGIC := '0';
  SIGNAL rst                 : STD_LOGIC;
  SIGNAL clk                 : STD_LOGIC := '0';
 
  SIGNAL random              : STD_LOGIC_VECTOR(14 DOWNTO 0) := (OTHERS=>'0');  -- use different lengths to have different random sequences
 
  SIGNAL in_ar               : STD_LOGIC_VECTOR(g_in_dat_w-1 DOWNTO 0);
  SIGNAL in_ai               : STD_LOGIC_VECTOR(g_in_dat_w-1 DOWNTO 0);
  SIGNAL in_br               : STD_LOGIC_VECTOR(g_in_dat_w-1 DOWNTO 0);
  SIGNAL in_bi               : STD_LOGIC_VECTOR(g_in_dat_w-1 DOWNTO 0);
 
  SIGNAL in_val              : STD_LOGIC;  -- in_val is only passed on to out_val
  SIGNAL result_val_expected : STD_LOGIC;
  SIGNAL result_val_rtl      : STD_LOGIC;
  SIGNAL result_val_ip       : STD_LOGIC;
 
  SIGNAL out_result_re       : STD_LOGIC_VECTOR(g_out_dat_w-1 DOWNTO 0);  -- combinatorial result
  SIGNAL out_result_im       : STD_LOGIC_VECTOR(g_out_dat_w-1 DOWNTO 0);
  SIGNAL result_re_expected  : STD_LOGIC_VECTOR(g_out_dat_w-1 DOWNTO 0);  -- pipelined results
  SIGNAL result_re_rtl       : STD_LOGIC_VECTOR(g_out_dat_w-1 DOWNTO 0);
  SIGNAL result_re_ip        : STD_LOGIC_VECTOR(g_out_dat_w-1 DOWNTO 0);
  SIGNAL result_im_expected  : STD_LOGIC_VECTOR(g_out_dat_w-1 DOWNTO 0);
  SIGNAL result_im_rtl       : STD_LOGIC_VECTOR(g_out_dat_w-1 DOWNTO 0);
  SIGNAL result_im_ip        : STD_LOGIC_VECTOR(g_out_dat_w-1 DOWNTO 0);
 
 
BEGIN
 
  clk <= (NOT clk) OR tb_end AFTER clk_period/2;
 
  random <= func_common_random(random) WHEN rising_edge(clk);
 
  in_val <= random(random'HIGH);
 
  -- run -all
  p_in_stimuli : PROCESS
  BEGIN
    rst <= '1';
    in_ar <= TO_SVEC(0, g_in_dat_w);
    in_br <= TO_SVEC(0, g_in_dat_w);
    in_ai <= TO_SVEC(0, g_in_dat_w);
    in_bi <= TO_SVEC(0, g_in_dat_w);
    WAIT UNTIL rising_edge(clk);
    FOR I IN 0 TO 9 LOOP
      WAIT UNTIL rising_edge(clk);
    END LOOP;
    rst <= '0';
    FOR I IN 0 TO 9 LOOP
      WAIT UNTIL rising_edge(clk);
    END LOOP;
 
    -- Some special combinations
    in_ar <= TO_SVEC(2, g_in_dat_w);
    in_ai <= TO_SVEC(4, g_in_dat_w);
    in_br <= TO_SVEC(3, g_in_dat_w);
    in_bi <= TO_SVEC(5, g_in_dat_w);
    WAIT UNTIL rising_edge(clk);
    in_ar <= TO_SVEC( c_max, g_in_dat_w);  -- p*p - p*p + j ( p*p + p*p) = 0 + j 2pp  or  p*p + p*p + j (-p*p + p*p) = 2pp + j 0
    in_ai <= TO_SVEC( c_max, g_in_dat_w);
    in_br <= TO_SVEC( c_max, g_in_dat_w);
    in_bi <= TO_SVEC( c_max, g_in_dat_w);
    WAIT UNTIL rising_edge(clk);
    in_ar <= TO_SVEC( c_min, g_in_dat_w);
    in_ai <= TO_SVEC( c_min, g_in_dat_w);
    in_br <= TO_SVEC( c_min, g_in_dat_w);
    in_bi <= TO_SVEC( c_min, g_in_dat_w);
    WAIT UNTIL rising_edge(clk);
    in_ar <= TO_SVEC( c_max, g_in_dat_w);
    in_ai <= TO_SVEC( c_max, g_in_dat_w);
    in_br <= TO_SVEC( c_min, g_in_dat_w);
    in_bi <= TO_SVEC( c_min, g_in_dat_w);
    WAIT UNTIL rising_edge(clk);
    in_ar <= TO_SVEC( c_max, g_in_dat_w);
    in_ai <= TO_SVEC( c_max, g_in_dat_w);
    in_br <= TO_SVEC(-c_max, g_in_dat_w);
    in_bi <= TO_SVEC(-c_max, g_in_dat_w);
    WAIT UNTIL rising_edge(clk);
    in_ar <= TO_SVEC( c_min, g_in_dat_w);
    in_ai <= TO_SVEC( c_min, g_in_dat_w);
    in_br <= TO_SVEC(-c_max, g_in_dat_w);
    in_bi <= TO_SVEC(-c_max, g_in_dat_w);
    WAIT UNTIL rising_edge(clk);
 
    FOR I IN 0 TO 49 LOOP
      WAIT UNTIL rising_edge(clk);
    END LOOP;
 
    -- All combinations
    FOR I IN -c_max TO c_max LOOP
      FOR J IN -c_max TO c_max LOOP
        FOR K IN -c_max TO c_max LOOP
          FOR L IN -c_max TO c_max LOOP
            in_ar <= TO_SVEC(I, g_in_dat_w);
            in_ai <= TO_SVEC(K, g_in_dat_w);
            in_br <= TO_SVEC(J, g_in_dat_w);
            in_bi <= TO_SVEC(L, g_in_dat_w);
            WAIT UNTIL rising_edge(clk);
          END LOOP;
        END LOOP;
      END LOOP;
    END LOOP;
 
    FOR I IN 0 TO 49 LOOP
      WAIT UNTIL rising_edge(clk);
    END LOOP;
 
    tb_end <= '1';
    WAIT;
  END PROCESS;
 
  -- Expected combinatorial complex multiply out_result
  out_result_re <= func_complex_multiply(in_ar, in_ai, in_br, in_bi, g_conjugate_b, "RE", g_out_dat_w);
  out_result_im <= func_complex_multiply(in_ar, in_ai, in_br, in_bi, g_conjugate_b, "IM", g_out_dat_w);
 
  u_result_re : ENTITY common_components_lib.common_pipeline
  GENERIC MAP (
    g_representation => "SIGNED",
    g_pipeline       => c_pipeline,
    g_reset_value    => 0,
    g_in_dat_w       => g_out_dat_w,
    g_out_dat_w      => g_out_dat_w
  )
  PORT MAP (
    rst     => rst,
    clk     => clk,
    clken   => '1',
    in_dat  => out_result_re,
    out_dat => result_re_expected
  );
 
  u_result_im : ENTITY common_components_lib.common_pipeline
  GENERIC MAP (
    g_representation => "SIGNED",
    g_pipeline       => c_pipeline,
    g_reset_value    => 0,
    g_in_dat_w       => g_out_dat_w,
    g_out_dat_w      => g_out_dat_w
  )
  PORT MAP (
    rst     => rst,
    clk     => clk,
    clken   => '1',
    in_dat  => out_result_im,
    out_dat => result_im_expected
  );
 
  u_result_val_expected : ENTITY common_components_lib.common_pipeline_sl
  GENERIC MAP (
    g_pipeline    => c_pipeline,
    g_reset_value => 0
  )
  PORT MAP (
    rst     => rst,
    clk     => clk,
    clken   => '1',
    in_dat  => in_val,
    out_dat => result_val_expected
  );
 
  u_dut_rtl : ENTITY work.common_complex_mult
  GENERIC MAP (
    g_technology       => c_technology,
    g_variant          => "RTL",
    g_in_a_w           => g_in_dat_w,
    g_in_b_w           => g_in_dat_w,
    g_out_p_w          => g_out_dat_w,
    g_conjugate_b      => g_conjugate_b,
    g_pipeline_input   => g_pipeline_input,
    g_pipeline_product => g_pipeline_product,
    g_pipeline_adder   => g_pipeline_adder,
    g_pipeline_output  => g_pipeline_output
  )
  PORT MAP (
    rst        => rst,
    clk        => clk,
    clken      => '1',
    in_ar      => in_ar,
    in_ai      => in_ai,
    in_br      => in_br,
    in_bi      => in_bi,
    in_val     => in_val,
    out_pr     => result_re_rtl,
    out_pi     => result_im_rtl,
    out_val    => result_val_rtl
  );
 
  u_dut_ip : ENTITY work.common_complex_mult
  GENERIC MAP (
    g_technology       => c_technology,
    g_variant          => "IP",
    g_in_a_w           => g_in_dat_w,
    g_in_b_w           => g_in_dat_w,
    g_out_p_w          => g_out_dat_w,
    g_conjugate_b      => g_conjugate_b,
    g_pipeline_input   => g_pipeline_input,
    g_pipeline_product => g_pipeline_product,
    g_pipeline_adder   => g_pipeline_adder,
    g_pipeline_output  => g_pipeline_output
  )
  PORT MAP (
    rst        => rst,
    clk        => clk,
    clken      => '1',
    in_ar      => in_ar,
    in_ai      => in_ai,
    in_br      => in_br,
    in_bi      => in_bi,
    in_val     => in_val,
    out_pr     => result_re_ip,
    out_pi     => result_im_ip,
    out_val    => result_val_ip
  );
 
  p_verify : PROCESS(rst, clk)
  BEGIN
    IF rst='0' THEN
      IF rising_edge(clk) THEN
        ASSERT result_re_rtl  = result_re_expected  REPORT "Error: RE wrong RTL result"  SEVERITY ERROR;
        ASSERT result_im_rtl  = result_im_expected  REPORT "Error: IM wrong RTL result"  SEVERITY ERROR;
        ASSERT result_val_rtl = result_val_expected REPORT "Error: VAL wrong RTL result" SEVERITY ERROR;
 
        ASSERT result_re_ip   = result_re_expected  REPORT "Error: RE wrong IP result"  SEVERITY ERROR;
        ASSERT result_im_ip   = result_im_expected  REPORT "Error: IM wrong IP result"  SEVERITY ERROR;
        ASSERT result_val_ip  = result_val_expected REPORT "Error: VAL wrong IP result" SEVERITY ERROR;
 
      END IF;
    END IF;
  END PROCESS;
 
END tb;
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.