diff --git a/libraries/dsp/beamformer/hdllib.cfg b/libraries/dsp/beamformer/hdllib.cfg index 797f20092d3fe00b9e67852e286e608f667e457d..8bfd35cabbd50720afe8714a9c81bf54d9c4e7ad 100644 --- a/libraries/dsp/beamformer/hdllib.cfg +++ b/libraries/dsp/beamformer/hdllib.cfg @@ -1,7 +1,7 @@ hdl_lib_name = beamformer hdl_library_clause_name = beamformer_lib hdl_lib_uses_synth = common common_mult technology mm dp -hdl_lib_uses_sim = +hdl_lib_uses_sim = diag hdl_lib_technology = synth_files = diff --git a/libraries/dsp/beamformer/src/vhdl/beamformer.vhd b/libraries/dsp/beamformer/src/vhdl/beamformer.vhd index ad850117a3f80eb80ed8dafee92e15693e926c98..64137f5a789665ea121fce22ca0ed072bdc7167e 100644 --- a/libraries/dsp/beamformer/src/vhdl/beamformer.vhd +++ b/libraries/dsp/beamformer/src/vhdl/beamformer.vhd @@ -124,7 +124,7 @@ BEGIN GENERIC MAP ( g_technology => g_technology, g_ram => c_common_ram_crw_crw_ram, - g_init_file => g_weights_file & "_" & NATURAL'IMAGE(i) & ".hex" + g_init_file => sel_a_b(g_weights_file="UNUSED", "UNUSED", g_weights_file & "_" & NATURAL'IMAGE(i) & ".hex") ) PORT MAP ( rst_a => mm_rst, diff --git a/libraries/dsp/beamformer/tb/vhdl/tb_beamformer.vhd b/libraries/dsp/beamformer/tb/vhdl/tb_beamformer.vhd index 96e61120495555a62541f2e987e57ead3637ed55..5d4021508ea610573978115aae47077e6028546a 100644 --- a/libraries/dsp/beamformer/tb/vhdl/tb_beamformer.vhd +++ b/libraries/dsp/beamformer/tb/vhdl/tb_beamformer.vhd @@ -22,21 +22,26 @@ -- Author: -- . Daniel van der Schuur -- Purpose: --- . +-- . -- Description: --- . +-- . -LIBRARY IEEE, common_lib, dp_lib, technology_lib; +LIBRARY IEEE, common_lib, dp_lib, technology_lib, diag_lib, mm_lib; USE IEEE.std_logic_1164.ALL; USE IEEE.numeric_std.ALL; USE common_lib.common_pkg.ALL; +USE common_lib.common_str_pkg.ALL; USE dp_lib.dp_stream_pkg.ALL; +USE diag_lib.diag_pkg.ALL; USE common_lib.tb_common_pkg.ALL; USE technology_lib.technology_select_pkg.ALL; USE common_lib.common_mem_pkg.ALL; +USE mm_lib.mm_file_unb_pkg.ALL; +USE mm_lib.mm_file_pkg.ALL; ENTITY tb_beamformer IS GENERIC ( + g_tb_index : NATURAL := 0; -- use different index to avoid MM file conflict in multi tb g_technology : NATURAL := c_tech_select_default; g_nof_inputs : NATURAL := 2; g_nof_weights : NATURAL := 32; @@ -49,55 +54,180 @@ ARCHITECTURE tb OF tb_beamformer IS ----------------------------------------------------------------------------- -- General ----------------------------------------------------------------------------- - CONSTANT c_dp_clk_period : TIME := 5 ns; - CONSTANT c_mm_clk_period : TIME := 25 ns; + CONSTANT c_dp_clk_period : TIME := 5 ns; + CONSTANT c_mm_clk_period : TIME := 25 ns; + CONSTANT c_stimulus_period : TIME := 100 ns; SIGNAL tb_end : STD_LOGIC := '0'; SIGNAL dp_clk : STD_LOGIC := '1'; SIGNAL dp_rst : STD_LOGIC; SIGNAL mm_clk : STD_LOGIC := '1'; SIGNAL mm_rst : STD_LOGIC; + SIGNAL OK : STD_LOGIC := '1'; + SIGNAL verify_mm_en : STD_LOGIC := '1'; + SIGNAL verify_input_en : STD_LOGIC := '0'; + SIGNAL verify_sum_en : STD_LOGIC := '0'; + + ----------------------------------------------------------------------------- + -- Block generator + ----------------------------------------------------------------------------- + CONSTANT c_bg_block_size : NATURAL := g_nof_weights; + CONSTANT c_bg_gapsize : NATURAL := c_bg_block_size; + CONSTANT c_bg_blocks_per_sync : NATURAL := 10; --not used + CONSTANT c_bg_ctrl : t_diag_block_gen := ('1', -- enable + '0', -- enable_sync + TO_UVEC( c_bg_block_size, c_diag_bg_samples_per_packet_w), + TO_UVEC(c_bg_blocks_per_sync, c_diag_bg_blocks_per_sync_w), + TO_UVEC( c_bg_gapsize, c_diag_bg_gapsize_w), + TO_UVEC( 0, c_diag_bg_mem_low_adrs_w), + TO_UVEC( c_bg_block_size-1, c_diag_bg_mem_high_adrs_w), + TO_UVEC( 0, c_diag_bg_bsn_init_w)); + + -- 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 block_gen_src_out_arr : t_dp_sosi_arr(1-1 DOWNTO 0); ----------------------------------------------------------------------------- -- beamformer ----------------------------------------------------------------------------- + SIGNAL ram_beamformer_mosi : t_mem_mosi := c_mem_mosi_rst; + SIGNAL ram_beamformer_miso : t_mem_miso := c_mem_miso_rst; + + SIGNAL beamformer_snk_in_arr : t_dp_sosi_arr(g_nof_inputs-1 DOWNTO 0); SIGNAL beamformer_src_out : t_dp_sosi; SIGNAL beamformer_weight_addr : STD_LOGIC_VECTOR(ceil_log2(g_nof_weights)-1 DOWNTO 0); + SIGNAL rd_data : STD_LOGIC_VECTOR(c_word_w-1 DOWNTO 0); + BEGIN ----------------------------------------------------------------------------- -- Clocks and reset - ----------------------------------------------------------------------------- + ------------------------------------------------------------------------------- dp_clk <= NOT dp_clk OR tb_end AFTER c_dp_clk_period/2; dp_rst <= '1', '0' AFTER c_dp_clk_period*7; mm_clk <= NOT mm_clk OR tb_end AFTER c_mm_clk_period/2; mm_rst <= '1', '0' AFTER c_mm_clk_period*7; + + mm_stimulus: PROCESS + BEGIN + IF verify_mm_en = '1' THEN + + proc_common_wait_until_low(mm_clk, mm_rst); + proc_common_wait_until_low(dp_clk, dp_rst); + proc_common_wait_some_cycles(dp_clk, 10); + + 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); + 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 UNSIGNED(rd_data) /= J THEN + OK <= '0'; + END IF; + ASSERT TO_UINT(rd_data)=J + REPORT "MM Wrong weight, expected=" & int_to_str(J) & ", readback=" & int_to_str(INTEGER(TO_UINT(rd_data))) + SEVERITY ERROR; + + END LOOP; + END LOOP; + verify_sum_en <= '1'; + END IF; + verify_mm_en <= '0'; + END PROCESS; + + + stimulus: PROCESS + BEGIN + proc_common_wait_until_high(dp_clk, verify_sum_en); + -- loop over all weights adresses + FOR i IN 0 TO g_nof_weights-1 LOOP + beamformer_weight_addr <= STD_LOGIC_VECTOR(TO_UNSIGNED(i, ceil_log2(g_nof_weights))); + WAIT FOR c_stimulus_period; + proc_common_wait_until_high(dp_clk, beamformer_src_out.valid); + IF UNSIGNED(beamformer_weight_addr)*g_nof_inputs /= UNSIGNED(beamformer_src_out.re) THEN + OK <= '0'; + END IF; + ASSERT UNSIGNED(beamformer_weight_addr)*g_nof_inputs = UNSIGNED(beamformer_src_out.re) + REPORT "Beamformer wrong weights" & + ", expected=" & int_to_str(TO_SINT(beamformer_weight_addr)*g_nof_inputs) & + ", readback=" & int_to_str(TO_SINT(beamformer_src_out.re)) + SEVERITY ERROR; + END LOOP; + tb_end <= '1'; -- end test + WAIT; + END PROCESS; + + + + ----------------------------------------------------------------------------- + -- Block generator: + -- . X pol = complex( 1, 1) + -- . Y pol = complex(-1,-1) + ----------------------------------------------------------------------------- + u_mms_diag_block_gen : ENTITY diag_lib.mms_diag_block_gen + GENERIC MAP ( + g_nof_streams => 1, + g_buf_dat_w => g_data_w, + g_buf_addr_w => ceil_log2(TO_UINT(c_bg_ctrl.samples_per_packet)), + g_file_name_prefix => "hex/mms_diag_block_gen", + g_diag_block_gen_rst => c_bg_ctrl + ) + PORT MAP ( + mm_clk => mm_clk, + mm_rst => mm_rst, + + dp_clk => dp_clk, + dp_rst => dp_rst, + + out_sosi_arr => block_gen_src_out_arr + ); + ----------------------------------------------------------------------------- -- beamformer for each TAB - ----------------------------------------------------------------------------- + ----------------------------------------------------------------------------- + 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); + + gen_arts_tab_beamformer_snk_in_arr : FOR i IN 0 TO g_nof_inputs-1 GENERATE + beamformer_snk_in_arr(i) <= block_gen_src_out_arr(0); -- Copy the block gen stream 'g_nof_inputs' times + END GENERATE; + u_beamformer : ENTITY work.beamformer GENERIC MAP ( + g_technology => g_technology, g_nof_inputs => g_nof_inputs, g_nof_weights => g_nof_weights, - g_data_w => g_data_w + g_data_w => g_data_w, + g_weights_file => "UNUSED" ) PORT MAP ( dp_clk => dp_clk, dp_rst => dp_rst, - mm_clk => mm_clk, mm_rst => mm_rst, + ram_mosi => ram_beamformer_mosi, + ram_miso => ram_beamformer_miso, + weight_addr => beamformer_weight_addr, snk_in_arr => beamformer_snk_in_arr, src_out => beamformer_src_out ); + END tb;