From 1477216ac0df726244647e07ca4ce83b7985fa6e Mon Sep 17 00:00:00 2001 From: Eric Kooistra <kooistra@astron.nl> Date: Fri, 17 Sep 2021 15:34:16 +0200 Subject: [PATCH] Cleanup the tb. --- .../tb/vhdl/tb_common_complex_mult.vhd | 217 ++++++++++-------- 1 file changed, 117 insertions(+), 100 deletions(-) diff --git a/libraries/base/common_mult/tb/vhdl/tb_common_complex_mult.vhd b/libraries/base/common_mult/tb/vhdl/tb_common_complex_mult.vhd index c835646c87..bc21287b07 100644 --- a/libraries/base/common_mult/tb/vhdl/tb_common_complex_mult.vhd +++ b/libraries/base/common_mult/tb/vhdl/tb_common_complex_mult.vhd @@ -23,7 +23,7 @@ -- 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 +-- > as 12 -- > run -all -- signal tb_end will stop the simulation by stopping the clk LIBRARY IEEE, common_lib, technology_lib, tech_mult_lib, ip_stratixiv_mult_lib; @@ -32,14 +32,15 @@ USE IEEE.numeric_std.ALL; USE technology_lib.technology_select_pkg.ALL; USE common_lib.common_pkg.ALL; USE common_lib.common_lfsr_sequences_pkg.ALL; +USE common_lib.common_str_pkg.ALL; USE common_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_variant : STRING := "IP"; -- "RTL" or "IP" + g_in_dat_w : NATURAL := 18; + g_conjugate_b : BOOLEAN := TRUE; -- 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; @@ -53,9 +54,14 @@ 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; + -- g_in_dat_w*2 for multiply and +1 for adder to fit largest im product value + CONSTANT c_out_dat_w : NATURAL := g_in_dat_w * 2 + 1; + CONSTANT c_max : INTEGER := 2**(g_in_dat_w-1)-1; CONSTANT c_min : INTEGER := -2**(g_in_dat_w-1); + CONSTANT c_small : INTEGER := smallest(5, c_max); + CONSTANT c_technology : NATURAL := c_tech_select_default; SIGNAL tb_end : STD_LOGIC := '0'; @@ -64,25 +70,32 @@ ARCHITECTURE tb OF tb_common_complex_mult IS SIGNAL random : STD_LOGIC_VECTOR(14 DOWNTO 0) := (OTHERS=>'0'); -- use different lengths to have different random sequences + -- Input 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); + SIGNAL in_val : STD_LOGIC; -- in_val is only passed on to out_val, not used by multiplier itself + -- Results + -- . expected valid and DUT valid, only depends on in_val and c_pipeline + SIGNAL result_val_expected : STD_LOGIC; + SIGNAL result_val_dut : STD_LOGIC; + + -- . product result + SIGNAL ref_result_re : STD_LOGIC_VECTOR(c_out_dat_w-1 DOWNTO 0); -- combinatorial result + SIGNAL ref_result_im : STD_LOGIC_VECTOR(c_out_dat_w-1 DOWNTO 0); + SIGNAL result_re_expected : STD_LOGIC_VECTOR(c_out_dat_w-1 DOWNTO 0); -- pipelined results + SIGNAL result_re_dut : STD_LOGIC_VECTOR(c_out_dat_w-1 DOWNTO 0); + SIGNAL result_im_expected : STD_LOGIC_VECTOR(c_out_dat_w-1 DOWNTO 0); + SIGNAL result_im_dut : STD_LOGIC_VECTOR(c_out_dat_w-1 DOWNTO 0); + + -- Debug signals to view constant values in wave window + SIGNAL dbg_variant : STRING(g_variant'RANGE) := g_variant; + SIGNAL dbg_in_dat_w : NATURAL := g_in_dat_w; + SIGNAL dbg_conjugate_b : BOOLEAN := g_conjugate_b; + SIGNAL dbg_pipeline : NATURAL := c_pipeline; BEGIN @@ -101,34 +114,36 @@ BEGIN 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; + proc_common_wait_some_cycles(clk, 10); rst <= '0'; - FOR I IN 0 TO 9 LOOP - WAIT UNTIL rising_edge(clk); - END LOOP; + proc_common_wait_some_cycles(clk, 10); - -- 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); + -- Some more special combinations with max and min 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); + + -- Skip (c_min + j*c_min) * (c_min + j*c_min), because that just does not fit in 2*g_in_dat_w bits of complex multiplier + --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); + + IF dbg_conjugate_b = FALSE THEN + 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); + ELSE + 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); + END IF; + 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); @@ -140,51 +155,85 @@ BEGIN 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(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); + proc_common_wait_some_cycles(clk, 10); - FOR I IN 0 TO 49 LOOP - WAIT UNTIL rising_edge(clk); - END LOOP; + -- Some special combinations close to max, min + in_ar <= TO_SVEC( c_max, g_in_dat_w); + in_ai <= TO_SVEC( c_max-1, g_in_dat_w); + in_br <= TO_SVEC( c_max-2, g_in_dat_w); + in_bi <= TO_SVEC( c_max-3, 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+1, g_in_dat_w); + in_br <= TO_SVEC( c_min+2, g_in_dat_w); + in_bi <= TO_SVEC( c_min+3, 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-1, g_in_dat_w); + in_br <= TO_SVEC( c_min+2, g_in_dat_w); + in_bi <= TO_SVEC( c_min+3, 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-1, g_in_dat_w); + in_br <= TO_SVEC(-c_max+2, g_in_dat_w); + in_bi <= TO_SVEC(-c_max+3, 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+1, g_in_dat_w); + in_br <= TO_SVEC(-c_max+2, g_in_dat_w); + in_bi <= TO_SVEC(-c_max+3, g_in_dat_w); + WAIT UNTIL rising_edge(clk); + 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); + proc_common_wait_some_cycles(clk, 100); - -- 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 + -- Try all small combinations + FOR I IN -c_small TO c_small LOOP + FOR J IN -c_small TO c_small LOOP + FOR K IN -c_small TO c_small LOOP + FOR L IN -c_small TO c_small 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; + proc_common_wait_some_cycles(clk, 10); END LOOP; + proc_common_wait_some_cycles(clk, 100); END LOOP; - END LOOP; - - FOR I IN 0 TO 49 LOOP - WAIT UNTIL rising_edge(clk); + proc_common_wait_some_cycles(clk, 1000); 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); + -- Expected combinatorial complex multiply ref_result + ref_result_re <= func_complex_multiply(in_ar, in_ai, in_br, in_bi, g_conjugate_b, "RE", c_out_dat_w); + ref_result_im <= func_complex_multiply(in_ar, in_ai, in_br, in_bi, g_conjugate_b, "IM", c_out_dat_w); u_result_re : ENTITY common_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 + g_in_dat_w => c_out_dat_w, + g_out_dat_w => c_out_dat_w ) PORT MAP ( rst => rst, clk => clk, clken => '1', - in_dat => out_result_re, + in_dat => ref_result_re, out_dat => result_re_expected ); @@ -193,14 +242,14 @@ BEGIN 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 + g_in_dat_w => c_out_dat_w, + g_out_dat_w => c_out_dat_w ) PORT MAP ( rst => rst, clk => clk, clken => '1', - in_dat => out_result_im, + in_dat => ref_result_im, out_dat => result_im_expected ); @@ -217,40 +266,13 @@ BEGIN 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 + u_dut : ENTITY work.common_complex_mult GENERIC MAP ( g_technology => c_technology, - g_variant => "IP", + g_variant => g_variant, 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_out_p_w => c_out_dat_w, g_conjugate_b => g_conjugate_b, g_pipeline_input => g_pipeline_input, g_pipeline_product => g_pipeline_product, @@ -266,23 +288,18 @@ BEGIN 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 + out_pr => result_re_dut, + out_pi => result_im_dut, + out_val => result_val_dut ); 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; - + ASSERT result_re_dut = result_re_expected REPORT "Error: RE wrong result, " & slv_to_str(result_re_dut) & " /= " & slv_to_str(result_re_expected) SEVERITY ERROR; + ASSERT result_im_dut = result_im_expected REPORT "Error: IM wrong result, " & slv_to_str(result_im_dut) & " /= " & slv_to_str(result_im_expected) SEVERITY ERROR; + ASSERT result_val_dut = result_val_expected REPORT "Error: VAL wrong result" SEVERITY ERROR; END IF; END IF; END PROCESS; -- GitLab