diff --git a/applications/lofar2/libraries/sdp/src/vhdl/sdp_crosslets_subband_select.vhd b/applications/lofar2/libraries/sdp/src/vhdl/sdp_crosslets_subband_select.vhd index 1b4d1753f9c49ad38b28390d1df7906969393848..94347aaca1aeccb0c0ed9efed5a10b24fbc668e3 100644 --- a/applications/lofar2/libraries/sdp/src/vhdl/sdp_crosslets_subband_select.vhd +++ b/applications/lofar2/libraries/sdp/src/vhdl/sdp_crosslets_subband_select.vhd @@ -61,7 +61,6 @@ ENTITY sdp_crosslets_subband_select IS reg_bsn_sync_scheduler_xsub_miso : OUT t_mem_miso := c_mem_miso_rst; out_crosslets_info : OUT STD_LOGIC_VECTOR(c_sdp_crosslets_info_reg_w-1 DOWNTO 0) - ); END sdp_crosslets_subband_select; @@ -105,6 +104,7 @@ ARCHITECTURE str OF sdp_crosslets_subband_select IS SIGNAL crosslets_info_reg : STD_LOGIC_VECTOR(c_sdp_crosslets_info_reg_w-1 DOWNTO 0) := (OTHERS => '0'); SIGNAL crosslets_info_reg_in : STD_LOGIC_VECTOR(c_sdp_crosslets_info_reg_w-1 DOWNTO 0) := (OTHERS => '0'); SIGNAL active_crosslets_info : STD_LOGIC_VECTOR(c_sdp_crosslets_info_reg_w-1 DOWNTO 0) := (OTHERS => '0'); + SIGNAL i_out_crosslets_info : STD_LOGIC_VECTOR(c_sdp_crosslets_info_reg_w-1 DOWNTO 0) := (OTHERS => '0'); BEGIN --------------------------------------------------------------- @@ -152,9 +152,11 @@ BEGIN in_reg => crosslets_info_reg_in, out_reg => crosslets_info_reg ); - p_set_unused_crosslets : PROCESS(crosslets_info_reg) + + p_set_unused_crosslets : PROCESS(i_out_crosslets_info) BEGIN - crosslets_info_reg_in <= crosslets_info_reg; -- Always use crosslets info 6:0 + step(@ index 15) + -- MM readback the currently active crosslets info, instead of the initial MM written crosslets_info_reg + crosslets_info_reg_in <= i_out_crosslets_info; -- Always use crosslets info 6:0 + step(@ index 15) -- Set crosslets 14:7 to -1 FOR I IN g_N_crosslets TO c_sdp_mm_reg_crosslets_info.nof_dat - 2 LOOP crosslets_info_reg_in((I+1) * c_sdp_crosslets_index_w - 1 DOWNTO I * c_sdp_crosslets_index_w ) <= TO_SVEC(-1, c_sdp_crosslets_index_w); @@ -309,6 +311,7 @@ BEGIN gen_crosslets_info : FOR I IN 0 TO g_N_crosslets-1 GENERATE active_crosslets_info((I+1)*c_sdp_crosslets_index_w-1 DOWNTO I*c_sdp_crosslets_index_w) <= TO_UVEC(r.offsets(I), c_sdp_crosslets_index_w); END GENERATE; + -- pipeline for alignment with sync u_common_pipeline : ENTITY common_lib.common_pipeline GENERIC MAP( @@ -321,9 +324,11 @@ BEGIN clk => dp_clk, in_en => row_sosi.sync, in_dat => active_crosslets_info, - out_dat => out_crosslets_info + out_dat => i_out_crosslets_info ); + out_crosslets_info <= i_out_crosslets_info; + --------------------------------------------------------------- -- Out sosi pipeline --------------------------------------------------------------- diff --git a/applications/lofar2/libraries/sdp/tb/vhdl/tb_sdp_crosslets_subband_select.vhd b/applications/lofar2/libraries/sdp/tb/vhdl/tb_sdp_crosslets_subband_select.vhd index 2b6912dc420207a7adb5bd133be40546074c798c..d58cd1b58e1de6fbc64612736e5f3bad2ce48e72 100644 --- a/applications/lofar2/libraries/sdp/tb/vhdl/tb_sdp_crosslets_subband_select.vhd +++ b/applications/lofar2/libraries/sdp/tb/vhdl/tb_sdp_crosslets_subband_select.vhd @@ -55,28 +55,31 @@ ARCHITECTURE tb OF tb_sdp_crosslets_subband_select IS CONSTANT c_rl : NATURAL := 1; CONSTANT c_nof_sync : NATURAL := 5; CONSTANT c_nof_block_per_sync : NATURAL := 4; - CONSTANT c_nof_ch_in : NATURAL := 1024; -- nof input words per block, identical for all input streams. CONSTANT c_dsp_data_w : NATURAL := c_sdp_W_subband; - CONSTANT c_nof_ch_sel_row : NATURAL := c_sdp_P_pfb; CONSTANT c_N_crosslets : NATURAL := 2; - CONSTANT c_ch_sel_offsets : t_natural_arr(0 TO c_N_crosslets-1) := (0, 15); - CONSTANT c_nof_ch_sel_col : NATURAL := c_sdp_Q_fft; -- nof of sequential collums to select per row. - CONSTANT c_ch_sel_step : NATURAL := 3; -- offset step size to increase per sync interval + CONSTANT c_crosslet_offsets : t_natural_arr(0 TO c_N_crosslets-1) := (0, 15); + CONSTANT c_crosslet_step : NATURAL := 3; -- offset step size to increase per sync interval + CONSTANT c_nof_ch_in : NATURAL := 1024; -- nof input words per block, identical for all input streams. + CONSTANT c_nof_ch_sel_row : NATURAL := c_sdp_P_pfb; + CONSTANT c_nof_ch_sel_col : NATURAL := c_sdp_Q_fft; -- nof of sequential columns to select per row. CONSTANT c_nof_ch_sel : NATURAL := c_N_crosslets*c_nof_ch_sel_col*c_nof_ch_sel_row; + CONSTANT c_ctrl_interval_size : NATURAL := c_nof_block_per_sync * c_nof_ch_in; CONSTANT c_scheduled_bsn : NATURAL := 11; CONSTANT c_nof_block_dly : NATURAL := c_nof_block_per_sync; + SIGNAL tb_end : STD_LOGIC; SIGNAL rst : STD_LOGIC; SIGNAL clk : STD_LOGIC := '1'; SIGNAL mm_clk : STD_LOGIC := '1'; - SIGNAL tb_end : STD_LOGIC; - - SIGNAL mm_mosi : t_mem_mosi; - SIGNAL mm_miso : t_mem_miso; - + + SIGNAL mm_mosi : t_mem_mosi := c_mem_mosi_rst; + SIGNAL mm_miso : t_mem_miso; + SIGNAL rd_crosslet_offsets : t_natural_arr(0 TO c_N_crosslets-1) := (0, 15); + SIGNAL rd_crosslet_step : NATURAL; + SIGNAL mm_trigger_mosi : t_mem_mosi := c_mem_mosi_rst; SIGNAL mm_trigger_miso : t_mem_miso; @@ -91,32 +94,74 @@ ARCHITECTURE tb OF tb_sdp_crosslets_subband_select IS SIGNAL out_sosi : t_dp_sosi; - SIGNAL exp_crosslets_info : STD_LOGIC_VECTOR(c_sdp_crosslets_info_reg_w-1 DOWNTO 0) := (OTHERS => '0'); - SIGNAL out_crosslets_info : STD_LOGIC_VECTOR(c_sdp_crosslets_info_reg_w-1 DOWNTO 0) := (OTHERS => '0'); + SIGNAL exp_crosslets_info_slv : STD_LOGIC_VECTOR(c_sdp_crosslets_info_reg_w-1 DOWNTO 0) := (OTHERS => '0'); + SIGNAL out_crosslets_info_slv : STD_LOGIC_VECTOR(c_sdp_crosslets_info_reg_w-1 DOWNTO 0) := (OTHERS => '0'); + SIGNAL exp_crosslets_info_rec : t_sdp_crosslets_info; + SIGNAL out_crosslets_info_rec : t_sdp_crosslets_info; + BEGIN clk <= (NOT clk) OR tb_end AFTER c_clk_period/2; mm_clk <= (NOT mm_clk) OR tb_end AFTER c_mm_clk_period/2; rst <= '1', '0' AFTER c_clk_period*7; - p_select_stimuli : PROCESS + p_mm_stimuli : PROCESS VARIABLE k : NATURAL; BEGIN - proc_common_wait_until_low(mm_clk, rst); proc_common_wait_some_cycles(mm_clk, 50); -- Give dut some time to start - -- BSN Scheduler + + -- Set BSN sync scheduler proc_mem_mm_bus_wr(1, c_ctrl_interval_size, mm_clk, mm_trigger_miso, mm_trigger_mosi); proc_mem_mm_bus_wr(2, c_scheduled_bsn, mm_clk, mm_trigger_miso, mm_trigger_mosi); proc_mem_mm_bus_wr(3, 0, mm_clk, mm_trigger_miso, mm_trigger_mosi); proc_mem_mm_bus_wr(0, 1, mm_clk, mm_trigger_miso, mm_trigger_mosi); --enable + -- Set crosslet info + FOR I IN 0 TO c_N_crosslets-1 LOOP + proc_mem_mm_bus_wr(I, c_crosslet_offsets(I), mm_clk, mm_miso, mm_mosi); --offsets + END LOOP; + proc_mem_mm_bus_wr(15, c_crosslet_step, mm_clk, mm_miso, mm_mosi); --step + proc_common_wait_cross_clock_domain_latency(c_clk_period, c_mm_clk_period); - -- crosslet info + -- Verify that MM reads the active crosslets_info + -- a) Readback crosslet info after rst release + FOR I IN 0 TO c_N_crosslets-1 LOOP + proc_mem_mm_bus_rd(I, mm_clk, mm_miso, mm_mosi); --offsets + proc_mem_mm_bus_rd_latency(1, mm_clk); + rd_crosslet_offsets(I) <= TO_UINT(mm_miso.rddata(c_word_w-1 DOWNTO 0)); + END LOOP; + proc_mem_mm_bus_rd(15, mm_clk, mm_miso, mm_mosi); + proc_mem_mm_bus_rd_latency(1, mm_clk); + rd_crosslet_step <= TO_UINT(mm_miso.rddata(c_word_w-1 DOWNTO 0)); + proc_common_wait_some_cycles(mm_clk, 1); + -- Verify that readback crosslet info is active crosslets_info FOR I IN 0 TO c_N_crosslets-1 LOOP - proc_mem_mm_bus_wr(I, c_ch_sel_offsets(I), mm_clk, mm_miso, mm_mosi); --offsets + ASSERT rd_crosslet_offsets(I) = 0 REPORT "Wrong crosslet offset after rst." SEVERITY ERROR; END LOOP; - proc_mem_mm_bus_wr(15, c_ch_sel_step, mm_clk, mm_miso, mm_mosi); --step + ASSERT rd_crosslet_step = 0 REPORT "Wrong crosslet step after rst." SEVERITY ERROR; + + -- b) Read crosslet_info in every sync interval + WHILE TRUE LOOP + proc_common_wait_until_hi_lo(clk, out_sosi.sync); + proc_common_wait_cross_clock_domain_latency(c_clk_period, c_mm_clk_period); + -- Readback crosslet info + FOR I IN 0 TO c_N_crosslets-1 LOOP + proc_mem_mm_bus_rd(I, mm_clk, mm_miso, mm_mosi); --offsets + proc_mem_mm_bus_rd_latency(1, mm_clk); + rd_crosslet_offsets(I) <= TO_UINT(mm_miso.rddata(c_word_w-1 DOWNTO 0)); + END LOOP; + proc_mem_mm_bus_rd(15, mm_clk, mm_miso, mm_mosi); + proc_mem_mm_bus_rd_latency(1, mm_clk); + rd_crosslet_step <= TO_UINT(mm_miso.rddata(c_word_w-1 DOWNTO 0)); + proc_common_wait_some_cycles(mm_clk, 1); + -- Verify that readback crosslet info is active crosslets_info + FOR I IN 0 TO c_N_crosslets-1 LOOP + ASSERT rd_crosslet_offsets(I) = exp_crosslets_info_rec.offset_arr(I) REPORT "Wrong active crosslet offset in output sync interval." SEVERITY ERROR; + END LOOP; + ASSERT rd_crosslet_step = exp_crosslets_info_rec.step REPORT "Wrong active crosslet step in output sync interval." SEVERITY ERROR; + END LOOP; + WAIT; END PROCESS; @@ -179,16 +224,16 @@ BEGIN exp_sosi <= c_dp_sosi_rst; WAIT UNTIL rising_edge(out_sosi.sop); - exp_crosslets_info(c_sdp_crosslets_info_reg_w-1 DOWNTO c_sdp_crosslets_info_reg_w - c_sdp_crosslets_index_w) <= TO_UVEC(c_ch_sel_step, c_sdp_crosslets_index_w); + exp_crosslets_info_slv(c_sdp_crosslets_info_reg_w-1 DOWNTO c_sdp_crosslets_info_reg_w - c_sdp_crosslets_index_w) <= TO_UVEC(c_crosslet_step, c_sdp_crosslets_index_w); FOR C IN 0 TO c_nof_ch_sel_col-1 LOOP - exp_crosslets_info((C+1)*c_sdp_crosslets_index_w-1 DOWNTO C*c_sdp_crosslets_index_w) <= TO_UVEC(c_ch_sel_offsets(C) + v_sync_ix * c_ch_sel_step, c_sdp_crosslets_index_w); + exp_crosslets_info_slv((C+1)*c_sdp_crosslets_index_w-1 DOWNTO C*c_sdp_crosslets_index_w) <= TO_UVEC(c_crosslet_offsets(C) + v_sync_ix * c_crosslet_step, c_sdp_crosslets_index_w); END LOOP; FOR J IN 0 TO c_nof_ch_sel-1 LOOP v_offset := J / (c_nof_ch_sel_col*c_nof_ch_sel_row); v_col := J MOD c_nof_ch_sel_col; v_row := (J/c_nof_ch_sel_col) MOD c_nof_ch_sel_row; - v_k := c_nof_ch_sel_col * v_sync_ix * c_ch_sel_step; + v_k := c_nof_ch_sel_col * v_sync_ix * c_crosslet_step; exp_sosi <= c_dp_sosi_rst; exp_sosi.valid <= '1'; @@ -202,8 +247,8 @@ BEGIN exp_sosi.eop <= '1'; END IF; - exp_sosi.re <= RESIZE_DP_DSP_DATA(TO_DP_DSP_DATA( (I + c_nof_block_dly) * c_nof_ch_in + v_k + c_nof_ch_sel_col*c_ch_sel_offsets(v_offset) + v_col + v_row*2**5)(c_sdp_W_crosslet-1 DOWNTO 0)); - exp_sosi.im <= RESIZE_DP_DSP_DATA(TO_DP_DSP_DATA(1+ (I + c_nof_block_dly) * c_nof_ch_in + v_k + c_nof_ch_sel_col*c_ch_sel_offsets(v_offset) + v_col + v_row*2**5)(c_sdp_W_crosslet-1 DOWNTO 0)); + exp_sosi.re <= RESIZE_DP_DSP_DATA(TO_DP_DSP_DATA( (I + c_nof_block_dly) * c_nof_ch_in + v_k + c_nof_ch_sel_col*c_crosslet_offsets(v_offset) + v_col + v_row*2**5)(c_sdp_W_crosslet-1 DOWNTO 0)); + exp_sosi.im <= RESIZE_DP_DSP_DATA(TO_DP_DSP_DATA(1+ (I + c_nof_block_dly) * c_nof_ch_in + v_k + c_nof_ch_sel_col*c_crosslet_offsets(v_offset) + v_col + v_row*2**5)(c_sdp_W_crosslet-1 DOWNTO 0)); proc_common_wait_some_cycles(clk, 1); END LOOP; @@ -219,7 +264,7 @@ BEGIN ASSERT out_sosi.sop = exp_sosi.sop REPORT "Wrong out_sosi.sop" SEVERITY ERROR; ASSERT out_sosi.eop = exp_sosi.eop REPORT "Wrong out_sosi.eop" SEVERITY ERROR; ASSERT out_sosi.sync = exp_sosi.sync REPORT "Wrong out_sosi.sync" SEVERITY ERROR; - ASSERT out_crosslets_info = exp_crosslets_info REPORT "Wrong out_crosslets_info" SEVERITY ERROR; + ASSERT out_crosslets_info_slv = exp_crosslets_info_slv REPORT "Wrong out_crosslets_info_slv" SEVERITY ERROR; IF exp_sosi.valid = '1' THEN ASSERT out_sosi.re = exp_sosi.re REPORT "Wrong out_sosi.re" SEVERITY ERROR; ASSERT out_sosi.im = exp_sosi.im REPORT "Wrong out_sosi.im" SEVERITY ERROR; @@ -249,7 +294,11 @@ BEGIN in_sosi_arr => in_sosi_arr, out_sosi => out_sosi, - out_crosslets_info => out_crosslets_info + out_crosslets_info => out_crosslets_info_slv ); + -- Map crosslets_info slv to record for easier view in Wave window + exp_crosslets_info_rec <= func_sdp_map_crosslets_info(exp_crosslets_info_slv); + out_crosslets_info_rec <= func_sdp_map_crosslets_info(out_crosslets_info_slv); + END tb;