diff --git a/libraries/dsp/beamformer/tb/vhdl/tb_beamformer.vhd b/libraries/dsp/beamformer/tb/vhdl/tb_beamformer.vhd index 08806444a1510df6b60fed379ccee4f24d9c0d0d..8f59580bdd65b88c8f06041a55d11e119c191f9a 100644 --- a/libraries/dsp/beamformer/tb/vhdl/tb_beamformer.vhd +++ b/libraries/dsp/beamformer/tb/vhdl/tb_beamformer.vhd @@ -77,13 +77,16 @@ ARCHITECTURE tb OF tb_beamformer IS SIGNAL verify_addr_en : STD_LOGIC := '0'; SIGNAL verify_data_en : STD_LOGIC := '0'; + CONSTANT min_snk_in_val: INTEGER := -(2**g_data_w/2); + CONSTANT max_snk_in_val: INTEGER := (2**g_data_w/2)-1; + -- MM CONSTANT c_unb_nr : NATURAL := 0; CONSTANT c_node_nr : NATURAL := 0; -- choose node 0 is FN 0 CONSTANT c_mm_file_ram_beamformer : STRING := mmf_unb_file_prefix(c_unb_nr, c_node_nr) & "RAM_BEAMFORMER_" & int_to_str(g_tb_index); - SIGNAL src_in_enable : STD_LOGIC := '0'; - SIGNAL src_in : t_dp_sosi := c_dp_sosi_rst; + SIGNAL snk_in_enable : STD_LOGIC := '0'; + SIGNAL snk_in : t_dp_sosi := c_dp_sosi_rst; ----------------------------------------------------------------------------- -- beamformer @@ -99,13 +102,13 @@ ARCHITECTURE tb OF tb_beamformer IS SIGNAL addr_stimulus_weight_addr : STD_LOGIC_VECTOR(ceil_log2(g_nof_weights)-1 DOWNTO 0) := (OTHERS=>'0'); SIGNAL data_stimulus_weight_addr : STD_LOGIC_VECTOR(ceil_log2(g_nof_weights)-1 DOWNTO 0) := (OTHERS=>'0'); - SIGNAL rd_data : STD_LOGIC_VECTOR(c_word_w-1 DOWNTO 0); + SIGNAL rd_data_mm_stimuli : STD_LOGIC_VECTOR(c_word_w-1 DOWNTO 0); + SIGNAL rd_data_addr_stimuli : STD_LOGIC_VECTOR(c_word_w-1 DOWNTO 0); - -- used to set src_in re data - SIGNAL src_re_data : STD_LOGIC_VECTOR(g_data_w-1 DOWNTO 0) := "00000001"; - SIGNAL src_im_data : STD_LOGIC_VECTOR(g_data_w-1 DOWNTO 0) := "00000001"; + -- used to set snk_in re data + SIGNAL snk_re_data : STD_LOGIC_VECTOR(g_data_w-1 DOWNTO 0) := TO_SVEC(1, g_data_w); + SIGNAL snk_im_data : STD_LOGIC_VECTOR(g_data_w-1 DOWNTO 0) := TO_SVEC(0, g_data_w); - BEGIN ----------------------------------------------------------------------------- -- Clocks and reset @@ -117,18 +120,18 @@ ARCHITECTURE tb OF tb_beamformer IS mm_rst <= '1', '0' AFTER c_mm_clk_period*7; ---------------------------------------------------------------------------- - -- Stimuli src_in + -- Stimuli snk_in ---------------------------------------------------------------------------- -- sync, valid, sop, eop - proc_common_gen_duty_pulse(0, 1, c_in_sync_interval, '1', dp_rst, dp_clk, src_in_enable, src_in.sync); - proc_common_gen_duty_pulse(0, c_in_block_size, c_in_block_interval, '1', dp_rst, dp_clk, src_in_enable, src_in.valid); - proc_common_gen_duty_pulse(0, 1, c_in_block_interval, '1', dp_rst, dp_clk, src_in_enable, src_in.sop); - proc_common_gen_duty_pulse(c_in_block_size-1, 1, c_in_block_interval, '1', dp_rst, dp_clk, src_in_enable, src_in.eop); -- DUT uses eop + proc_common_gen_duty_pulse(0, 1, c_in_sync_interval, '1', dp_rst, dp_clk, snk_in_enable, snk_in.sync); + proc_common_gen_duty_pulse(0, c_in_block_size, c_in_block_interval, '1', dp_rst, dp_clk, snk_in_enable, snk_in.valid); + proc_common_gen_duty_pulse(0, 1, c_in_block_interval, '1', dp_rst, dp_clk, snk_in_enable, snk_in.sop); + proc_common_gen_duty_pulse(c_in_block_size-1, 1, c_in_block_interval, '1', dp_rst, dp_clk, snk_in_enable, snk_in.eop); -- DUT uses eop -- bsn - src_in.bsn <= INCR_UVEC(src_in.bsn, 1) WHEN rising_edge(dp_clk) AND src_in.eop='1'; + snk_in.bsn <= INCR_UVEC(snk_in.bsn, 1) WHEN rising_edge(dp_clk) AND snk_in.eop='1'; -- re/im data - src_in.re <= TO_DP_DSP_DATA(TO_UINT(src_re_data)); - src_in.im <= TO_DP_DSP_DATA(TO_UINT(src_im_data)); + snk_in.re <= TO_DP_DSP_DATA(TO_SINT(snk_re_data)); + snk_in.im <= TO_DP_DSP_DATA(TO_SINT(snk_im_data)); -- set master OK OK <= mm_ok and addr_ok and data_ok; @@ -156,32 +159,39 @@ ARCHITECTURE tb OF tb_beamformer IS proc_common_wait_until_low(dp_clk, dp_rst); proc_common_wait_some_cycles(dp_clk, 10); - -- enable src_in generator - src_in_enable <= '1'; - proc_common_wait_until_hi_lo(dp_clk, src_in.sync); + -- enable snk_in generator + snk_in_enable <= '1'; + proc_common_wait_until_hi_lo(dp_clk, snk_in.sync); REPORT "Start mm stumulus"; FOR I IN 0 TO g_nof_inputs-1 LOOP FOR J IN 0 TO g_nof_weights-1 LOOP -- write MM page - mmf_mm_bus_wr(c_mm_file_ram_beamformer, I*g_nof_weights+J, J, mm_clk); + mmf_mm_bus_wr(c_mm_file_ram_beamformer, I*g_nof_weights+J, (J+1)*2**16+J+1, mm_clk); END LOOP; END LOOP; FOR I IN 0 TO g_nof_inputs-1 LOOP FOR J IN 0 TO g_nof_weights-1 LOOP -- read back MM page - mmf_mm_bus_rd(c_mm_file_ram_beamformer, I*g_nof_weights+J, rd_data, mm_clk); - IF TO_UINT(rd_data) /= J THEN + mmf_mm_bus_rd(c_mm_file_ram_beamformer, I*g_nof_weights+J, rd_data_mm_stimuli, mm_clk); + IF TO_SINT(rd_data_mm_stimuli(c_word_w/2-1 DOWNTO 0)) /= J+1 THEN ASSERT FALSE - REPORT "MM Wrong weight" & - ", expected=" & int_to_str(J) & - ", readback=" & int_to_str(INTEGER(TO_UINT(rd_data))) + REPORT "MM Wrong weight for re" & + ", expected=" & int_to_str(J+1) & + ", readback=" & int_to_str(INTEGER(TO_UINT(rd_data_mm_stimuli(c_word_w/2-1 DOWNTO 0)))) + SEVERITY ERROR; + mm_ok <= '0'; + END IF; + + IF TO_SINT(rd_data_mm_stimuli(c_word_w-1 DOWNTO c_word_w/2)) /= J+1 THEN + ASSERT FALSE + REPORT "MM Wrong weight for im" & + ", expected=" & int_to_str(J+1) & + ", readback=" & int_to_str(INTEGER(TO_UINT(rd_data_mm_stimuli(c_word_w-1 DOWNTO c_word_w/2)))) SEVERITY ERROR; mm_ok <= '0'; END IF; - - END LOOP; END LOOP; verify_addr_en <= '1'; -- enable second check @@ -190,25 +200,35 @@ ARCHITECTURE tb OF tb_beamformer IS END PROCESS; -- second check, activate weights and check effect on output + -- for this test snk_in must be (1+0j) addr_stimulus: PROCESS BEGIN proc_common_wait_until_high(dp_clk, verify_addr_en); REPORT "Start weights addr stimulus"; -- loop over all weights adresses - FOR i IN 0 TO g_nof_weights-1 LOOP - --REPORT "Start weights addr stimulus for weight " & int_to_str(i); - addr_stimulus_weight_addr <= TO_UVEC(i, ceil_log2(g_nof_weights)); - proc_common_wait_some_cycles(dp_clk, 5+ceil_log2(g_nof_inputs)); - IF TO_UINT(beamformer_weight_addr)*g_nof_inputs /= TO_UINT(beamformer_src_out.re) THEN + FOR I IN 0 TO g_nof_inputs-1 LOOP + FOR J IN 0 TO g_nof_weights-1 LOOP + addr_stimulus_weight_addr <= TO_UVEC(J, ceil_log2(g_nof_weights)); + proc_common_wait_some_cycles(dp_clk, 4+ceil_log2(g_nof_inputs)+1); + + mmf_mm_bus_rd(c_mm_file_ram_beamformer, I*g_nof_weights+J, rd_data_addr_stimuli, mm_clk); + IF TO_SINT(rd_data_addr_stimuli(c_word_w/2-1 DOWNTO 0))*g_nof_inputs*TO_SINT(snk_in.re) /= TO_SINT(beamformer_src_out.re) THEN ASSERT FALSE - REPORT "Beamformer wrong weights" & - ", expected=" & int_to_str(TO_UINT(beamformer_weight_addr)*g_nof_inputs) & - ", readback=" & int_to_str(TO_UINT(beamformer_src_out.re)) + REPORT "Beamformer wrong weights for re" & + ", expected=" & int_to_str(TO_SINT(rd_data_addr_stimuli(c_word_w/2-1 DOWNTO 0))*g_nof_inputs*TO_SINT(snk_in.re)) & + ", readback=" & int_to_str(TO_SINT(beamformer_src_out.re)) SEVERITY ERROR; addr_ok <= '0'; END IF; - - + IF TO_SINT(rd_data_addr_stimuli(c_word_w-1 DOWNTO c_word_w/2))*g_nof_inputs*TO_SINT(snk_in.re) /= TO_SINT(beamformer_src_out.im) THEN + ASSERT FALSE + REPORT "Beamformer wrong weights for im" & + ", expected=" & int_to_str(TO_SINT(rd_data_addr_stimuli(c_word_w-1 DOWNTO c_word_w/2))*g_nof_inputs*TO_SINT(snk_in.im)) & + ", readback=" & int_to_str(TO_SINT(beamformer_src_out.im)) + SEVERITY ERROR; + addr_ok <= '0'; + END IF; + END LOOP; END LOOP; verify_data_en <= '1'; -- enable third check WAIT; @@ -220,26 +240,46 @@ ARCHITECTURE tb OF tb_beamformer IS proc_common_wait_until_high(dp_clk, verify_data_en); REPORT "Start data stimulus"; - -- loop over weight address 1..2 - FOR I IN 1 TO 2 LOOP + -- set weights for test on addr 0 and 1 for all inputs + -- with weight (1+1j) output: re=0, im=(snk_in.re+snk_in.im)*nof_inputs + -- with weight (1+0j) output: re=snk_in.re*nof_inputs, im=snk_in.im*nof_inputs + FOR I IN 0 TO g_nof_inputs LOOP + mmf_mm_bus_wr(c_mm_file_ram_beamformer, I*g_nof_weights, 1*2**16+1, mm_clk); -- (1+1j) + mmf_mm_bus_wr(c_mm_file_ram_beamformer, I*g_nof_weights+1, 1, mm_clk); -- (1+0j) + END LOOP; + proc_common_wait_some_cycles(dp_clk, 1); + + -- loop over weight address 0..1 + FOR I IN 0 TO 1 LOOP data_stimulus_weight_addr <= TO_UVEC(I, ceil_log2(g_nof_weights)); - proc_common_wait_some_cycles(dp_clk, 2); - -- loop over input data.re 1..127 - FOR J IN 1 TO 127 LOOP - --REPORT "Start data stimulus with input " & int_to_str(i); - src_re_data <= TO_UVEC(J, g_data_w); - proc_common_wait_some_cycles(dp_clk, 4+ceil_log2(g_nof_inputs)+1); - IF TO_UINT(beamformer_weight_addr)*g_nof_inputs*J /= TO_UINT(beamformer_src_out.re) THEN - ASSERT FALSE - REPORT "Beamformer wrong data" & - ", expected=" & int_to_str(TO_UINT(beamformer_weight_addr)*g_nof_inputs*J) & - ", readback=" & int_to_str(TO_UINT(beamformer_src_out.re)) - SEVERITY ERROR; - data_ok <= '0'; - END IF; + proc_common_wait_some_cycles(dp_clk, 1); + -- loop over input data + FOR J IN min_snk_in_val TO max_snk_in_val LOOP + snk_re_data <= TO_SVEC(J, g_data_w); + snk_im_data <= TO_SVEC(J, g_data_w); + + proc_common_wait_some_cycles(dp_clk, 4+ceil_log2(g_nof_inputs)+1); + IF I*g_nof_inputs*J /= TO_SINT(beamformer_src_out.re) THEN + ASSERT FALSE + REPORT "Beamformer wrong data for re" & + ", expected=" & int_to_str(TO_SINT(beamformer_weight_addr)*g_nof_inputs*J) & + ", readback=" & int_to_str(TO_SINT(beamformer_src_out.re)) + SEVERITY ERROR; + data_ok <= '0'; + END IF; + -- (2-I): (I=0), doubles value for weight (1+1j) + IF g_nof_inputs*J*(2-I) /= TO_SINT(beamformer_src_out.im) THEN + ASSERT FALSE + REPORT "Beamformer wrong data for im" & + ", expected=" & int_to_str(g_nof_inputs*J*(2-I)) & + ", readback=" & int_to_str(TO_SINT(beamformer_src_out.im)) + SEVERITY ERROR; + data_ok <= '0'; + END IF; END LOOP; -- input data END LOOP; -- weigth address + proc_common_wait_some_cycles(dp_clk, 1); IF OK = '0' THEN REPORT "TEST WENT WRONG."; ELSE @@ -257,9 +297,7 @@ ARCHITECTURE tb OF tb_beamformer IS u_mm_file_ram_beamformer : ENTITY mm_lib.mm_file GENERIC MAP(c_mm_file_ram_beamformer) PORT MAP(mm_rst, mm_clk, ram_beamformer_mosi, ram_beamformer_miso); -- assign input_source to snk_in_arr - gen_beamformer_snk_in_arr : FOR i IN 0 TO g_nof_inputs-1 GENERATE - beamformer_snk_in_arr(i) <= src_in; -- Copy the block gen stream 'g_nof_inputs' times - END GENERATE; + beamformer_snk_in_arr <= (OTHERS => snk_in); u_beamformer : ENTITY work.beamformer GENERIC MAP ( diff --git a/libraries/dsp/beamformer/tb/vhdl/tb_tb_beamformer.vhd b/libraries/dsp/beamformer/tb/vhdl/tb_tb_beamformer.vhd index bde92449e7aa9357957a8a2bdcd4b8caf999e224..0b2aabd2627180f91c34014c4b5c5c6caf35f208 100644 --- a/libraries/dsp/beamformer/tb/vhdl/tb_tb_beamformer.vhd +++ b/libraries/dsp/beamformer/tb/vhdl/tb_tb_beamformer.vhd @@ -52,8 +52,6 @@ BEGIN -- do test for different number of inputs sim_i1_beamformer : ENTITY work.tb_beamformer GENERIC MAP (1, 1, 32, 8); sim_i2_beamformer : ENTITY work.tb_beamformer GENERIC MAP (2, 2, 32, 8); -sim_i3_beamformer : ENTITY work.tb_beamformer GENERIC MAP (3, 3, 32, 8); -sim_i8_beamformer : ENTITY work.tb_beamformer GENERIC MAP (4, 8, 32, 8); -sim_i32_beamformer : ENTITY work.tb_beamformer GENERIC MAP (5, 32, 32, 8); +sim_i32_beamformer : ENTITY work.tb_beamformer GENERIC MAP (3, 32, 32, 8); END tb; \ No newline at end of file