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/src/vhdl/sdp_pkg.vhd b/applications/lofar2/libraries/sdp/src/vhdl/sdp_pkg.vhd index 68f4fc8427f64a11797b02f60b4c58f367172652..b96a84e1fdf6af18be24f5692ae1af1c6bb08246 100644 --- a/applications/lofar2/libraries/sdp/src/vhdl/sdp_pkg.vhd +++ b/applications/lofar2/libraries/sdp/src/vhdl/sdp_pkg.vhd @@ -78,7 +78,7 @@ PACKAGE sdp_pkg is CONSTANT c_sdp_N_sub : NATURAL := 512; CONSTANT c_sdp_N_sync_rcu : NATURAL := 1; CONSTANT c_sdp_N_taps : NATURAL := 16; - CONSTANT c_sdp_P_sq : NATURAL := 9; + CONSTANT c_sdp_P_sq : NATURAL := 9; -- = N_pn / 2 + 1 CONSTANT c_sdp_Q_fft : NATURAL := 2; CONSTANT c_sdp_S_pn : NATURAL := 12; CONSTANT c_sdp_S_rcu : NATURAL := 3; @@ -116,10 +116,10 @@ PACKAGE sdp_pkg is CONSTANT c_sdp_N_sync_jesd : NATURAL := c_sdp_S_pn * c_sdp_N_sync_rcu / c_sdp_S_rcu; -- = 4, nof JESD IP sync outputs per PN CONSTANT c_sdp_A_pn : NATURAL := c_sdp_S_pn / c_sdp_N_pol; -- = 6 dual pol antenna per PN, is 6 signal input pairs CONSTANT c_sdp_P_pfb : NATURAL := c_sdp_S_pn / c_sdp_Q_fft; -- = 6 PFB units, for 6 signal input pairs - CONSTANT c_sdp_T_adc : TIME := (10**6 / c_sdp_f_adc_MHz) * 1 ps; - CONSTANT c_sdp_T_sub : TIME := c_sdp_N_fft * c_sdp_T_adc; + CONSTANT c_sdp_T_adc : TIME := (10**6 / c_sdp_f_adc_MHz) * 1 ps; -- = 5 ns @ 200MHz + CONSTANT c_sdp_T_sub : TIME := c_sdp_N_fft * c_sdp_T_adc; -- = 5.12 us @ 200MHz CONSTANT c_sdp_W_bf_product : NATURAL := c_sdp_W_subband + c_sdp_W_bf_weight -1; - CONSTANT c_sdp_X_sq : NATURAL := c_sdp_S_pn * c_sdp_S_pn; + CONSTANT c_sdp_X_sq : NATURAL := c_sdp_S_pn * c_sdp_S_pn; -- = 144 CONSTANT c_sdp_block_period : NATURAL := c_sdp_N_fft * 1000 / c_sdp_f_adc_MHz; -- = 5120 [ns] CONSTANT c_sdp_N_beamlets_sdp : NATURAL := c_sdp_N_beamsets * c_sdp_S_sub_bf; -- = 976 CONSTANT c_sdp_unit_sub_weight : NATURAL := 2**c_sdp_W_sub_weight_fraction; -- 2**13, so range +-4.0 for 16 bit signed weight diff --git a/applications/lofar2/libraries/sdp/src/vhdl/sdp_statistics_offload.vhd b/applications/lofar2/libraries/sdp/src/vhdl/sdp_statistics_offload.vhd index 296222df4dc16c22a0e6cb9934415f86e7326f18..73441a61938e0d25bc5d4ef85714fef5b4d9845c 100644 --- a/applications/lofar2/libraries/sdp/src/vhdl/sdp_statistics_offload.vhd +++ b/applications/lofar2/libraries/sdp/src/vhdl/sdp_statistics_offload.vhd @@ -82,6 +82,17 @@ -- BST (Xh, Xl), (Yh, Yl), 2 keep X, Y parts order -- XST (Rh, Rl), (Ih, Il), 2 keep Re, Im parts order -- +-- . g_P_sq and nof_used_P_sq +-- The g_P_sq defines the number of correlator cells that is available in +-- the SDPFW. Use generic to support P_sq = 1 for one node and P_sq = +-- c_sdp_P_sq for multiple nodes (with ring). +-- The nof_used_P_sq is the number of correlator cells that is actually +-- used and that will output XST packets. Unused correlator cells yield +-- zero data that should not be output. The nof_used_P_sq is the smallest +-- of g_P_sq and ring_info.N_rn/2 + 1. In this way the XST offload can work +-- with g_P_sq = 1 when N_rn > 1 and also in a ring with N_rn < N_pn when +-- g_P_sq = 9. +-- ------------------------------------------------------------------------------- LIBRARY IEEE, common_lib, mm_lib, dp_lib, ring_lib; @@ -99,8 +110,8 @@ ENTITY sdp_statistics_offload IS g_statistics_type : STRING := "SST"; g_offload_time : NATURAL := c_sdp_offload_time; g_beamset_id : NATURAL := 0; - g_P_sq : NATURAL := c_sdp_P_sq; -- use generic to support P_sq = 1 for one node and P_sq = c_sdp_P_sq for multiple nodes (with ring) - g_crosslets_direction : NATURAL := 1; -- > 0 for crosslet transport in positive direction (incrementing RN), else 0 for negative direction + g_P_sq : NATURAL := c_sdp_P_sq; -- number of available correlator cells, + g_crosslets_direction : NATURAL := 1; -- > 0 for crosslet transport in positive direction (incrementing RN), else 0 for negative direction g_reverse_word_order : BOOLEAN := TRUE -- default word order is MSB after LSB, we need to stream LSB after MSB. ); PORT ( @@ -198,7 +209,10 @@ ARCHITECTURE str OF sdp_statistics_offload IS SIGNAL remote_pn : NATURAL; -- index of remote node in antenna band SIGNAL remote_si_offset : NATURAL; -- index of first signal input on remote node SIGNAL nof_cycles_dly : NATURAL; -- trigger_offload delay for this node - SIGNAL nof_packets : NATURAL; -- nof packets per integration interval + SIGNAL offset_rn : NATURAL; -- = ring_info.O_rn, GN index of first ring node + SIGNAL nof_rn : NATURAL; -- = ring_info.N_rn, number of GN in the ring + SIGNAL nof_used_P_sq : NATURAL; -- number of used correlator cells <= g_P_sq (is number of available correlator cells) + SIGNAL nof_packets : NATURAL; -- nof XST offload packets per integration interval SIGNAL data_id_rec : t_sdp_stat_data_id; SIGNAL data_id_slv : STD_LOGIC_VECTOR(31 DOWNTO 0) := (OTHERS => '0'); @@ -293,17 +307,24 @@ BEGIN END PROCESS; -- Derive and pipeline dynamic parameters - gn_index_reg <= gn_index WHEN rising_edge(dp_clk); - pn_index <= func_sdp_gn_index_to_pn_index(gn_index) WHEN rising_edge(dp_clk); - rn_index <= gn_index - TO_UINT(ring_info.O_rn) WHEN rising_edge(dp_clk); - local_si_offset <= pn_index * c_sdp_S_pn WHEN rising_edge(dp_clk); - nof_cycles_dly <= gn_index * g_offload_time WHEN rising_edge(dp_clk); - nof_packets <= func_sdp_get_stat_nof_packets(g_statistics_type, c_sdp_S_pn, g_P_sq, r.nof_crosslets) WHEN rising_edge(dp_clk); - - remote_rn <= func_ring_nof_hops_to_source_rn(r.instance_count, rn_index, TO_UINT(ring_info.N_rn), g_crosslets_direction); - remote_gn <= TO_UINT(ring_info.O_rn) + remote_rn; - remote_pn <= func_sdp_gn_index_to_pn_index(remote_gn) WHEN rising_edge(dp_clk); - remote_si_offset <= remote_pn * c_sdp_S_pn WHEN rising_edge(dp_clk); + p_parameters : PROCESS(dp_clk) + BEGIN + IF rising_edge(dp_clk) THEN + gn_index_reg <= gn_index; + pn_index <= func_sdp_gn_index_to_pn_index(gn_index_reg); + offset_rn <= TO_UINT(ring_info.O_rn); + rn_index <= gn_index_reg - offset_rn; + local_si_offset <= pn_index * c_sdp_S_pn; + nof_cycles_dly <= gn_index_reg * g_offload_time; + nof_rn <= TO_UINT(ring_info.N_rn); + nof_used_P_sq <= smallest(nof_rn / 2 + 1, g_P_sq); + nof_packets <= func_sdp_get_stat_nof_packets(g_statistics_type, c_sdp_S_pn, nof_used_P_sq, r.nof_crosslets); + remote_rn <= func_ring_nof_hops_to_source_rn(r.instance_count, rn_index, nof_rn, g_crosslets_direction); + remote_gn <= offset_rn + remote_rn; + remote_pn <= func_sdp_gn_index_to_pn_index(remote_gn); + remote_si_offset <= remote_pn * c_sdp_S_pn; + END IF; + END PROCESS; -- Assign application header data_id for different statistic types, use -- GENERATE to keep unused fields at 0. 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; diff --git a/applications/lofar2/libraries/sdp/tb/vhdl/tb_sdp_statistics_offload.vhd b/applications/lofar2/libraries/sdp/tb/vhdl/tb_sdp_statistics_offload.vhd index e586a5294dfdbad484a746f6198468e1b5abc133..d3e8ea79f510f428d3550ecc8ccefe21028da6e8 100644 --- a/applications/lofar2/libraries/sdp/tb/vhdl/tb_sdp_statistics_offload.vhd +++ b/applications/lofar2/libraries/sdp/tb/vhdl/tb_sdp_statistics_offload.vhd @@ -54,17 +54,17 @@ USE work.tb_sdp_pkg.ALL; ENTITY tb_sdp_statistics_offload IS GENERIC ( -- All - g_statistics_type : STRING := "SST"; + g_statistics_type : STRING := "XST"; g_offload_time : NATURAL := 50; g_reverse_word_order : BOOLEAN := TRUE; -- when TRUE then stream LSB word after MSB word. - g_gn_index : NATURAL := 5; -- global node (GN) index, must be in range(O_rn, O_rn + N_rn), use > 0 to see effect of g_offload_time + g_gn_index : NATURAL := 0; -- global node (GN) index, must be in range(O_rn, O_rn + N_rn), use > 0 to see effect of g_offload_time -- BST - g_beamset_id : NATURAL := 1; -- < c_sdp_N_beamsets + g_beamset_id : NATURAL := 0; -- < c_sdp_N_beamsets -- XST - g_O_rn : NATURAL := 4; -- GN index of first ring node (RN) + g_O_rn : NATURAL := 0; -- GN index of first ring node (RN) g_N_rn : NATURAL := 8; -- <= c_sdp_N_rn_max = 16, number of nodes in ring - g_P_sq : NATURAL := 4; -- <= c_sdp_P_sq - g_nof_crosslets : NATURAL := 3; -- <= c_sdp_N_crosslets_max + g_P_sq : NATURAL := 9; -- <= c_sdp_P_sq, nof available correlator cells + g_nof_crosslets : NATURAL := 7; -- <= c_sdp_N_crosslets_max g_crosslets_direction : NATURAL := 1 -- > 0 for crosslet transport in positive direction (incrementing RN), else 0 for negative direction ); END tb_sdp_statistics_offload; @@ -117,7 +117,8 @@ ARCHITECTURE tb OF tb_sdp_statistics_offload IS -- Crosslets settings CONSTANT c_mm_nof_crosslets : STD_LOGIC_VECTOR(c_sdp_nof_crosslets_reg_w-1 DOWNTO 0) := TO_UVEC(g_nof_crosslets, c_sdp_nof_crosslets_reg_w); - CONSTANT c_mm_nof_packets : NATURAL := func_sdp_get_stat_nof_packets(g_statistics_type, c_sdp_S_pn, g_P_sq, g_nof_crosslets); + CONSTANT c_nof_used_P_sq : NATURAL := smallest(g_N_rn / 2 + 1, g_P_sq); -- number of used correlator cells <= g_P_sq + CONSTANT c_rx_nof_packets : NATURAL := func_sdp_get_stat_nof_packets(g_statistics_type, c_sdp_S_pn, c_nof_used_P_sq, g_nof_crosslets); -- payload data CONSTANT c_packet_size : NATURAL := c_nof_statistics_per_packet * c_sdp_W_statistic_sz; @@ -225,6 +226,7 @@ ARCHITECTURE tb OF tb_sdp_statistics_offload IS SIGNAL dbg_c_marker : NATURAL := c_marker; SIGNAL dbg_c_nof_signal_inputs : NATURAL := c_nof_signal_inputs; SIGNAL dbg_c_nof_packets_max : NATURAL := c_nof_packets_max; + SIGNAL dbg_c_rx_nof_packets : NATURAL := c_rx_nof_packets; SIGNAL dbg_c_beamlet_index : NATURAL := c_beamlet_index; SIGNAL dbg_c_packet_size : NATURAL := c_packet_size; SIGNAL dbg_c_mm_user_size : NATURAL := c_mm_user_size; @@ -337,7 +339,7 @@ BEGIN test_sync_cnt <= in_sync_cnt - 1; -- optionally adjust to fit test_offload_sosi -- derive current X_sq correlator cell index - cur_X_sq_cell <= (test_offload_eop_cnt / g_nof_crosslets) MOD g_P_sq; + cur_X_sq_cell <= (test_offload_eop_cnt / g_nof_crosslets) MOD c_nof_used_P_sq; -- derive current N_crosslets index index cur_crosslet <= test_offload_eop_cnt MOD g_nof_crosslets; @@ -460,7 +462,7 @@ BEGIN BEGIN IF rising_edge(dp_clk) THEN IF in_sosi.sync = '1' AND in_sync_cnt > 1 THEN - ASSERT rx_packet_cnt = c_mm_nof_packets REPORT "Wrong number of packets per sync interval" SEVERITY ERROR; + ASSERT rx_packet_cnt = c_rx_nof_packets REPORT "Wrong number of packets per sync interval" SEVERITY ERROR; END IF; END IF; END PROCESS; @@ -557,7 +559,7 @@ BEGIN ASSERT v_exp_data = v_rx_data REPORT "Wrong BST payload data Rx" SEVERITY ERROR; ELSIF g_statistics_type = "XST" THEN - -- . g_P_sq = 4 + -- . c_nof_used_P_sq = 4 -- . g_nof_crosslets = 3 -- . c_sdp_N_crosslets_max = 7 --> c_mm_Xsq_span = 2**ceil_log2(7 * 576) = 4096 -- @@ -587,9 +589,9 @@ BEGIN -- c_mm_data_size / c_sdp_W_statistic_sz = 2 = c_nof_complex X := D; -- range c_sdp_X_sq = 144 complex XST values I := W MOD c_mm_user_size; -- range c_mm_user_size = c_sdp_W_statistic_sz = 2 words - P := rx_packet_cnt; -- range c_mm_nof_packets + P := rx_packet_cnt; -- range c_rx_nof_packets J := P MOD g_nof_crosslets; -- range g_nof_crosslets - K := P / g_nof_crosslets; -- range g_P_sq + K := P / g_nof_crosslets; -- range c_nof_used_P_sq v_exp_data := S * c_mm_user_size; -- c_mm_user_size = 2 IF g_reverse_word_order = FALSE THEN diff --git a/applications/lofar2/libraries/sdp/tb/vhdl/tb_tb_sdp_statistics_offload.vhd b/applications/lofar2/libraries/sdp/tb/vhdl/tb_tb_sdp_statistics_offload.vhd index a688d26acd7d88aba8f60ca51f3409710bf0c36e..0d3f42ce3fd8ebfd344e86d101ddc1a301d05b49 100644 --- a/applications/lofar2/libraries/sdp/tb/vhdl/tb_tb_sdp_statistics_offload.vhd +++ b/applications/lofar2/libraries/sdp/tb/vhdl/tb_tb_sdp_statistics_offload.vhd @@ -63,5 +63,7 @@ BEGIN u_xst_P9_N3_no_reverse : ENTITY work.tb_sdp_statistics_offload GENERIC MAP("XST", 50, FALSE, 1, 0, 0, 16, 9, 3, 1); u_xst_P9_N3_neg : ENTITY work.tb_sdp_statistics_offload GENERIC MAP("XST", 50, TRUE, 1, 0, 0, 16, 9, 3, 0); u_xst_P8_N7_RN1_15 : ENTITY work.tb_sdp_statistics_offload GENERIC MAP("XST", 50, TRUE, 1, 0, 1, 15, 8, 7, 0); + u_xst_P1_N7_RN0_7 : ENTITY work.tb_sdp_statistics_offload GENERIC MAP("XST", 50, TRUE, 3, 0, 0, 8, 1, 7, 1); -- P_sq = 1 < N_rn/2+1 = 5 + u_xst_P9_N7_RN0_7 : ENTITY work.tb_sdp_statistics_offload GENERIC MAP("XST", 50, TRUE, 3, 0, 0, 8, 9, 7, 1); -- P_sq = 9 > N_rn/2+1 = 5 END tb; diff --git a/libraries/base/diag/src/vhdl/diag_wg.vhd b/libraries/base/diag/src/vhdl/diag_wg.vhd index 53ab3a2a5daf43706991a4e810991280920e5dc8..a30ec8a8608aa3fce0021d2829869ddaf3116558 100644 --- a/libraries/base/diag/src/vhdl/diag_wg.vhd +++ b/libraries/base/diag/src/vhdl/diag_wg.vhd @@ -21,7 +21,12 @@ -- Purpose: Sine waveform generator -- Description: --- . Based on diag_waveproc from LOFAR. +-- . Based on diag_waveproc from LOFAR1. +-- . Monitor the active WG ctrl: +-- - WG ctrl.mode = off takes effect immediately +-- - WG ctrl.ampl takes effect immediately +-- - Changing WG ctrl.phase and ctrl.freq require a restart to take effect, +-- to have synchronous phase relation between different WG. -- Remarks: -- . For WG sine periods that integer fit in the WG buffer size the carrier -- wWave (CW) frequency is exact. For fractional WG frequencies, for which @@ -73,6 +78,7 @@ ENTITY diag_wg IS buf_rdval : IN STD_LOGIC; ctrl : IN t_diag_wg; + mon_ctrl : OUT t_diag_wg; out_ovr : OUT STD_LOGIC; out_dat : OUT STD_LOGIC_VECTOR(g_buf_dat_w-1 DOWNTO 0); @@ -117,8 +123,11 @@ ARCHITECTURE rtl OF diag_wg IS SIGNAL state : state_enum; SIGNAL nxt_state : state_enum; + SIGNAL prev_state : state_enum; SIGNAL idle : STD_LOGIC; + SIGNAL i_mon_ctrl : t_diag_wg; + SIGNAL nxt_mon_ctrl : t_diag_wg; SIGNAL nof_samples : STD_LOGIC_VECTOR(g_buf_addr_w DOWNTO 0); -- only use effective range of nof_samples+1 SIGNAL nxt_nof_samples : STD_LOGIC_VECTOR(g_buf_addr_w DOWNTO 0); SIGNAL sample_cnt : NATURAL RANGE 0 TO 2**g_buf_addr_w-1; @@ -126,7 +135,7 @@ ARCHITECTURE rtl OF diag_wg IS SIGNAL sample_step : NATURAL RANGE 0 TO g_rate_factor; SIGNAL nxt_sample_step : NATURAL; SIGNAL init_repeat_done : STD_LOGIC; - + SIGNAL phase : STD_LOGIC_VECTOR(ctrl.freq'LENGTH-1 DOWNTO 0); SIGNAL nxt_phase : STD_LOGIC_VECTOR(phase'RANGE); SIGNAL phase_step : STD_LOGIC_VECTOR(phase'RANGE); @@ -159,12 +168,15 @@ ARCHITECTURE rtl OF diag_wg IS BEGIN + mon_ctrl <= i_mon_ctrl; + registers : PROCESS(clk, rst) BEGIN IF rst = '1' THEN -- Internal registers. nof_samples <= (OTHERS => '0'); state <= s_off; + prev_state <= s_off; sample_cnt <= 0; sample_step <= 0; phase <= (OTHERS => '0'); @@ -172,6 +184,7 @@ BEGIN init_phase_cnt <= 0; init_sync <= '0'; -- Output registers. + i_mon_ctrl <= c_diag_wg_rst; buf_addr <= (OTHERS => '0'); buf_rden <= '0'; out_ovr <= '0'; @@ -182,6 +195,7 @@ BEGIN -- Internal registers. nof_samples <= nxt_nof_samples; state <= nxt_state; + prev_state <= state; sample_cnt <= nxt_sample_cnt; sample_step <= nxt_sample_step; phase <= nxt_phase; @@ -189,6 +203,7 @@ BEGIN init_phase_cnt <= nxt_init_phase_cnt; init_sync <= nxt_init_sync; -- Output registers. + i_mon_ctrl <= nxt_mon_ctrl; buf_addr <= nxt_buf_addr; buf_rden <= nxt_buf_rden; out_ovr <= nxt_out_ovr; @@ -317,9 +332,23 @@ BEGIN END IF; END PROCESS; - ctrl_ampl <= '0' & ctrl.ampl; + p_mon_ctrl : PROCESS(i_mon_ctrl, ctrl, prev_state, state) + BEGIN + nxt_mon_ctrl <= i_mon_ctrl; + IF TO_UINT(ctrl.mode) = c_diag_wg_mode_off THEN + -- WG immediately goes into off state + nxt_mon_ctrl <= ctrl; + ELSIF prev_state = s_init AND prev_state /= state THEN + -- WG holds ctrl, when it goes into active state (s_single, s_repeat, or s_calc) + nxt_mon_ctrl <= ctrl; + END IF; + -- These MM ctrl fields always take effect immediately in all WG states + nxt_mon_ctrl.ampl <= ctrl.ampl; + nxt_mon_ctrl.nof_samples <= ctrl.nof_samples; + END PROCESS; + mult : ENTITY common_mult_lib.common_mult GENERIC MAP ( g_technology => g_technology, diff --git a/libraries/base/diag/src/vhdl/diag_wg_wideband.vhd b/libraries/base/diag/src/vhdl/diag_wg_wideband.vhd index 63d02e992cb7517fae7ddb83bbaf8649f71e3e3d..0f4384df6182b31988bb8090ab3bcd95b4835b9b 100644 --- a/libraries/base/diag/src/vhdl/diag_wg_wideband.vhd +++ b/libraries/base/diag/src/vhdl/diag_wg_wideband.vhd @@ -66,6 +66,7 @@ ENTITY diag_wg_wideband IS st_restart : IN STD_LOGIC; st_ctrl : IN t_diag_wg; + st_mon_ctrl : OUT t_diag_wg; out_ovr : OUT STD_LOGIC_VECTOR(g_wideband_factor -1 DOWNTO 0); -- big endian, so first output sample in MSBit, MSData out_dat : OUT STD_LOGIC_VECTOR(g_wideband_factor*g_buf_dat_w-1 DOWNTO 0); @@ -88,7 +89,9 @@ ARCHITECTURE str OF diag_wg_wideband IS TYPE t_buf_dat_arr IS ARRAY (NATURAL RANGE <>) OF STD_LOGIC_VECTOR(g_buf_dat_w-1 DOWNTO 0); TYPE t_buf_adr_arr IS ARRAY (NATURAL RANGE <>) OF STD_LOGIC_VECTOR(g_buf_addr_w-1 DOWNTO 0); - + + SIGNAL st_mon_ctrl_arr : t_diag_wg_arr(0 TO g_wideband_factor-1); + -- Use same address and data widths for both MM side and ST side memory ports SIGNAL buf_rdval : STD_LOGIC_VECTOR(0 TO g_wideband_factor-1); SIGNAL buf_rddata : t_buf_dat_arr(0 TO g_wideband_factor-1); @@ -107,6 +110,8 @@ BEGIN mm_rdval <= buf_rdval(0); mm_rddata <= buf_rddata(0); + st_mon_ctrl <= st_mon_ctrl_arr(0); -- same for all g_wideband_factor waveform generators + gen_wg : FOR I IN 0 TO g_wideband_factor-1 GENERATE -- Waveform buffer u_buf : ENTITY common_lib.common_ram_crw_crw @@ -157,7 +162,8 @@ BEGIN buf_rden => st_rd(I), ctrl => st_ctrl, - + mon_ctrl => st_mon_ctrl_arr(I), + out_ovr => out_ovr( g_wideband_factor-I-1), out_dat => out_dat((g_wideband_factor-I)*g_buf_dat_w-1 DOWNTO (g_wideband_factor-I-1)*g_buf_dat_w), out_val => out_val( g_wideband_factor-I-1), diff --git a/libraries/base/diag/src/vhdl/diag_wg_wideband_reg.vhd b/libraries/base/diag/src/vhdl/diag_wg_wideband_reg.vhd index 4043c51e1efa6bb2bcbf672b4f52ae97dba203a3..c6db7329b6ea11c94d3918d8b6f728518c06230e 100644 --- a/libraries/base/diag/src/vhdl/diag_wg_wideband_reg.vhd +++ b/libraries/base/diag/src/vhdl/diag_wg_wideband_reg.vhd @@ -62,7 +62,8 @@ ENTITY diag_wg_wideband_reg IS sla_out : OUT t_mem_miso; -- actual ranges defined by c_mm_reg -- MM registers in st_clk domain - st_wg_ctrl : OUT t_diag_wg -- WG control port + st_wg_ctrl : OUT t_diag_wg; -- WG control write port + st_mon_ctrl : IN t_diag_wg -- WG control read port, for currently active control ); END diag_wg_wideband_reg; @@ -80,6 +81,8 @@ ARCHITECTURE rtl OF diag_wg_wideband_reg IS SIGNAL mm_wg_ctrl : t_diag_wg; SIGNAL mm_wg_ctrl_mode_wr : STD_LOGIC; + SIGNAL mm_mon_ctrl : t_diag_wg; + -- Registers in st_clk domain BEGIN @@ -129,14 +132,14 @@ BEGIN sla_out.rdval <= '1'; -- c_mm_reg.latency = 1 CASE TO_UINT(sla_in.address(c_mm_reg.adr_w-1 DOWNTO 0)) IS WHEN 0 => - sla_out.rddata( 7 DOWNTO 0) <= mm_wg_ctrl.mode; -- = 8 = c_diag_wg_mode_w - sla_out.rddata(31 DOWNTO 16) <= mm_wg_ctrl.nof_samples; -- = 16 = c_diag_wg_nof_samples_w + sla_out.rddata( 7 DOWNTO 0) <= mm_mon_ctrl.mode; -- = 8 = c_diag_wg_mode_w + sla_out.rddata(31 DOWNTO 16) <= mm_mon_ctrl.nof_samples; -- = 16 = c_diag_wg_nof_samples_w WHEN 1 => - sla_out.rddata(15 DOWNTO 0) <= mm_wg_ctrl.phase; -- = 16 = c_diag_wg_phase_w + sla_out.rddata(15 DOWNTO 0) <= mm_mon_ctrl.phase; -- = 16 = c_diag_wg_phase_w WHEN 2 => - sla_out.rddata(30 DOWNTO 0) <= mm_wg_ctrl.freq; -- = 31 = c_diag_wg_freq_w + sla_out.rddata(30 DOWNTO 0) <= mm_mon_ctrl.freq; -- = 31 = c_diag_wg_freq_w WHEN 3 => - sla_out.rddata(16 DOWNTO 0) <= mm_wg_ctrl.ampl; -- = 17 = c_diag_wg_ampl_w + sla_out.rddata(16 DOWNTO 0) <= mm_mon_ctrl.ampl; -- = 17 = c_diag_wg_ampl_w WHEN OTHERS => NULL; -- not used MM addresses END CASE; END IF; @@ -161,6 +164,7 @@ BEGIN ------------------------------------------------------------------------------ no_cross : IF g_cross_clock_domain = FALSE GENERATE -- so mm_clk = st_clk + -- Write: MM to ST clock domain p_st_clk : PROCESS(st_rst, st_clk) BEGIN IF st_rst='1' THEN @@ -171,9 +175,13 @@ BEGIN END IF; END IF; END PROCESS; - END GENERATE; -- no_cross - gen_cross : IF g_cross_clock_domain = TRUE GENERATE + -- Read: ST to MM clock domain + mm_mon_ctrl <= st_mon_ctrl; + END GENERATE; + + -- Write: MM to ST clock domain + gen_cross_wr : IF g_cross_clock_domain = TRUE GENERATE -- Assume diag WG mode gets written last, so when diag WG mode is transfered properly to the st_clk domain, then -- the other diag WG control fields are stable as well u_mode : ENTITY common_lib.common_reg_cross_domain @@ -188,7 +196,7 @@ BEGIN out_dat => st_wg_ctrl.mode, out_new => OPEN -- when '1' then the out_dat was updated with in_dat due to in_new ); - END GENERATE; -- gen_cross + END GENERATE; -- The other wg_ctrl only take effect in diag_wg after the mode has been set st_wg_ctrl.nof_samples <= mm_wg_ctrl.nof_samples; @@ -196,4 +204,57 @@ BEGIN st_wg_ctrl.phase <= mm_wg_ctrl.phase; st_wg_ctrl.ampl <= mm_wg_ctrl.ampl; + -- Read: ST to MM clock domain + gen_cross_rd : IF g_cross_clock_domain = TRUE GENERATE + u_mode : ENTITY common_lib.common_reg_cross_domain + PORT MAP ( + in_rst => st_rst, + in_clk => st_clk, + in_dat => st_mon_ctrl.mode, + out_rst => mm_rst, + out_clk => mm_clk, + out_dat => mm_mon_ctrl.mode + ); + + u_nof_samples : ENTITY common_lib.common_reg_cross_domain + PORT MAP ( + in_rst => st_rst, + in_clk => st_clk, + in_dat => st_mon_ctrl.nof_samples, + out_rst => mm_rst, + out_clk => mm_clk, + out_dat => mm_mon_ctrl.nof_samples + ); + + u_freq : ENTITY common_lib.common_reg_cross_domain + PORT MAP ( + in_rst => st_rst, + in_clk => st_clk, + in_dat => st_mon_ctrl.freq, + out_rst => mm_rst, + out_clk => mm_clk, + out_dat => mm_mon_ctrl.freq + ); + + u_phase : ENTITY common_lib.common_reg_cross_domain + PORT MAP ( + in_rst => st_rst, + in_clk => st_clk, + in_dat => st_mon_ctrl.phase, + out_rst => mm_rst, + out_clk => mm_clk, + out_dat => mm_mon_ctrl.phase + ); + + u_ampl : ENTITY common_lib.common_reg_cross_domain + PORT MAP ( + in_rst => st_rst, + in_clk => st_clk, + in_dat => st_mon_ctrl.ampl, + out_rst => mm_rst, + out_clk => mm_clk, + out_dat => mm_mon_ctrl.ampl + ); + END GENERATE; + END rtl; diff --git a/libraries/base/diag/src/vhdl/mms_diag_wg_wideband.vhd b/libraries/base/diag/src/vhdl/mms_diag_wg_wideband.vhd index 6c6b912bde048cc3c7897963943bbc0c694ae430..e2f291106471290e27750fb6485d82002f149158 100644 --- a/libraries/base/diag/src/vhdl/mms_diag_wg_wideband.vhd +++ b/libraries/base/diag/src/vhdl/mms_diag_wg_wideband.vhd @@ -80,7 +80,8 @@ END mms_diag_wg_wideband; ARCHITECTURE str OF mms_diag_wg_wideband IS - SIGNAL st_wg_ctrl : t_diag_wg; + SIGNAL st_wg_ctrl : t_diag_wg; -- write + SIGNAL st_mon_ctrl : t_diag_wg; -- read BEGIN @@ -100,7 +101,8 @@ BEGIN sla_out => reg_miso, -- MM registers in st_clk domain - st_wg_ctrl => st_wg_ctrl + st_wg_ctrl => st_wg_ctrl, + st_mon_ctrl => st_mon_ctrl ); u_wg_wideband : ENTITY work.diag_wg_wideband @@ -137,6 +139,7 @@ BEGIN st_restart => st_restart, st_ctrl => st_wg_ctrl, + st_mon_ctrl => st_mon_ctrl, out_ovr => out_ovr, out_dat => out_dat, diff --git a/libraries/base/diag/tb/vhdl/tb_diag_wg.vhd b/libraries/base/diag/tb/vhdl/tb_diag_wg.vhd index ca3ba5ef9857a8cd8b962bf3fb7aa4f4a450445f..520bf017d12372c674ac709130a7c0fc01bde844 100644 --- a/libraries/base/diag/tb/vhdl/tb_diag_wg.vhd +++ b/libraries/base/diag/tb/vhdl/tb_diag_wg.vhd @@ -19,7 +19,7 @@ -- along with this program. If not, see <http://www.gnu.org/licenses/>. -- -------------------------------------------------------------------------------- - + LIBRARY IEEE, common_lib; USE IEEE.STD_LOGIC_1164.ALL; USE IEEE.NUMERIC_STD.ALL; @@ -49,7 +49,7 @@ ARCHITECTURE tb OF tb_diag_wg IS CONSTANT c_clk_freq : NATURAL := 200*10**6; -- Hz CONSTANT c_clk_period : TIME := (10**9 / c_clk_freq) * 1 ns; - + -- Default settings CONSTANT c_buf : t_c_mem := (latency => 1, adr_w => g_buf_adr_w, @@ -59,86 +59,86 @@ ARCHITECTURE tb OF tb_diag_wg IS CONSTANT c_buf_file : STRING := sel_a_b(c_buf.adr_w=11 AND c_buf.dat_w=18, "data/diag_sin_2048x18.hex", sel_a_b(c_buf.adr_w=10 AND c_buf.dat_w=18, "data/diag_sin_1024x18.hex", sel_a_b(c_buf.adr_w=10 AND c_buf.dat_w= 8, "data/diag_sin_1024x8.hex", "UNUSED"))); - - + + CONSTANT c_wg_nof_samples : NATURAL := c_buf.nof_dat; -- must be <= c_buf.nof_dat CONSTANT c_wg_gain_w : NATURAL := 1; -- Normalized range [0 1> maps to fixed point range [0:2**c_diag_wg_ampl_w> -- . use gain 2**0 = 1 to have fulle scale without clipping -- . use gain 2**g_calc_gain_w > 1 to cause clipping - + CONSTANT c_buf_full_scale : NATURAL := 2**(g_buf_dat_w-1)-1; -- The stored waveform range should also be [-c_buf_full_scale +c_buf_full_scale], so not including -c_buf_full_scale-1 CONSTANT c_wg_full_scale : NATURAL := 2**(g_wg_dat_w-1)-1; CONSTANT c_ampl_norm : REAL := sel_a_b(g_wg_dat_w < g_buf_dat_w, REAL(c_wg_full_scale)/REAL(c_wg_full_scale+1), 1.0); --CONSTANT c_ampl_norm : REAL := REAL(c_wg_full_scale)/REAL(c_wg_full_scale+1); -- Use this if g_wg_dat_w < g_buf_dat_w, to avoid clipping --CONSTANT c_ampl_norm : REAL := 1.0; -- Use this if g_wg_dat_w = g_buf_dat_w, because the stored waveform range is already -+c_buf_full_scale --CONSTANT c_ampl_norm : REAL := REAL(c_buf_full_scale)/REAL(c_buf_full_scale+1); -- No need to use this, because the stored waveform range is already -+c_buf_full_scale - + CONSTANT c_freq_unit : REAL := c_diag_wg_freq_unit; -- ^= c_clk_freq = Fs (sample frequency), assuming one sinus waveform in the buffer CONSTANT c_ampl_unit : REAL := c_diag_wg_ampl_unit*c_ampl_norm; -- ^= Full Scale range [-c_wg_full_scale +c_wg_full_scale] without clipping CONSTANT c_phase_unit : REAL := c_diag_wg_phase_unit; -- ^= 1 degree - + SIGNAL tb_end : STD_LOGIC; SIGNAL rst : STD_LOGIC; SIGNAL clk : STD_LOGIC := '1'; SIGNAL restart : STD_LOGIC; - + SIGNAL buf_rddat : STD_LOGIC_VECTOR(c_buf.dat_w-1 DOWNTO 0); SIGNAL buf_rdval : STD_LOGIC; SIGNAL buf_addr : STD_LOGIC_VECTOR(c_buf.adr_w-1 DOWNTO 0); SIGNAL buf_rden : STD_LOGIC; - + SIGNAL wg_ctrl : t_diag_wg; - + SIGNAL wg_mode : NATURAL; SIGNAL wg_freq : NATURAL; SIGNAL wg_ampl : NATURAL; SIGNAL wg_nof_samples : NATURAL; SIGNAL wg_phase : NATURAL; - + SIGNAL wg_ovr : STD_LOGIC; SIGNAL wg_dat : STD_LOGIC_VECTOR(c_buf.dat_w-1 DOWNTO 0); SIGNAL wg_val : STD_LOGIC; SIGNAL wg_sync : STD_LOGIC; - + BEGIN rst <= '1', '0' AFTER c_clk_period/10; clk <= NOT clk OR tb_end AFTER c_clk_period/2; - + wg_ctrl.mode <= TO_UVEC(wg_mode, c_diag_wg_mode_w); wg_ctrl.freq <= TO_UVEC(wg_freq, c_diag_wg_freq_w); wg_ctrl.ampl <= TO_UVEC(wg_ampl, c_diag_wg_ampl_w); wg_ctrl.nof_samples <= TO_UVEC(wg_nof_samples, c_diag_wg_nofsamples_w); wg_ctrl.phase <= TO_UVEC(wg_phase, c_diag_wg_phase_w); - + p_mm : PROCESS BEGIN tb_end <= '0'; restart <= '0'; wg_mode <= c_diag_wg_mode_off; - + --------------------------------------------------------------------------- -- >>> Single, repeat mode wg_nof_samples <= c_wg_nof_samples; - + -- >>> CALC mode -- Cosinus with frequency Fs/2 (note sinus Fs/2 yields DC = 0) -- wg_freq <= INTEGER(0.5 * c_freq_unit); -- wg_phase <= INTEGER(90.0 * c_phase_unit); - + -- Choosing 1.0*Fs to select Fs which is equivalent to DC, hence the DC value is then determined by phase - -- this also applies to 2.0, 3.0, 4.0 etc + -- this also applies to 2.0, 3.0, 4.0 etc -- wg_freq <= INTEGER(1.0 * c_freq_unit); -- wg_phase <= INTEGER(45.0 * c_phase_unit); - + -- Sinus Fs/16 wg_freq <= INTEGER(0.0625 * c_freq_unit); --wg_freq <= INTEGER(511.0/512.0 * c_freq_unit); --wg_freq <= INTEGER(1.0/512.0 * c_freq_unit); --wg_freq <= INTEGER(1.0); -- minimum value, yields Fs/c_freq_unit Hz sinus wg_phase <= INTEGER(0.0 * c_phase_unit); - + -- Sinus Fs/17 -- wg_freq <= INTEGER(1.0/17.0 * c_freq_unit); -- wg_phase <= INTEGER(0.0 * c_phase_unit); @@ -146,13 +146,13 @@ BEGIN wg_ampl <= INTEGER(1.0 * c_ampl_unit); -- yields amplitude of c_wg_full_scale -- wg_ampl <= INTEGER(1.0/REAL(c_wg_full_scale) * c_ampl_unit); -- yields amplitude of 1 -- wg_ampl <= INTEGER(3.0/REAL(c_wg_full_scale) * c_ampl_unit); -- yields amplitude of 3 - + WAIT UNTIL rising_edge(clk); -- align to rising edge WAIT FOR c_clk_period*200; - + --------------------------------------------------------------------------- -- >>> Select the different modes - + -- CALC mode wg_mode <= c_diag_wg_mode_calc; restart <= '1'; @@ -164,14 +164,14 @@ BEGIN restart <= '0'; WAIT FOR c_clk_period*3000; --WAIT FOR 1 sec; - + -- OFF mode wg_mode <= c_diag_wg_mode_off; restart <= '1'; WAIT FOR c_clk_period*1; restart <= '0'; WAIT FOR c_clk_period*200; - + -- SINGLE mode wg_mode <= c_diag_wg_mode_single; FOR I IN 0 TO 1 LOOP @@ -181,7 +181,7 @@ BEGIN WAIT FOR c_clk_period*c_buf.nof_dat; WAIT FOR c_clk_period*300; END LOOP; - + -- REPEAT mode wg_mode <= c_diag_wg_mode_repeat; restart <= '1'; @@ -194,19 +194,19 @@ BEGIN restart <= '0'; WAIT FOR c_clk_period*c_buf.nof_dat*5; WAIT FOR c_clk_period*200; - + -- OFF mode wg_mode <= c_diag_wg_mode_off; restart <= '1'; WAIT FOR c_clk_period*1; restart <= '0'; WAIT FOR c_clk_period*200; - + WAIT FOR c_clk_period*100; tb_end <= '1'; WAIT; END PROCESS; - + -- Waveform buffer u_buf : ENTITY common_lib.common_ram_crw_crw GENERIC MAP ( @@ -231,7 +231,7 @@ BEGIN rd_val_a => OPEN, rd_val_b => buf_rdval ); - + -- Waveform generator u_wg : ENTITY work.diag_wg GENERIC MAP ( @@ -258,6 +258,6 @@ BEGIN out_val => wg_val, out_sync => wg_sync ); - + END tb; diff --git a/libraries/base/diag/tb/vhdl/tb_diag_wg_wideband.vhd b/libraries/base/diag/tb/vhdl/tb_diag_wg_wideband.vhd index 5fe5307223af3b54807bffcd691fe80b30ea4130..3727020eac42f779201e4a94f5d043d0b93ec80d 100644 --- a/libraries/base/diag/tb/vhdl/tb_diag_wg_wideband.vhd +++ b/libraries/base/diag/tb/vhdl/tb_diag_wg_wideband.vhd @@ -19,7 +19,15 @@ -- along with this program. If not, see <http://www.gnu.org/licenses/>. -- -------------------------------------------------------------------------------- - +-- Purpose: Tb for WG +-- Description: Verifies all WG modes. +-- Usage: +-- > as 10 +-- > run -all +-- . Use select rigth mouse in Wave window on wg_dat and choose radix --> +-- decimal and format --> analogue (automatic) +-- . Observe state in diag_wg(0). + LIBRARY IEEE, common_lib; USE IEEE.STD_LOGIC_1164.ALL; USE IEEE.NUMERIC_STD.ALL; @@ -27,15 +35,6 @@ USE IEEE.MATH_REAL.ALL; USE common_lib.common_pkg.ALL; USE work.diag_pkg.ALL; --- Usage: --- > do wave_diag_wg_wideband.do --- > run -all --- --- . Use select rigth mouse in wave window on wg_dat and choose 'format --> analogue (automatic)' --- . run 10 us to see CALC mode waveform output at proper automatic scale --- . run 100 us to see SINGLE and REPEAT mode waveform output at proper automatic scale - - ENTITY tb_diag_wg_wideband IS GENERIC ( -- Wideband parameters @@ -52,49 +51,51 @@ ARCHITECTURE tb OF tb_diag_wg_wideband IS CONSTANT c_clk_freq : NATURAL := 200; -- MHz CONSTANT c_clk_period : TIME := (10**6 / c_clk_freq) * 1 ps; - + -- Default WG settings CONSTANT c_buf_nof_dat : NATURAL := 2**g_buf_addr_w; - + CONSTANT c_wg_gain_w : NATURAL := 1; -- Normalized range [0 1> maps to fixed point range [0:2**c_diag_wg_ampl_w> -- . use gain 2**0 = 1 to have fulle scale without clipping -- . use gain 2**g_calc_gain_w > 1 to cause clipping - + CONSTANT c_buf_full_scale : NATURAL := 2**(g_buf_dat_w-1)-1; -- The stored waveform range should also be [-c_buf_full_scale +c_buf_full_scale], so not including -c_buf_full_scale-1 CONSTANT c_wg_full_scale : NATURAL := 2**(g_wg_dat_w-1)-1; CONSTANT c_ampl_norm : REAL := sel_a_b(g_wg_dat_w < g_buf_dat_w, REAL(c_wg_full_scale)/REAL(c_wg_full_scale+1), 1.0); --CONSTANT c_ampl_norm : REAL := REAL(c_wg_full_scale)/REAL(c_wg_full_scale+1); -- Use this if g_wg_dat_w < g_buf_dat_w, to avoid clipping --CONSTANT c_ampl_norm : REAL := 1.0; -- Use this if g_wg_dat_w = g_buf_dat_w, because the stored waveform range is already -+c_buf_full_scale --CONSTANT c_ampl_norm : REAL := REAL(c_buf_full_scale)/REAL(c_buf_full_scale+1); -- No need to use this, because the stored waveform range is already -+c_buf_full_scale - + CONSTANT c_freq_unit : REAL := c_diag_wg_freq_unit; -- ^= c_clk_freq = Fs (sample frequency), assuming one sinus waveform in the buffer CONSTANT c_ampl_unit : REAL := c_diag_wg_ampl_unit*c_ampl_norm; -- ^= Full Scale range [-c_wg_full_scale +c_wg_full_scale] without clipping CONSTANT c_phase_unit : REAL := c_diag_wg_phase_unit; -- ^= 1 degree - + -- Wideband WG settings CONSTANT c_sample_period : TIME := (10**6 / (c_clk_freq*g_wideband_factor)) * 1 ps; - + TYPE t_buf_dat_arr IS ARRAY (NATURAL RANGE <>) OF STD_LOGIC_VECTOR(g_buf_dat_w-1 DOWNTO 0); - + SIGNAL tb_end : STD_LOGIC; SIGNAL rst : STD_LOGIC; SIGNAL clk : STD_LOGIC := '1'; SIGNAL restart : STD_LOGIC; - + SIGNAL wg_ctrl : t_diag_wg; - + SIGNAL cur_ctrl : t_diag_wg; + SIGNAL mon_ctrl : t_diag_wg; + SIGNAL wg_mode : NATURAL; SIGNAL wg_freq : NATURAL; SIGNAL wg_ampl : NATURAL; SIGNAL wg_nof_samples : NATURAL; SIGNAL wg_phase : NATURAL; - + -- Wideband WG output is big endian, so first output sample in MSBit, MSData SIGNAL out_ovr : STD_LOGIC_VECTOR(g_wideband_factor -1 DOWNTO 0); SIGNAL out_dat : STD_LOGIC_VECTOR(g_wideband_factor*g_buf_dat_w-1 DOWNTO 0); SIGNAL out_val : STD_LOGIC_VECTOR(g_wideband_factor -1 DOWNTO 0); SIGNAL out_sync : STD_LOGIC_VECTOR(g_wideband_factor -1 DOWNTO 0); - + SIGNAL wg_ovr : STD_LOGIC_VECTOR(0 TO g_wideband_factor-1); SIGNAL wg_dat : t_buf_dat_arr(0 TO g_wideband_factor-1); SIGNAL wg_val : STD_LOGIC_VECTOR(0 TO g_wideband_factor-1); @@ -106,47 +107,47 @@ ARCHITECTURE tb OF tb_diag_wg_wideband IS SIGNAL sample_dat : STD_LOGIC_VECTOR(g_buf_dat_w-1 DOWNTO 0); SIGNAL sample_val : STD_LOGIC; SIGNAL sample_sync : STD_LOGIC; - + BEGIN rst <= '1', '0' AFTER c_clk_period/10; clk <= NOT clk OR tb_end AFTER c_clk_period/2; - + sample_clk <= NOT sample_clk OR tb_end AFTER c_sample_period/2; - + wg_ctrl.mode <= TO_UVEC(wg_mode, c_diag_wg_mode_w); wg_ctrl.freq <= TO_UVEC(wg_freq, c_diag_wg_freq_w); wg_ctrl.ampl <= TO_UVEC(wg_ampl, c_diag_wg_ampl_w); wg_ctrl.nof_samples <= TO_UVEC(wg_nof_samples, c_diag_wg_nofsamples_w); wg_ctrl.phase <= TO_UVEC(wg_phase, c_diag_wg_phase_w); - + p_mm : PROCESS BEGIN tb_end <= '0'; restart <= '0'; wg_mode <= c_diag_wg_mode_off; - + --------------------------------------------------------------------------- -- >>> Single, repeat mode wg_nof_samples <= c_buf_nof_dat; -- must be <= c_buf_nof_dat - + -- >>> CALC mode -- Cosinus with frequency Fs/2 (note sinus Fs/2 yields DC = 0) -- wg_freq <= INTEGER(0.5 * c_freq_unit); -- wg_phase <= INTEGER(90.0 * c_phase_unit); - + -- Choosing 1.0*Fs to select Fs which is equivalent to DC, hence the DC value is then determined by phase - -- this also applies to 2.0, 3.0, 4.0 etc + -- this also applies to 2.0, 3.0, 4.0 etc -- wg_freq <= INTEGER(1.0 * c_freq_unit); -- wg_phase <= INTEGER(45.0 * c_phase_unit); - + -- Sinus Fs/16 wg_freq <= INTEGER(0.0625 * c_freq_unit); --wg_freq <= INTEGER(511.0/512.0 * c_freq_unit); wg_freq <= INTEGER(1.0/512.0 * c_freq_unit); --wg_freq <= INTEGER(1.0); -- minimum value, yields Fs/c_freq_unit Hz sinus wg_phase <= INTEGER(0.0 * c_phase_unit); - + -- Sinus Fs/17 -- wg_freq <= INTEGER(1.0/17.0 * c_freq_unit); -- wg_phase <= INTEGER(0.0 * c_phase_unit); @@ -154,68 +155,115 @@ BEGIN wg_ampl <= INTEGER(1.0 * c_ampl_unit); -- yields amplitude of c_wg_full_scale -- wg_ampl <= INTEGER(1.0/REAL(c_wg_full_scale) * c_ampl_unit); -- yields amplitude of 1 -- wg_ampl <= INTEGER(3.0/REAL(c_wg_full_scale) * c_ampl_unit); -- yields amplitude of 3 - + WAIT UNTIL rising_edge(clk); -- align to rising edge + cur_ctrl <= wg_ctrl; WAIT FOR c_clk_period*200; - + --------------------------------------------------------------------------- -- >>> Select the different modes - + -- CALC mode wg_mode <= c_diag_wg_mode_calc; + WAIT FOR c_clk_period*10; + ASSERT mon_ctrl = cur_ctrl REPORT "Wrong mon_ctrl (expected hold OFF)" SEVERITY ERROR; restart <= '1'; WAIT FOR c_clk_period*1; restart <= '0'; + cur_ctrl <= wg_ctrl; + WAIT FOR c_clk_period*10; + ASSERT mon_ctrl = cur_ctrl REPORT "Wrong mon_ctrl (expected new CALC)" SEVERITY ERROR; + WAIT FOR c_clk_period*3000; + + wg_ampl <= INTEGER(0.5 * c_ampl_unit); -- change ampl immediately + WAIT FOR c_clk_period*1; + cur_ctrl <= wg_ctrl; + WAIT FOR c_clk_period*10; + ASSERT mon_ctrl = cur_ctrl REPORT "Wrong mon_ctrl (expected new CALC ampl)" SEVERITY ERROR; + + WAIT FOR c_clk_period*3000; + + wg_phase <= INTEGER(90.0 * c_phase_unit); -- no change phase without restart + wg_freq <= INTEGER(0.5/512.0 * c_freq_unit); -- no change freq without restart + WAIT FOR c_clk_period*10; + ASSERT mon_ctrl = cur_ctrl REPORT "Wrong mon_ctrl (expected hold CALC phase and freq)" SEVERITY ERROR; + + WAIT FOR c_clk_period*3000; + restart <= '1'; WAIT FOR c_clk_period*1; restart <= '0'; + cur_ctrl <= wg_ctrl; + WAIT FOR c_clk_period*10; + ASSERT mon_ctrl = cur_ctrl REPORT "Wrong mon_ctrl (expected new CALC phase and freq)" SEVERITY ERROR; + WAIT FOR c_clk_period*3000; - --WAIT FOR 1 sec; - + -- OFF mode wg_mode <= c_diag_wg_mode_off; + WAIT FOR c_clk_period*1; + cur_ctrl <= wg_ctrl; -- OFF mode takes effect immediately + WAIT FOR c_clk_period*10; + ASSERT mon_ctrl = cur_ctrl REPORT "Wrong mon_ctrl (expected immediately OFF)" SEVERITY ERROR; restart <= '1'; WAIT FOR c_clk_period*1; restart <= '0'; + WAIT FOR c_clk_period*10; + ASSERT mon_ctrl = cur_ctrl REPORT "Wrong mon_ctrl (expected still OFF)" SEVERITY ERROR; + WAIT FOR c_clk_period*200; - + -- SINGLE mode wg_mode <= c_diag_wg_mode_single; - FOR I IN 0 TO 1 LOOP + WAIT FOR c_clk_period*10; + ASSERT mon_ctrl = cur_ctrl REPORT "Wrong mon_ctrl (expected hold OFF)" SEVERITY ERROR; + FOR I IN 0 TO 3 LOOP restart <= '1'; WAIT FOR c_clk_period*1; restart <= '0'; + cur_ctrl <= wg_ctrl; + WAIT FOR c_clk_period*10; + ASSERT mon_ctrl = cur_ctrl REPORT "Wrong mon_ctrl (expected new SINGLE)" SEVERITY ERROR; WAIT FOR c_clk_period*c_buf_nof_dat; WAIT FOR c_clk_period*300; END LOOP; - + -- REPEAT mode wg_mode <= c_diag_wg_mode_repeat; - restart <= '1'; - WAIT FOR c_clk_period*1; - restart <= '0'; - WAIT FOR c_clk_period*c_buf_nof_dat*5; - WAIT FOR c_clk_period*200; - restart <= '1'; - WAIT FOR c_clk_period*1; - restart <= '0'; - WAIT FOR c_clk_period*c_buf_nof_dat*5; - WAIT FOR c_clk_period*200; - + WAIT FOR c_clk_period*10; + ASSERT mon_ctrl = cur_ctrl REPORT "Wrong mon_ctrl (expected hold SINGLE)" SEVERITY ERROR; + FOR I IN 0 TO 1 LOOP + restart <= '1'; + WAIT FOR c_clk_period*1; + restart <= '0'; + cur_ctrl <= wg_ctrl; + WAIT FOR c_clk_period*10; + ASSERT mon_ctrl = cur_ctrl REPORT "Wrong mon_ctrl (expected new REPEAT)" SEVERITY ERROR; + WAIT FOR c_clk_period*c_buf_nof_dat*5; + WAIT FOR c_clk_period*200; + END LOOP; + -- OFF mode wg_mode <= c_diag_wg_mode_off; + WAIT FOR c_clk_period*1; + cur_ctrl <= wg_ctrl; -- OFF mode takes effect immediately, no need for restart + WAIT FOR c_clk_period*10; + ASSERT mon_ctrl = cur_ctrl REPORT "Wrong mon_ctrl (expected immediately OFF)" SEVERITY ERROR; restart <= '1'; WAIT FOR c_clk_period*1; restart <= '0'; + WAIT FOR c_clk_period*10; + ASSERT mon_ctrl = cur_ctrl REPORT "Wrong mon_ctrl (expected still OFF)" SEVERITY ERROR; + WAIT FOR c_clk_period*200; - + WAIT FOR c_clk_period*100; tb_end <= '1'; WAIT; END PROCESS; - - + + u_wideband_wg : ENTITY work.diag_wg_wideband GENERIC MAP ( -- Wideband parameters @@ -231,7 +279,7 @@ BEGIN -- Memory-mapped clock domain mm_rst => '0', mm_clk => '0', - + mm_wrdata => (OTHERS=>'0'), mm_address => (OTHERS=>'0'), mm_wr => '0', @@ -243,15 +291,16 @@ BEGIN st_rst => rst, st_clk => clk, st_restart => restart, - + st_ctrl => wg_ctrl, + st_mon_ctrl => mon_ctrl, out_ovr => out_ovr, out_dat => out_dat, out_val => out_val, out_sync => out_sync ); - + -- Map wideband WG out_* slv to wg_* arrays to ease interpretation in wave window gen_wires : FOR I IN 0 TO g_wideband_factor-1 GENERATE wg_ovr(I) <= out_ovr( g_wideband_factor-I-1); @@ -259,8 +308,8 @@ BEGIN wg_val(I) <= out_val( g_wideband_factor-I-1); wg_sync(I) <= out_sync( g_wideband_factor-I-1); END GENERATE; - - -- View WG output at the sample rate + + -- View WG output at the sample rate p_sample : PROCESS(sample_clk) BEGIN IF rising_edge(sample_clk) THEN @@ -275,6 +324,6 @@ BEGIN sample_sync <= wg_sync(sample_cnt); END IF; END PROCESS; - + END tb; diff --git a/libraries/base/dp/hdllib.cfg b/libraries/base/dp/hdllib.cfg index 34a2c49f89a64e30918443ee012c44e85d40f1d5..fdead4ddbcbdaa5a5e5274ef6dbb2a49e688a1da 100644 --- a/libraries/base/dp/hdllib.cfg +++ b/libraries/base/dp/hdllib.cfg @@ -300,6 +300,7 @@ test_bench_files = tb/vhdl/tb_tb_dp_block_validate_channel.vhd tb/vhdl/tb_tb_dp_bsn_align.vhd tb/vhdl/tb_tb_dp_bsn_align_v2.vhd + tb/vhdl/tb_tb_mmp_dp_bsn_align_v2.vhd tb/vhdl/tb_tb_dp_bsn_source_v2.vhd tb/vhdl/tb_tb_dp_bsn_sync_scheduler.vhd tb/vhdl/tb_tb_dp_concat.vhd @@ -357,7 +358,6 @@ regression_test_vhdl = tb/vhdl/tb_dp_latency_adapter.vhd tb/vhdl/tb_dp_shiftreg.vhd tb/vhdl/tb_dp_bsn_source.vhd - tb/vhdl/tb_mmp_dp_bsn_align_v2.vhd tb/vhdl/tb_mms_dp_bsn_source.vhd tb/vhdl/tb_mms_dp_bsn_source_v2.vhd tb/vhdl/tb_mmp_dp_bsn_sync_scheduler.vhd @@ -372,6 +372,7 @@ regression_test_vhdl = tb/vhdl/tb_tb_dp_block_from_mm.vhd tb/vhdl/tb_tb_dp_block_validate_channel.vhd tb/vhdl/tb_tb_dp_bsn_align_v2.vhd + tb/vhdl/tb_tb_mmp_dp_bsn_align_v2.vhd tb/vhdl/tb_tb_dp_bsn_source_v2.vhd tb/vhdl/tb_tb_dp_bsn_sync_scheduler.vhd tb/vhdl/tb_tb_dp_concat.vhd diff --git a/libraries/base/dp/src/vhdl/dp_bsn_sync_scheduler.vhd b/libraries/base/dp/src/vhdl/dp_bsn_sync_scheduler.vhd index 0d5b21ea615ec19a28357937cc811b4c43b23ddc..22099bf168a065ce4064308f9e30c4a84b12f1e0 100644 --- a/libraries/base/dp/src/vhdl/dp_bsn_sync_scheduler.vhd +++ b/libraries/base/dp/src/vhdl/dp_bsn_sync_scheduler.vhd @@ -111,29 +111,31 @@ USE work.dp_stream_pkg.ALL; ENTITY dp_bsn_sync_scheduler IS GENERIC ( - g_bsn_w : NATURAL := c_dp_stream_bsn_w; - g_block_size : NATURAL := 256; -- = number of data valid per BSN block, must be >= 2 - g_pipeline : NATURAL := 1 -- use '1' on HW, use '0' for easier debugging in Wave window + g_bsn_w : NATURAL := c_dp_stream_bsn_w; + g_block_size : NATURAL := 256; -- = number of data valid per BSN block, must be >= 2 + g_ctrl_interval_size_min : NATURAL := 1; -- Minimum interval size to use if MM write interval size is set too small. + g_pipeline : NATURAL := 1 -- use '1' on HW, use '0' for easier debugging in Wave window ); PORT ( - rst : IN STD_LOGIC; - clk : IN STD_LOGIC; + rst : IN STD_LOGIC; + clk : IN STD_LOGIC; -- M&C - ctrl_enable : IN STD_LOGIC; - ctrl_enable_evt : IN STD_LOGIC; - ctrl_interval_size : IN NATURAL; - ctrl_start_bsn : IN STD_LOGIC_VECTOR(g_bsn_w-1 DOWNTO 0) := (OTHERS=>'0'); - mon_current_input_bsn : OUT STD_LOGIC_VECTOR(g_bsn_w-1 DOWNTO 0); - mon_input_bsn_at_sync : OUT STD_LOGIC_VECTOR(g_bsn_w-1 DOWNTO 0); - mon_output_enable : OUT STD_LOGIC; - mon_output_sync_bsn : OUT STD_LOGIC_VECTOR(g_bsn_w-1 DOWNTO 0); + ctrl_enable : IN STD_LOGIC; + ctrl_enable_evt : IN STD_LOGIC; + ctrl_interval_size : IN NATURAL; + ctrl_start_bsn : IN STD_LOGIC_VECTOR(g_bsn_w-1 DOWNTO 0) := (OTHERS=>'0'); + mon_current_input_bsn : OUT STD_LOGIC_VECTOR(g_bsn_w-1 DOWNTO 0); + mon_input_bsn_at_sync : OUT STD_LOGIC_VECTOR(g_bsn_w-1 DOWNTO 0); + mon_output_enable : OUT STD_LOGIC; + mon_output_interval_size : OUT NATURAL; + mon_output_sync_bsn : OUT STD_LOGIC_VECTOR(g_bsn_w-1 DOWNTO 0); -- Streaming - in_sosi : IN t_dp_sosi; - out_sosi : OUT t_dp_sosi; - out_start : OUT STD_LOGIC; -- pulse at out_sosi.sync at ctrl_start_bsn - out_enable : OUT STD_LOGIC -- for tb verification purposes + in_sosi : IN t_dp_sosi; + out_sosi : OUT t_dp_sosi; + out_start : OUT STD_LOGIC; -- pulse at out_sosi.sync at ctrl_start_bsn + out_enable : OUT STD_LOGIC -- for tb verification purposes ); END dp_bsn_sync_scheduler; @@ -158,7 +160,7 @@ ARCHITECTURE rtl OF dp_bsn_sync_scheduler IS output_sync_bsn : STD_LOGIC_VECTOR(g_bsn_w-1 DOWNTO 0); END RECORD; - CONSTANT c_reg_rst : t_reg := ('0', '0', 0, 0, (OTHERS=>'0'), (OTHERS=>'0'), 0, 0, 0, 0, 0, '1', '0', '0', (OTHERS=>'0')); + CONSTANT c_reg_rst : t_reg := ('0', '0', 0, g_ctrl_interval_size_min, (OTHERS=>'0'), (OTHERS=>'0'), 0, 0, 0, 0, 0, '1', '0', '0', (OTHERS=>'0')); -- Local registers SIGNAL r : t_reg; @@ -173,10 +175,11 @@ BEGIN ASSERT g_block_size >= 2 REPORT "g_block_size must be >= 2." SEVERITY FAILURE; -- Capture monitoring info - mon_current_input_bsn <= in_sosi.bsn(g_bsn_w-1 DOWNTO 0) WHEN rising_edge(clk) AND in_sosi.sop = '1'; - mon_input_bsn_at_sync <= in_sosi.bsn(g_bsn_w-1 DOWNTO 0) WHEN rising_edge(clk) AND in_sosi.sync = '1'; - mon_output_enable <= r.output_enable; - mon_output_sync_bsn <= r.output_sync_bsn; + mon_current_input_bsn <= in_sosi.bsn(g_bsn_w-1 DOWNTO 0) WHEN rising_edge(clk) AND in_sosi.sop = '1'; + mon_input_bsn_at_sync <= in_sosi.bsn(g_bsn_w-1 DOWNTO 0) WHEN rising_edge(clk) AND in_sosi.sync = '1'; + mon_output_enable <= r.output_enable; + mon_output_interval_size <= g_ctrl_interval_size_min WHEN rst='1' ELSE r.interval_size WHEN rising_edge(clk) AND output_start = '1'; + mon_output_sync_bsn <= r.output_sync_bsn; p_clk : PROCESS(rst, clk) BEGIN diff --git a/libraries/base/dp/src/vhdl/mmp_dp_bsn_sync_scheduler.vhd b/libraries/base/dp/src/vhdl/mmp_dp_bsn_sync_scheduler.vhd index 75b42316d077b32591da03f6a12aff7ee6da26d9..9cfe48f8dba79806999f160015e2e625b4753190 100644 --- a/libraries/base/dp/src/vhdl/mmp_dp_bsn_sync_scheduler.vhd +++ b/libraries/base/dp/src/vhdl/mmp_dp_bsn_sync_scheduler.vhd @@ -22,7 +22,8 @@ -- -- wi Bits Access Type Name -- 0 [0] RW boolean ctrl_enable, '1' is on, '0' is FALSE is off --- 1 [31:0] RW uint32 ctrl_interval_size +-- 1 [31:0] RW uint32 W: ctrl_interval_size +-- R: mon_output_interval_size -- 2 [31:0] RW uint64 ctrl_start_bsn[31:0] -- 3 [31:0] RW ctrl_start_bsn[63:32] -- 4 [31:0] RO uint64 mon_current_input_bsn[31:0] @@ -63,7 +64,7 @@ USE work.dp_stream_pkg.ALL; ENTITY mmp_dp_bsn_sync_scheduler IS GENERIC ( g_bsn_w : NATURAL := c_dp_stream_bsn_w; - g_block_size : NATURAL := 256; -- = number of data valid per BSN block, must be >= 2 + g_block_size : NATURAL := 256; -- = number of data valid per BSN block, must be >= 2 g_ctrl_interval_size_min : NATURAL := 1 -- Minimum interval size to use if MM write interval size is set too small. ); PORT ( @@ -95,20 +96,21 @@ ARCHITECTURE str OF mmp_dp_bsn_sync_scheduler IS -- init_sl : STD_LOGIC; -- optional, init all dat words to std_logic '0', '1' or 'X' CONSTANT c_mm_reg : t_c_mem := (1, 4, c_word_w, 12, '0'); - SIGNAL reg_wr_arr : STD_LOGIC_VECTOR(c_mm_reg.nof_dat -1 DOWNTO 0); - SIGNAL reg_wr : STD_LOGIC_VECTOR(c_mm_reg.nof_dat*c_mm_reg.dat_w-1 DOWNTO 0); - SIGNAL reg_rd : STD_LOGIC_VECTOR(c_mm_reg.nof_dat*c_mm_reg.dat_w-1 DOWNTO 0) := (OTHERS=>'0'); - - SIGNAL wr_ctrl_enable : STD_LOGIC; - SIGNAL wr_ctrl_enable_evt : STD_LOGIC; - SIGNAL ctrl_enable : STD_LOGIC := '0'; - SIGNAL ctrl_enable_evt : STD_LOGIC := '0'; - SIGNAL ctrl_interval_size : NATURAL; - SIGNAL ctrl_start_bsn : STD_LOGIC_VECTOR(g_bsn_w-1 DOWNTO 0) := (OTHERS=>'0'); - SIGNAL mon_current_input_bsn : STD_LOGIC_VECTOR(g_bsn_w-1 DOWNTO 0); - SIGNAL mon_input_bsn_at_sync : STD_LOGIC_VECTOR(g_bsn_w-1 DOWNTO 0); - SIGNAL mon_output_enable : STD_LOGIC; - SIGNAL mon_output_sync_bsn : STD_LOGIC_VECTOR(g_bsn_w-1 DOWNTO 0); + SIGNAL reg_wr_arr : STD_LOGIC_VECTOR(c_mm_reg.nof_dat -1 DOWNTO 0); + SIGNAL reg_wr : STD_LOGIC_VECTOR(c_mm_reg.nof_dat*c_mm_reg.dat_w-1 DOWNTO 0); + SIGNAL reg_rd : STD_LOGIC_VECTOR(c_mm_reg.nof_dat*c_mm_reg.dat_w-1 DOWNTO 0) := (OTHERS=>'0'); + + SIGNAL wr_ctrl_enable : STD_LOGIC; + SIGNAL wr_ctrl_enable_evt : STD_LOGIC; + SIGNAL ctrl_enable : STD_LOGIC := '0'; + SIGNAL ctrl_enable_evt : STD_LOGIC := '0'; + SIGNAL ctrl_interval_size : NATURAL; + SIGNAL ctrl_start_bsn : STD_LOGIC_VECTOR(g_bsn_w-1 DOWNTO 0) := (OTHERS=>'0'); + SIGNAL mon_current_input_bsn : STD_LOGIC_VECTOR(g_bsn_w-1 DOWNTO 0); + SIGNAL mon_input_bsn_at_sync : STD_LOGIC_VECTOR(g_bsn_w-1 DOWNTO 0); + SIGNAL mon_output_enable : STD_LOGIC; + SIGNAL mon_output_interval_size : NATURAL; + SIGNAL mon_output_sync_bsn : STD_LOGIC_VECTOR(g_bsn_w-1 DOWNTO 0); -- Resize BSN values to 64 bit SIGNAL wr_start_bsn_64 : STD_LOGIC_VECTOR(2*c_word_w-1 DOWNTO 0); @@ -151,7 +153,7 @@ BEGIN -- . Read reg_rd( 0) <= ctrl_enable; -- read back internal ctrl_enable - reg_rd( 2*c_word_w-1 DOWNTO 1*c_word_w) <= TO_UVEC(ctrl_interval_size, c_word_w); + reg_rd( 2*c_word_w-1 DOWNTO 1*c_word_w) <= TO_UVEC(mon_output_interval_size, c_word_w); reg_rd( 3*c_word_w-1 DOWNTO 2*c_word_w) <= wr_start_bsn_64( c_word_w-1 DOWNTO 0); -- low word reg_rd( 4*c_word_w-1 DOWNTO 3*c_word_w) <= wr_start_bsn_64( 2*c_word_w-1 DOWNTO c_word_w); -- high word reg_rd( 5*c_word_w-1 DOWNTO 4*c_word_w) <= rd_current_input_bsn_64( c_word_w-1 DOWNTO 0); -- low word @@ -189,29 +191,31 @@ BEGIN u_dp_bsn_sync_scheduler : ENTITY work.dp_bsn_sync_scheduler GENERIC MAP ( - g_bsn_w => g_bsn_w, - g_block_size => g_block_size, - g_pipeline => 1 + g_bsn_w => g_bsn_w, + g_block_size => g_block_size, + g_ctrl_interval_size_min => g_ctrl_interval_size_min, + g_pipeline => 1 ) PORT MAP ( - rst => dp_rst, - clk => dp_clk, + rst => dp_rst, + clk => dp_clk, -- M&C - ctrl_enable => ctrl_enable, - ctrl_enable_evt => ctrl_enable_evt, - ctrl_interval_size => ctrl_interval_size, - ctrl_start_bsn => ctrl_start_bsn, - mon_current_input_bsn => mon_current_input_bsn, - mon_input_bsn_at_sync => mon_input_bsn_at_sync, - mon_output_enable => mon_output_enable, - mon_output_sync_bsn => mon_output_sync_bsn, + ctrl_enable => ctrl_enable, + ctrl_enable_evt => ctrl_enable_evt, + ctrl_interval_size => ctrl_interval_size, + ctrl_start_bsn => ctrl_start_bsn, + mon_current_input_bsn => mon_current_input_bsn, + mon_input_bsn_at_sync => mon_input_bsn_at_sync, + mon_output_enable => mon_output_enable, + mon_output_interval_size => mon_output_interval_size, + mon_output_sync_bsn => mon_output_sync_bsn, -- Streaming - in_sosi => in_sosi, - out_sosi => out_sosi, - out_start => out_start, - out_enable => out_enable + in_sosi => in_sosi, + out_sosi => out_sosi, + out_start => out_start, + out_enable => out_enable ); END str; diff --git a/libraries/base/dp/tb/vhdl/tb_mmp_dp_bsn_align_v2.vhd b/libraries/base/dp/tb/vhdl/tb_mmp_dp_bsn_align_v2.vhd index a7b2234a79a41c7fb71c5250e2a999c8d3cbb43e..d9fd975a4eb30877fd101260a963134aab754ba7 100644 --- a/libraries/base/dp/tb/vhdl/tb_mmp_dp_bsn_align_v2.vhd +++ b/libraries/base/dp/tb/vhdl/tb_mmp_dp_bsn_align_v2.vhd @@ -45,6 +45,9 @@ USE work.dp_stream_pkg.ALL; USE work.tb_dp_pkg.ALL; ENTITY tb_mmp_dp_bsn_align_v2 IS + GENERIC ( + g_lost_input : BOOLEAN := TRUE -- when TRUE use c_nof_streams-1 as lost input + ); END tb_mmp_dp_bsn_align_v2; @@ -60,11 +63,12 @@ ARCHITECTURE tb OF tb_mmp_dp_bsn_align_v2 IS -- Fixed dut generics -- . for dp_bsn_align_v2 - CONSTANT c_nof_streams : NATURAL := 3; + CONSTANT c_nof_streams : NATURAL := 5; CONSTANT c_bsn_latency_max : NATURAL := 1; CONSTANT c_nof_aligners_max : POSITIVE := 1; -- fixed in this tb CONSTANT c_block_size : NATURAL := 11; CONSTANT c_block_period : NATURAL := 11; + CONSTANT c_block_per_sync : NATURAL := 7; CONSTANT c_bsn_w : NATURAL := c_dp_stream_bsn_w; CONSTANT c_data_w : NATURAL := 16; CONSTANT c_data_replacement_value : INTEGER := 17; @@ -73,7 +77,7 @@ ARCHITECTURE tb OF tb_mmp_dp_bsn_align_v2 IS CONSTANT c_pipeline_output : NATURAL := 1; CONSTANT c_rd_latency : NATURAL := 2; -- . for mms_dp_bsn_monitor_v2 - CONSTANT c_nof_clk_per_sync : NATURAL := 200*10**6; + CONSTANT c_nof_clk_per_sync : NATURAL := c_block_per_sync * c_block_period; CONSTANT c_nof_input_bsn_monitors : NATURAL := c_nof_streams; CONSTANT c_use_bsn_output_monitor : BOOLEAN := TRUE; @@ -96,8 +100,7 @@ ARCHITECTURE tb OF tb_mmp_dp_bsn_align_v2 IS CONSTANT c_bsn_init : NATURAL := 3; CONSTANT c_channel_init : INTEGER := 0; CONSTANT c_err_init : NATURAL := 247; - CONSTANT c_sync_period : NATURAL := 7; - CONSTANT c_sync_offset : NATURAL := 2; + CONSTANT c_sync_bsn_offset : NATURAL := 2; CONSTANT c_gap_size : NATURAL := c_block_period - c_block_size; -- DUT latency @@ -138,8 +141,8 @@ ARCHITECTURE tb OF tb_mmp_dp_bsn_align_v2 IS SIGNAL reg_output_monitor_copi : t_mem_copi := c_mem_copi_rst; SIGNAL reg_output_monitor_cipo : t_mem_cipo; - SIGNAL mon_latency_input_arr : t_nat_natural_arr(c_nof_streams-1 DOWNTO 0); - SIGNAL mon_latency_output : NATURAL; + SIGNAL mon_latency_input_arr : t_integer_arr(c_nof_streams-1 DOWNTO 0); + SIGNAL mon_latency_output : INTEGER; -- DP clock domain SIGNAL dp_clk : STD_LOGIC := '1'; @@ -173,7 +176,7 @@ ARCHITECTURE tb OF tb_mmp_dp_bsn_align_v2 IS SIGNAL out_err_arr : t_err_arr; SIGNAL verify_done_arr : STD_LOGIC_VECTOR(c_nof_streams-1 DOWNTO 0) := (OTHERS => '0'); - SIGNAL verify_done : STD_LOGIC; + SIGNAL verify_done : STD_LOGIC := '0'; SIGNAL hold_out_sop_arr : STD_LOGIC_VECTOR(c_nof_streams-1 DOWNTO 0) := (OTHERS => '0'); SIGNAL expected_out_bsn_arr : t_bsn_arr; @@ -257,15 +260,19 @@ BEGIN FOR I IN 0 TO c_nof_streams-1 LOOP proc_mem_mm_bus_rd(6 + I*c_reg_bsn_monitor_span, mm_clk, reg_input_monitor_cipo, reg_input_monitor_copi); proc_mem_mm_bus_rd_latency(1, mm_clk); - mon_latency_input_arr(I) <= TO_UINT(reg_input_monitor_cipo.rddata); + mon_latency_input_arr(I) <= TO_SINT(reg_input_monitor_cipo.rddata(31 DOWNTO 0)); proc_common_wait_some_cycles(mm_clk, 1); - ASSERT mon_latency_input_arr(I) = func_input_delay(I) REPORT "Wrong input BSN monitor latency for input " & int_to_str(I) SEVERITY ERROR; + IF g_lost_input = TRUE AND I = c_nof_streams-1 THEN + ASSERT mon_latency_input_arr(I) = -1 REPORT "Wrong input BSN monitor latency timeout for input " & int_to_str(I) SEVERITY ERROR; + ELSE + ASSERT mon_latency_input_arr(I) = func_input_delay(I) REPORT "Wrong input BSN monitor latency for input " & int_to_str(I) SEVERITY ERROR; + END IF; END LOOP; -- Read output BSN monitor proc_mem_mm_bus_rd(6, mm_clk, reg_output_monitor_cipo, reg_output_monitor_copi); proc_mem_mm_bus_rd_latency(1, mm_clk); - mon_latency_output <= TO_UINT(reg_output_monitor_cipo.rddata); + mon_latency_output <= TO_SINT(reg_output_monitor_cipo.rddata(31 DOWNTO 0)); proc_common_wait_some_cycles(mm_clk, 1); ASSERT mon_latency_output = c_total_latency REPORT "Wrong output BSN monitor latency" SEVERITY ERROR; @@ -299,14 +306,14 @@ BEGIN FOR S IN 0 TO c_tb_nof_restart-1 LOOP v_bsn := c_bsn_init; FOR R IN 0 TO c_tb_nof_blocks-1 LOOP - v_sync := sel_a_b(v_bsn MOD c_sync_period = c_sync_offset, '1', '0'); + v_sync := sel_a_b(v_bsn MOD c_block_per_sync = c_sync_bsn_offset, '1', '0'); proc_dp_gen_block_data(c_rl, TRUE, c_data_w, c_data_w, v_data, 0, 0, c_block_size, v_channel, v_err, v_sync, TO_UVEC(v_bsn, c_bsn_w), dp_clk, sl1, ref_siso_arr(I), ref_sosi_arr(I)); v_bsn := v_bsn + 1; v_data := v_data + c_block_size; proc_common_wait_some_cycles(dp_clk, c_gap_size); -- create gap between frames END LOOP; -- Create gap between restarts - proc_common_wait_some_cycles(dp_clk, 100); + proc_common_wait_some_cycles(dp_clk, 10); restart_cnt_arr(I) <= restart_cnt_arr(I) + 1; END LOOP; @@ -314,10 +321,15 @@ BEGIN -- . default c_bsn_latency_max blocks remain in DUT buffer expected_out_bsn_arr(I) <= TO_UVEC(v_bsn-1 - c_align_latency_nof_blocks, c_bsn_w); expected_out_data_arr(I) <= TO_UVEC(v_data-1 - c_align_latency_nof_valid, c_data_w); - -- . default no data is lost, so all channel(0) lost data flags are 0 + -- . default no data is lost, so all channel(bit 0) lost data flags are 0 expected_out_channel_arr(I) <= TO_DP_CHANNEL(0); - - proc_common_wait_some_cycles(dp_clk, 100); + IF g_lost_input = TRUE THEN + IF I = c_nof_streams-1 THEN + expected_out_data_arr(I) <= TO_UVEC(c_data_replacement_value, c_data_w); + expected_out_channel_arr(I) <= TO_DP_CHANNEL(1); + END IF; + END IF; + proc_common_wait_some_cycles(dp_clk, 10); verify_done_arr(I) <= '1'; proc_common_wait_some_cycles(dp_clk, 1); verify_done_arr(I) <= '0'; @@ -329,15 +341,25 @@ BEGIN END PROCESS; END GENERATE; - verify_done <= verify_done_arr(0); + verify_done <= '1' WHEN verify_done_arr(0) = '1'; restart_cnt <= restart_cnt_arr(0); dp_end <= vector_and(dp_end_arr); -- Model misalignment latency between the input streams to have different -- input BSN monitor latencies - gen_rx_sosi_arr : FOR I IN c_nof_streams-1 DOWNTO 0 GENERATE - in_sosi_arr(I) <= TRANSPORT ref_sosi_arr(I) AFTER func_input_delay(I) * c_dp_clk_period; + no_lost_input : IF g_lost_input = FALSE GENERATE + gen_in_sosi_arr : FOR I IN c_nof_streams-1 DOWNTO 0 GENERATE + in_sosi_arr(I) <= TRANSPORT ref_sosi_arr(I) AFTER func_input_delay(I) * c_dp_clk_period; + END GENERATE; + END GENERATE; + + one_lost_input : IF g_lost_input = TRUE GENERATE + -- Model missing enabled input stream at index c_lost_input = c_nof_streams-1 + in_sosi_arr(c_nof_streams-1) <= c_dp_sosi_rst; + gen_in_sosi_arr : FOR I IN c_nof_streams-2 DOWNTO 0 GENERATE + in_sosi_arr(I) <= TRANSPORT ref_sosi_arr(I) AFTER func_input_delay(I) * c_dp_clk_period; + END GENERATE; END GENERATE; ------------------------------------------------------------------------------ diff --git a/libraries/base/dp/tb/vhdl/tb_mmp_dp_bsn_sync_scheduler.vhd b/libraries/base/dp/tb/vhdl/tb_mmp_dp_bsn_sync_scheduler.vhd index ce4e5f605e7efbba13cb3ec7a972a5d9b9548805..43162d9c6df7dd1b3e4b768e0353f9f65d51e791 100644 --- a/libraries/base/dp/tb/vhdl/tb_mmp_dp_bsn_sync_scheduler.vhd +++ b/libraries/base/dp/tb/vhdl/tb_mmp_dp_bsn_sync_scheduler.vhd @@ -52,6 +52,7 @@ ARCHITECTURE tb OF tb_mmp_dp_bsn_sync_scheduler IS CONSTANT c_nof_block_per_input_sync : NATURAL := 17; CONSTANT c_nof_block_per_output_sync : NATURAL := 5; CONSTANT c_block_size : NATURAL := 10; + CONSTANT c_ctrl_interval_size_min : NATURAL := 19; -- Minimum interval size to use if MM write interval size is set too small. CONSTANT c_input_gap_size : NATURAL := 3; CONSTANT c_sim_nof_blocks : NATURAL := c_nof_block_per_input_sync * c_nof_input_sync; @@ -75,6 +76,7 @@ ARCHITECTURE tb OF tb_mmp_dp_bsn_sync_scheduler IS SIGNAL ctrl_start_bsn_64 : STD_LOGIC_VECTOR(2*c_word_w-1 DOWNTO 0); SIGNAL mon_output_enable : STD_LOGIC; + SIGNAL mon_output_interval_size : NATURAL; SIGNAL mon_current_input_bsn_64 : STD_LOGIC_VECTOR(2*c_word_w-1 DOWNTO 0); SIGNAL mon_input_bsn_at_sync_64 : STD_LOGIC_VECTOR(2*c_word_w-1 DOWNTO 0); SIGNAL mon_output_sync_bsn_64 : STD_LOGIC_VECTOR(2*c_word_w-1 DOWNTO 0); @@ -118,6 +120,13 @@ BEGIN proc_common_wait_some_cycles(mm_clk, 1); ASSERT mon_block_size = c_block_size REPORT "Wrong block_size." SEVERITY ERROR; + -- . Read mon_output_interval_size + proc_mem_mm_bus_rd(1, mm_clk, reg_miso, reg_mosi); + proc_mem_mm_bus_rd_latency(1, mm_clk); + mon_output_interval_size <= TO_UINT(reg_miso.rddata(c_word_w-1 DOWNTO 0)); + proc_common_wait_some_cycles(mm_clk, 1); + ASSERT mon_output_interval_size = c_ctrl_interval_size_min REPORT "Wrong minimum output interval_size." SEVERITY ERROR; + -- . Read mon_output_enable proc_mem_mm_bus_rd(8, mm_clk, reg_miso, reg_mosi); proc_mem_mm_bus_rd_latency(1, mm_clk); @@ -214,10 +223,16 @@ BEGIN proc_mem_mm_bus_rd_latency(1, mm_clk); mon_output_enable <= reg_miso.rddata(0); + -- . Read mon_output_interval_size + proc_mem_mm_bus_rd(1, mm_clk, reg_miso, reg_mosi); + proc_mem_mm_bus_rd_latency(1, mm_clk); + mon_output_interval_size <= TO_UINT(reg_miso.rddata(c_word_w-1 DOWNTO 0)); + -- Verify output is on and running proc_common_wait_some_cycles(mm_clk, 1); ASSERT mon_output_enable = '1' REPORT "mon_output_enable is not enabled." SEVERITY ERROR; ASSERT out_enable = '1' REPORT "output_enable is not enabled." SEVERITY ERROR; + ASSERT mon_output_interval_size = c_ctrl_interval_size REPORT "mon_output_interval_size is not ctrl_interval_size." SEVERITY ERROR; --------------------------------------------------------------------------- -- Check that monitor BSN are incrementing @@ -381,8 +396,9 @@ BEGIN u_mmp_dp_bsn_sync_scheduler : ENTITY work.mmp_dp_bsn_sync_scheduler GENERIC MAP ( - g_bsn_w => c_bsn_w, - g_block_size => c_block_size + g_bsn_w => c_bsn_w, + g_block_size => c_block_size, + g_ctrl_interval_size_min => c_ctrl_interval_size_min ) PORT MAP ( -- Clocks and reset diff --git a/libraries/base/dp/tb/vhdl/tb_tb_mmp_dp_bsn_align_v2.vhd b/libraries/base/dp/tb/vhdl/tb_tb_mmp_dp_bsn_align_v2.vhd new file mode 100644 index 0000000000000000000000000000000000000000..7eea68cc3bdd53a99d18a3334f5df6d2a1fa3f16 --- /dev/null +++ b/libraries/base/dp/tb/vhdl/tb_tb_mmp_dp_bsn_align_v2.vhd @@ -0,0 +1,46 @@ +-- -------------------------------------------------------------------------- +-- Copyright 2021 +-- 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. +-- -------------------------------------------------------------------------- +-- +-- Author: E. Kooistra, 2 march 2022 +-- Purpose: Regression multi tb for mmp_dp_bsn_align_v2 +-- Description: +-- Usage: +-- > as 3 +-- > run -all + +LIBRARY IEEE; +USE IEEE.std_logic_1164.ALL; +USE work.tb_dp_pkg.ALL; + + +ENTITY tb_tb_mmp_dp_bsn_align_v2 IS +END tb_tb_mmp_dp_bsn_align_v2; + + +ARCHITECTURE tb OF tb_tb_mmp_dp_bsn_align_v2 IS + + SIGNAL tb_end : STD_LOGIC := '0'; -- declare tb_end to avoid 'No objects found' error on 'when -label tb_end' + +BEGIN + + -- g_lost_input : BOOLEAN := FALSE + + u_no_lost_input : ENTITY work.tb_mmp_dp_bsn_align_v2 GENERIC MAP (FALSE); + u_one_lost_input : ENTITY work.tb_mmp_dp_bsn_align_v2 GENERIC MAP (TRUE); + +END tb;