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 33b59b65c850bef7be1f1f6503e2b333b343bac1..c36f8e1ac4b5e6dc3933d580b2c0aabefa2fa854 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 @@ -53,16 +53,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 -- BST g_beamset_id : NATURAL := 1; -- < c_sdp_N_beamsets -- XST g_O_rn : NATURAL := 4; -- 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 := 1; -- <= c_sdp_P_sq - g_nof_crosslets : NATURAL := 1; -- <= c_sdp_N_crosslets_max + g_P_sq : NATURAL := 4; -- <= c_sdp_P_sq + g_nof_crosslets : NATURAL := 3; -- <= 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; @@ -97,23 +98,33 @@ ARCHITECTURE tb OF tb_sdp_statistics_offload IS CONSTANT c_crosslets_info_rec : t_sdp_crosslets_info := (offset_arr => (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15), step => 16); CONSTANT c_crosslets_info_slv : STD_LOGIC_VECTOR(c_sdp_crosslets_info_reg_w-1 DOWNTO 0) := func_sdp_map_crosslets_info(c_crosslets_info_rec); + -- 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); + -- payload data - CONSTANT c_data_size : NATURAL := c_sdp_W_statistic_sz; - CONSTANT c_nof_data : NATURAL := c_nof_statistics_per_packet; + CONSTANT c_packet_size : NATURAL := c_nof_statistics_per_packet * c_sdp_W_statistic_sz; - -- Define SST RAM size for c_nof_packets_max. - CONSTANT c_ram_size : NATURAL := c_nof_data * c_data_size * c_nof_packets_max; + -- Define statistics RAM size for c_nof_packets_max. + CONSTANT c_ram_size : NATURAL := c_packet_size * c_nof_packets_max; CONSTANT c_ram_w : NATURAL := ceil_log2(c_ram_size); --CONSTANT c_ram_buf : t_c_mem := (c_mem_ram_rd_latency, c_ram_w, 32, 2**c_ram_w, 'X'); CONSTANT c_ram_buf : t_c_mem := (1, c_ram_w, 32, 2**c_ram_w, 'X'); + -- RAM dimensions + -- . nof_statistics_per_packet = c_mm_nof_data * c_mm_data_size / c_sdp_W_statistic_sz + CONSTANT c_mm_data_size : NATURAL := func_sdp_get_stat_from_mm_data_size(g_statistics_type); + CONSTANT c_mm_step_size : NATURAL := func_sdp_get_stat_from_mm_step_size(g_statistics_type); + CONSTANT c_mm_nof_data : NATURAL := func_sdp_get_stat_from_mm_nof_data(g_statistics_type); + CONSTANT c_mm_ram_size : NATURAL := c_mm_nof_data * c_mm_data_size * c_nof_packets_max; -- = c_ram_size + -- Define block timing. CONSTANT c_bsn_init : NATURAL := 0; - CONSTANT c_nof_block_per_sync : NATURAL := 3 + ceil_div(c_offload_time, c_nof_data) + c_nof_packets_max; -- Sufficient to fit more than c_nof_packets_max offload packets per sync interval. - CONSTANT c_nof_clk_per_block : NATURAL := c_nof_data * c_data_size; - CONSTANT c_nof_valid_per_block : NATURAL := c_nof_data * c_data_size; - CONSTANT c_nof_sync : NATURAL := 3; + -- Sufficient c_nof_block_per_sync to fit more than c_nof_packets_max offload packets per sync interval. + CONSTANT c_nof_block_per_sync : NATURAL := 3 + ceil_div(c_offload_time, c_packet_size) + c_nof_packets_max; + CONSTANT c_nof_clk_per_block : NATURAL := c_packet_size; CONSTANT c_nof_clk_per_sync : NATURAL := c_nof_block_per_sync * c_nof_clk_per_block; + CONSTANT c_nof_sync : NATURAL := 3; SIGNAL tb_end : STD_LOGIC := '0'; @@ -143,11 +154,11 @@ ARCHITECTURE tb OF tb_sdp_statistics_offload IS SIGNAL offload_sosi : t_dp_sosi; SIGNAL offload_siso : t_dp_siso := c_dp_siso_rst; + SIGNAL test_offload_en : STD_LOGIC := '0'; SIGNAL test_offload_data : STD_LOGIC_VECTOR(c_word_w-1 DOWNTO 0); -- 32 bit SIGNAL test_offload_sosi : t_dp_sosi := c_dp_sosi_rst; - SIGNAL test_offload_en : STD_LOGIC := '0'; - SIGNAL test_offload_sop_cnt : NATURAL; - SIGNAL test_offload_eop_cnt : NATURAL; + SIGNAL test_offload_sop_cnt : NATURAL := 0; + SIGNAL test_offload_eop_cnt : NATURAL := 0; SIGNAL rx_hdr_fields_out : STD_LOGIC_VECTOR(1023 DOWNTO 0); SIGNAL rx_hdr_fields_raw : STD_LOGIC_VECTOR(1023 DOWNTO 0) := (OTHERS => '0'); @@ -163,7 +174,11 @@ ARCHITECTURE tb OF tb_sdp_statistics_offload IS SIGNAL exp_xst_signal_input_A : NATURAL; SIGNAL exp_xst_signal_input_B : NATURAL; - -- Signals used to change settings of sdp_info. + SIGNAL rx_val : STD_LOGIC := '0'; + SIGNAL rx_data : NATURAL; + SIGNAL exp_data : NATURAL; + + -- Signals used to change settings of sdp_info. SIGNAL sdp_info : t_sdp_info := ( TO_UVEC(601, 16), -- station_id '0', -- antenna_band_index @@ -185,8 +200,6 @@ ARCHITECTURE tb OF tb_sdp_statistics_offload IS SIGNAL source_gn : NATURAL; -- source node GN SIGNAL subband_calibrated_flag : STD_LOGIC := '0'; - SIGNAL nof_crosslets : STD_LOGIC_VECTOR(c_sdp_nof_crosslets_reg_w-1 DOWNTO 0) := (OTHERS => '0'); - SIGNAL nof_packets : NATURAL; -- Signals used for starting processes. SIGNAL ram_wr_data : STD_LOGIC_VECTOR(c_ram_buf.dat_w-1 DOWNTO 0); @@ -194,9 +207,8 @@ ARCHITECTURE tb OF tb_sdp_statistics_offload IS SIGNAL ram_wr_en : STD_LOGIC; SIGNAL init_ram_done : STD_LOGIC := '0'; - SIGNAL in_sync_hold : STD_LOGIC := '0'; SIGNAL in_sync_cnt : NATURAL := 0; - SIGNAL test_sync_cnt : INTEGER; + SIGNAL test_sync_cnt : INTEGER := 0; SIGNAL rx_packet_cnt : NATURAL := 0; SIGNAL rx_valid_cnt : NATURAL := 0; @@ -209,14 +221,20 @@ ARCHITECTURE tb OF tb_sdp_statistics_offload IS 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_beamlet_index : NATURAL := c_beamlet_index; - SIGNAL dbg_c_data_size : NATURAL := c_data_size; - SIGNAL dbg_c_nof_data : NATURAL := c_nof_data; + SIGNAL dbg_c_packet_size : NATURAL := c_packet_size; + SIGNAL dbg_c_mm_data_size : NATURAL := c_mm_data_size; + SIGNAL dbg_c_mm_step_size : NATURAL := c_mm_step_size; + SIGNAL dbg_c_mm_nof_data : NATURAL := c_mm_nof_data; + SIGNAL dbg_c_mm_ram_size : NATURAL := c_mm_ram_size; SIGNAL dbg_c_ram_size : NATURAL := c_ram_size; SIGNAL dbg_c_crosslets_info_rec : t_sdp_crosslets_info := c_crosslets_info_rec; SIGNAL dbg_c_crosslets_info_slv : STD_LOGIC_VECTOR(c_sdp_crosslets_info_reg_w-1 DOWNTO 0) := c_crosslets_info_slv; BEGIN + -- Check consistency of constant value dependencies + ASSERT c_ram_size = c_mm_ram_size REPORT "Wrong derivation of RAM size." SEVERITY FAILURE; + dp_rst <= '1', '0' AFTER c_dp_clk_period*7; dp_clk <= (NOT dp_clk) OR tb_end AFTER c_dp_clk_period/2; @@ -292,36 +310,23 @@ BEGIN WAIT; END PROCESS; - -- Crosslets settings - nof_crosslets <= TO_UVEC(g_nof_crosslets, c_sdp_nof_crosslets_reg_w); - nof_packets <= func_sdp_get_stat_nof_packets(g_statistics_type, c_sdp_S_pn, g_P_sq, g_nof_crosslets); - -- Counters to time expected exp_sdp_stat_header fields per offload packet - p_exp_counters : PROCESS(dp_clk) + p_test_counters : PROCESS(dp_clk) BEGIN IF rising_edge(dp_clk) THEN - -- Count sync intervals using in_sosi.sync, because there is no test_offload_sosi.sync - IF test_offload_en = '0' THEN - in_sync_cnt <= 0; - test_offload_sop_cnt <= 0; - test_offload_eop_cnt <= 0; - ELSE - -- Count test_offload_sosi sync integration intervals - IF in_sosi.sync = '1' THEN - in_sync_cnt <= in_sync_cnt + 1; - END IF; - - -- Count test_offload_sosi packets - IF test_offload_sosi.sop = '1' THEN - test_offload_sop_cnt <= test_offload_sop_cnt + 1; -- early count - END IF; - IF test_offload_sosi.eop = '1' THEN - test_offload_eop_cnt <= test_offload_eop_cnt + 1; -- after count - END IF; + -- Count test_offload_sosi packets + IF test_offload_sosi.sop = '1' THEN + test_offload_sop_cnt <= test_offload_sop_cnt + 1; -- early count + END IF; + IF test_offload_sosi.eop = '1' THEN + test_offload_eop_cnt <= test_offload_eop_cnt + 1; -- after count END IF; END IF; END PROCESS; - test_sync_cnt <= in_sync_cnt + 0; -- optionally adjust to fit test_offload_sosi + + -- Count sync intervals using in_sosi.sync, because there is no test_offload_sosi.sync + in_sync_cnt <= in_sync_cnt + 1 WHEN rising_edge(dp_clk) AND in_sosi.sync = '1'; + 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; @@ -428,21 +433,16 @@ BEGIN END PROCESS; -- Count number of packets in a sync interval. - -- There is no active test_offload_sosi.sync to restart the count. Therefore capture the in_sosi.sync in in_sync_hold, and - -- use in_sync_hold with test_offload_sosi.sop to start counting packets from 0, at the start of every sync interval. + -- There is no active test_offload_sosi.sync to restart the count, therefore + -- use in_sosi.sync to reset the count for the next test_offload_sosi.sync + -- interval p_rx_packet_cnt : PROCESS(dp_clk) BEGIN IF rising_edge(dp_clk) THEN - IF test_offload_sosi.sop = '1' THEN - IF in_sync_hold = '1' THEN - in_sync_hold <= '0'; - rx_packet_cnt <= 0; - ELSE - rx_packet_cnt <= rx_packet_cnt + 1; - END IF; - END IF; IF in_sosi.sync = '1' THEN - in_sync_hold <= '1'; + rx_packet_cnt <= 0; + ELSIF test_offload_sosi.eop = '1' THEN + rx_packet_cnt <= rx_packet_cnt + 1; END IF; END IF; END PROCESS; @@ -451,12 +451,8 @@ BEGIN p_verify_nof_packets : PROCESS(dp_clk) BEGIN IF rising_edge(dp_clk) THEN - IF init_ram_done = '1' THEN - - IF in_sosi.sync = '1' AND rx_packet_cnt > 0 THEN - ASSERT rx_packet_cnt = nof_packets-1 REPORT "Wrong number of packets per sync interval" SEVERITY ERROR; - END IF; - + 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; END IF; END IF; END PROCESS; @@ -464,12 +460,147 @@ BEGIN p_verify_nof_valid_per_packet : PROCESS(dp_clk) BEGIN IF rising_edge(dp_clk) THEN - IF test_offload_sosi.sop = '1' THEN - rx_valid_cnt <= 1; - ELSIF test_offload_sosi.eop = '1' THEN - ASSERT rx_valid_cnt+1 = c_nof_valid_per_block REPORT "Wrong number of valid per packet" SEVERITY ERROR; - ELSE - rx_valid_cnt <= rx_valid_cnt + 1; -- test_offload_sosi.valid has no gaps + IF test_offload_sosi.eop = '1' THEN + rx_valid_cnt <= 0; + ASSERT rx_valid_cnt = c_packet_size - 1 REPORT "Wrong number of valid per packet" SEVERITY ERROR; + ELSIF test_offload_sosi.valid = '1' THEN + rx_valid_cnt <= rx_valid_cnt + 1; + END IF; + END IF; + END PROCESS; + + p_verify_payload : PROCESS(dp_clk) + CONSTANT c_nof_step : NATURAL := c_mm_step_size / c_mm_data_size; + VARIABLE W : NATURAL; -- 32bit Words + VARIABLE D : NATURAL; -- Data values of c_mm_data_size + VARIABLE S : NATURAL; -- Statistic values of c_sdp_W_statistic_sz + VARIABLE P : NATURAL; -- Packet count + VARIABLE I, J, K, L : NATURAL; -- auxiliary index + VARIABLE U : NATURAL; -- real sUbband SST values + VARIABLE B : NATURAL; -- dual polarization Beamlet BST values + VARIABLE X : NATURAL; -- complex crosslet XST values + VARIABLE v_rx_data : NATURAL; -- received (rx) 32bit word + VARIABLE v_exp_data : NATURAL; -- expected (exp) 32bit word + BEGIN + IF rising_edge(dp_clk) THEN + rx_val <= '0'; + v_rx_data := TO_UINT(test_offload_sosi.data); + IF test_offload_sosi.valid = '1' THEN + IF g_statistics_type = "SST" THEN + -- Indices: + -- W: 0 1 2 3 4 5 ... 1022 1023 + -- U = D = S: 0 1 2 511 + -- I: 0 1 0 1 0 1 ... 0 1 + -- P: J: Words values: + -- 0 0 0 1 4 5 8 9 ... 2044 2045 + -- 1 1 2 3 6 7 10 11 ... 2046 2047 + -- 2 0 2048 2049 2052 2053 2056 2057 ... 4092 4093 + -- 3 1 2050 2051 2054 2055 2058 2059 ... 4094 4095 + -- ... ... + -- 11 1 10242 10243 10246 10247 10250 10251 ... 12286 12287 + -- + -- g_reverse_word_order = TRUE: swaps odd and even W columns, + -- because c_sdp_W_statistic_sz = 2 + + W := rx_valid_cnt; -- range c_packet_size = 1024 32bit Words + S := W / c_sdp_W_statistic_sz; -- range c_nof_statistics_per_packet = 512 Statistic values + D := S; -- range c_mm_nof_data = 512 Data values, because + -- c_mm_data_size / c_sdp_W_statistic_sz = 1 + U := S; -- range c_sdp_N_sub = 512 SST values + I := W MOD c_sdp_W_statistic_sz; -- range c_sdp_W_statistic_sz = 2 words + P := rx_packet_cnt; -- range c_nof_packets_max = 12 = c_sdp_S_pn Packets + J := P MOD c_nof_step; -- range c_nof_step = 2 = c_sdp_Q_fft + + v_exp_data := S * 4; -- due to c_mm_step_size = 4 = c_sdp_W_statistic_sz * c_sdp_Q_fft; + IF I = sel_a_b(g_reverse_word_order, 0, 1) THEN + v_exp_data := v_exp_data + 1; -- due to odd, even of c_sdp_W_statistic_sz = 2 + END IF; + IF J = 1 THEN + v_exp_data := v_exp_data + 2; -- due to c_sdp_W_statistic_sz = 2 and c_nof_step = 2 > 1 + END IF; + v_exp_data := v_exp_data + (P/2) * 2048; -- due to c_packet_size = 1024 and c_nof_step = 2 > 1 + ASSERT v_exp_data = v_rx_data REPORT "Wrong SST payload data Rx" SEVERITY ERROR; + + ELSIF g_statistics_type = "BST" THEN + -- Indices: + -- W: 0 1 2 3 4 5 ... 1948 1949 1950 1951 + -- S: 0 1 2 ... 974 975 + -- B = D: 0 1 ... 487 + -- I: 0 1 2 3 0 ... 0 1 2 3 + -- P: Words values: + -- 0 0 1 2 3 4 5 ... 1948 1949 1950 1951 + + -- g_reverse_word_order = TRUE: swaps every c_mm_data_size = 4 D columns. + -- g_reverse_word_order occurs per c_mm_data_size = 4 words, so the + -- c_sdp_N_pol_bf = 2 beam polarizations also get swapped. + + W := rx_valid_cnt; -- range c_packet_size = 1952 + S := W / c_sdp_W_statistic_sz; -- range c_nof_statistics_per_packet = 976 Statistic values + D := S / c_sdp_N_pol_bf; -- range c_mm_nof_data = 488 Data values, because + -- c_mm_data_size / c_sdp_W_statistic_sz = 2 = c_sdp_N_pol_bf + B := D; -- range c_sdp_S_sub_bf = 488 dual polarization BST values + I := W MOD c_mm_data_size; -- range c_mm_data_size = 4 = c_sdp_W_statistic_sz * c_sdp_N_pol_bf + P := rx_packet_cnt; -- range c_nof_packets_max = 1 + + v_exp_data := B * c_mm_data_size; + IF g_reverse_word_order = FALSE THEN + v_exp_data := v_exp_data + I; + ELSE + v_exp_data := v_exp_data - I + c_mm_data_size-1; + END IF; + 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 + -- . g_nof_crosslets = 3 + -- . c_sdp_N_crosslets_max = 7 --> 2**ceil_log2(7 * 576) = 4096 + -- + -- W: 0 1 2 3 4 5 ... 572 573 574 575 + -- S: 0 1 2 ... 286 287 + -- X = D: 0 1 ... 143 + -- I: 0 1 2 3 0 ... 0 1 2 3 + -- P: J: K: Word values: + -- 0 0 0 0 1 2 3 4 5 ... 572 573 574 575 + -- 1 1 576 ... + -- 2 2 1052 ... + -- + -- 3 0 1 4096 ... + -- 4 1 4672 ... + -- 5 2 5244 ... + -- ... + -- 9 0 3 12288 ... + -- 10 1 12864 ... + -- 11 2 13436 ... + + -- g_reverse_word_order = TRUE: swaps every c_mm_data_size = 4 D columns. + -- g_reverse_word_order occurs per c_mm_data_size = 4 words, so the + -- c_nof_complex = 2 parts also get swapped. + + W := rx_valid_cnt; -- range c_packet_size = 576 + S := W / c_sdp_W_statistic_sz; -- range c_nof_statistics_per_packet = 288 Statistic values + D := S / c_nof_complex; -- range c_mm_nof_data = 144 Data values, because + -- 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_data_size; -- range c_mm_data_size = 4 = c_sdp_W_statistic_sz * c_nof_complex + P := rx_packet_cnt; -- range c_mm_nof_packets + J := P MOD g_nof_crosslets; -- range g_nof_crosslets + K := P / g_nof_crosslets; -- range g_P_sq + + v_exp_data := X * c_mm_data_size; + IF g_reverse_word_order = FALSE THEN + v_exp_data := v_exp_data + I; + ELSE + v_exp_data := v_exp_data - I + c_mm_data_size-1; + END IF; + v_exp_data := v_exp_data + J * 576; + v_exp_data := v_exp_data + K * 4096; + ASSERT v_exp_data = v_rx_data REPORT "Wrong XST payload data Rx" SEVERITY ERROR; + + END IF; + -- for debug in wave window + rx_val <= '1'; + rx_data <= v_rx_data; + exp_data <= v_exp_data; END IF; END IF; END PROCESS; @@ -535,6 +666,7 @@ BEGIN GENERIC MAP ( g_statistics_type => g_statistics_type, g_offload_time => g_offload_time, + g_reverse_word_order => g_reverse_word_order, g_beamset_id => g_beamset_id, g_P_sq => g_P_sq, g_crosslets_direction => g_crosslets_direction @@ -570,7 +702,7 @@ BEGIN sdp_info => sdp_info, subband_calibrated_flag => subband_calibrated_flag, - nof_crosslets => nof_crosslets, + nof_crosslets => c_mm_nof_crosslets, crosslets_info => in_crosslets_info_slv );