diff --git a/applications/lofar2/designs/lofar2_unb2c_sdp_station/revisions/lofar2_unb2c_sdp_station_bf/tb_lofar2_unb2c_sdp_station_bf.vhd b/applications/lofar2/designs/lofar2_unb2c_sdp_station/revisions/lofar2_unb2c_sdp_station_bf/tb_lofar2_unb2c_sdp_station_bf.vhd index c249bdfbf36cd3bfb72c435d906390f3187bf112..da901213a23fee1782471b330fee9210c8d33a0d 100644 --- a/applications/lofar2/designs/lofar2_unb2c_sdp_station/revisions/lofar2_unb2c_sdp_station_bf/tb_lofar2_unb2c_sdp_station_bf.vhd +++ b/applications/lofar2/designs/lofar2_unb2c_sdp_station/revisions/lofar2_unb2c_sdp_station_bf/tb_lofar2_unb2c_sdp_station_bf.vhd @@ -195,7 +195,7 @@ ARCHITECTURE tb OF tb_lofar2_unb2c_sdp_station_bf IS CONSTANT c_stat_lo_factor : REAL := 1.0 - c_stat_percentage; -- lower boundary CONSTANT c_stat_hi_factor : REAL := 1.0 + c_stat_percentage; -- higher boundary - CONSTANT c_nof_beamlets_per_data : NATURAL := 2; -- 2 dual pol beamlets (= XY, XY) per 64b data word + CONSTANT c_nof_beamlets_per_data : NATURAL := c_sdp_cep_nof_beamlets_per_longword; -- = 2 dual pol beamlets per 64b data word CONSTANT c_beamlet_output_delta : INTEGER := 2; -- +-delta margin diff --git a/applications/lofar2/designs/lofar2_unb2c_sdp_station/revisions/lofar2_unb2c_sdp_station_bf/tb_lofar2_unb2c_sdp_station_bf_bst_offload.vhd b/applications/lofar2/designs/lofar2_unb2c_sdp_station/revisions/lofar2_unb2c_sdp_station_bf/tb_lofar2_unb2c_sdp_station_bf_bst_offload.vhd index dd52d4eb206cf007076a9b100f4e9e00400e8d28..270ce27dea1c2cf60728dd488e7e075267b6d1be 100644 --- a/applications/lofar2/designs/lofar2_unb2c_sdp_station/revisions/lofar2_unb2c_sdp_station_bf/tb_lofar2_unb2c_sdp_station_bf_bst_offload.vhd +++ b/applications/lofar2/designs/lofar2_unb2c_sdp_station/revisions/lofar2_unb2c_sdp_station_bf/tb_lofar2_unb2c_sdp_station_bf_bst_offload.vhd @@ -249,8 +249,8 @@ BEGIN g_nof_streams => 1, g_data_w => c_word_w, g_hdr_field_arr => c_sdp_stat_hdr_field_arr, - g_remove_crc => FALSE, - g_crc_nof_words => 0 + g_remove_crc => TRUE, + g_crc_nof_words => 1 ) PORT MAP ( mm_rst => pps_rst, diff --git a/applications/lofar2/designs/lofar2_unb2c_sdp_station/revisions/lofar2_unb2c_sdp_station_fsub/tb_lofar2_unb2c_sdp_station_fsub_sst_offload.vhd b/applications/lofar2/designs/lofar2_unb2c_sdp_station/revisions/lofar2_unb2c_sdp_station_fsub/tb_lofar2_unb2c_sdp_station_fsub_sst_offload.vhd index 5b14cb9aea233df7b59df0ff7031032d571d7f40..74694c689dfd0849fffcea7de86c61886b268e8e 100644 --- a/applications/lofar2/designs/lofar2_unb2c_sdp_station/revisions/lofar2_unb2c_sdp_station_fsub/tb_lofar2_unb2c_sdp_station_fsub_sst_offload.vhd +++ b/applications/lofar2/designs/lofar2_unb2c_sdp_station/revisions/lofar2_unb2c_sdp_station_fsub/tb_lofar2_unb2c_sdp_station_fsub_sst_offload.vhd @@ -248,8 +248,8 @@ BEGIN g_nof_streams => 1, g_data_w => c_word_w, g_hdr_field_arr => c_sdp_stat_hdr_field_arr, - g_remove_crc => FALSE, - g_crc_nof_words => 0 + g_remove_crc => TRUE, + g_crc_nof_words => 1 ) PORT MAP ( mm_rst => pps_rst, diff --git a/applications/lofar2/designs/lofar2_unb2c_sdp_station/revisions/lofar2_unb2c_sdp_station_xsub_one/tb_lofar2_unb2c_sdp_station_xsub_one_xst_offload.vhd b/applications/lofar2/designs/lofar2_unb2c_sdp_station/revisions/lofar2_unb2c_sdp_station_xsub_one/tb_lofar2_unb2c_sdp_station_xsub_one_xst_offload.vhd index a11dac56788bf43d7cbb73d8bfba830f7a65832e..55315adbd57b1bb9dc6bce4e43b2f260c5f35b49 100644 --- a/applications/lofar2/designs/lofar2_unb2c_sdp_station/revisions/lofar2_unb2c_sdp_station_xsub_one/tb_lofar2_unb2c_sdp_station_xsub_one_xst_offload.vhd +++ b/applications/lofar2/designs/lofar2_unb2c_sdp_station/revisions/lofar2_unb2c_sdp_station_xsub_one/tb_lofar2_unb2c_sdp_station_xsub_one_xst_offload.vhd @@ -34,8 +34,21 @@ -- Usage: -- > as 7 # default -- > as 12 # for detailed debugging +-- And add more missing sosi_arr signals or constants via sim tab, entity instance in hierarchy and +-- then select from objects window, e.g. for: +-- > add wave -position insertpoint \ +-- sim:/tb_lofar2_unb2c_sdp_station_xsub_one_xst_offload/u_lofar_unb2c_sdp_station_xsub_one/u_sdp_station/ait_sosi_arr \ +-- sim:/tb_lofar2_unb2c_sdp_station_xsub_one_xst_offload/u_lofar_unb2c_sdp_station_xsub_one/u_sdp_station/pfb_sosi_arr \ +-- sim:/tb_lofar2_unb2c_sdp_station_xsub_one_xst_offload/u_lofar_unb2c_sdp_station_xsub_one/u_sdp_station/fsub_sosi_arr \ +-- sim:/tb_lofar2_unb2c_sdp_station_xsub_one_xst_offload/u_lofar_unb2c_sdp_station_xsub_one/u_sdp_station/bs_sosi +-- > add wave -position insertpoint \ +-- sim:/tb_lofar2_unb2c_sdp_station_xsub_one_xst_offload/c_exp_subband_xst -- > run -a --- Takes about 10 m +-- Takes about 50 m +-- View e.g.: +-- * rx_sdp_stat_re/im in radix decimal and in format literal or analogue +-- * rx_sdp_stat_header.app +-- * new_interval in node_sdp_correlator.vhd -- ------------------------------------------------------------------------------- LIBRARY IEEE, common_lib, unb2c_board_lib, i2c_lib, mm_lib, dp_lib, diag_lib, lofar2_sdp_lib, wpfb_lib, lofar2_unb2c_sdp_station_lib, eth_lib; @@ -76,13 +89,29 @@ ARCHITECTURE tb OF tb_lofar2_unb2c_sdp_station_xsub_one_xst_offload IS CONSTANT c_pps_period : NATURAL := c_nof_clk_per_sync; CONSTANT c_wpfb_sim : t_wpfb := func_wpfb_set_nof_block_per_sync(c_sdp_wpfb_subbands, c_nof_block_per_sync); CONSTANT c_ctrl_interval_size : NATURAL := c_nof_clk_per_sync; + CONSTANT c_nof_crosslets : NATURAL := 3; -- not too large, so that offload still fits in c_nof_block_per_sync CONSTANT c_subband_select_arr : t_natural_arr(0 TO c_sdp_N_crosslets_max-1) := (10, 11, 12, 13, 14, 15, 16); - CONSTANT c_subband_step : NATURAL := 0; - CONSTANT c_nof_crosslets : NATURAL := 3; - CONSTANT c_nof_sync : NATURAL := 2; + CONSTANT c_subband_step : NATURAL := 3; -- e.g. 0 or c_nof_crosslets + CONSTANT c_nof_sync : NATURAL := 3; - -- MM + CONSTANT c_max_ratio : REAL := 0.001; -- ratio that actual value may differ from expected value + + -- WG + CONSTANT c_bsn_start_wg : NATURAL := 2; + CONSTANT c_sp_ampl : REAL := 0.5; -- WG normalized amplitude, 1.0 = FS (full scale), use <= 0.5 to avoid XST overflow + CONSTANT c_wg_ampl : NATURAL := NATURAL(c_sp_ampl * REAL(c_sdp_FS_adc)); -- in number of lsb + CONSTANT c_wg_subband : NATURAL := 12; + + -- WPFB + CONSTANT c_exp_subband_ampl : REAL := REAL(c_wg_ampl) * c_sdp_wpfb_subband_sp_ampl_ratio; -- = c_wg_ampl * 0.994817 * 8 + CONSTANT c_exp_subband_power : REAL := c_exp_subband_ampl**2.0; -- complex, so no divide by 2 + CONSTANT c_exp_subband_sst : REAL := c_exp_subband_power * REAL(c_nof_block_per_sync); + CONSTANT c_exp_subband_xst : REAL := c_exp_subband_sst; -- all signal inputs use same WG, and auto correlation XST = SST + + -- MM CONSTANT c_mm_file_reg_bsn_source_v2 : STRING := mmf_unb_file_prefix(c_unb_nr, c_node_nr) & "REG_BSN_SOURCE_V2"; + CONSTANT c_mm_file_reg_bsn_scheduler_wg : STRING := mmf_unb_file_prefix(c_unb_nr, c_node_nr) & "REG_BSN_SCHEDULER"; + CONSTANT c_mm_file_reg_diag_wg : STRING := mmf_unb_file_prefix(c_unb_nr, c_node_nr) & "REG_WG"; CONSTANT c_mm_file_reg_crosslets_info : STRING := mmf_unb_file_prefix(c_unb_nr, c_node_nr) & "REG_CROSSLETS_INFO"; CONSTANT c_mm_file_reg_nof_crosslets : STRING := mmf_unb_file_prefix(c_unb_nr, c_node_nr) & "REG_NOF_CROSSLETS"; CONSTANT c_mm_file_reg_bsn_sync_scheduler_xsub : STRING := mmf_unb_file_prefix(c_unb_nr, c_node_nr) & "REG_BSN_SYNC_SCHEDULER_XSUB"; @@ -113,22 +142,38 @@ ARCHITECTURE tb OF tb_lofar2_unb2c_sdp_station_xsub_one_xst_offload IS SIGNAL INTA : STD_LOGIC; SIGNAL INTB : STD_LOGIC; - SIGNAL eth_clk : STD_LOGIC_VECTOR(c_unb2c_board_nof_eth-1 downto 0) := (OTHERS => '0'); - SIGNAL eth_txp : STD_LOGIC_VECTOR(c_unb2c_board_nof_eth-1 downto 0) := (OTHERS => '0'); - SIGNAL eth_rxp : STD_LOGIC_VECTOR(c_unb2c_board_nof_eth-1 downto 0) := (OTHERS => '0'); + SIGNAL eth_clk : STD_LOGIC_VECTOR(c_unb2c_board_nof_eth-1 DOWNTO 0) := (OTHERS => '0'); + SIGNAL eth_txp : STD_LOGIC_VECTOR(c_unb2c_board_nof_eth-1 DOWNTO 0) := (OTHERS => '0'); + SIGNAL eth_rxp : STD_LOGIC_VECTOR(c_unb2c_board_nof_eth-1 DOWNTO 0) := (OTHERS => '0'); + + -- WG + SIGNAL current_bsn_wg : STD_LOGIC_VECTOR(c_dp_stream_bsn_w-1 DOWNTO 0); -- Rx packets SIGNAL eth_rx_sosi : t_dp_sosi; - SIGNAL eth_rx_data : STD_LOGIC_VECTOR(c_32-1 downto 0); + SIGNAL eth_rx_data : STD_LOGIC_VECTOR(c_32-1 DOWNTO 0); -- Decode packets SIGNAL rx_offload_sosi : t_dp_sosi; + + -- . view payload statistics data + SIGNAL rx_word_cnt : NATURAL := 0; + SIGNAL rx_sdp_stat_data : STD_LOGIC_VECTOR(c_32-1 DOWNTO 0); + SIGNAL rx_sdp_stat_re : STD_LOGIC_VECTOR(c_64-1 DOWNTO 0); + SIGNAL rx_sdp_stat_im : STD_LOGIC_VECTOR(c_64-1 DOWNTO 0); + SIGNAL rx_sdp_stat_re_val : STD_LOGIC := '0'; + SIGNAL rx_sdp_stat_im_val : STD_LOGIC := '0'; + SIGNAL rx_sdp_stat_index : NATURAL := 0; + SIGNAL rx_a_sp : NATURAL := 0; + SIGNAL rx_b_sp : NATURAL := 0; + + -- . view header SIGNAL rx_hdr_fields_out : STD_LOGIC_VECTOR(1023 DOWNTO 0); SIGNAL rx_hdr_fields_raw : STD_LOGIC_VECTOR(1023 DOWNTO 0) := (OTHERS => '0'); SIGNAL rx_sdp_stat_header : t_sdp_stat_header; -- back transceivers - SIGNAL JESD204B_SERIAL_DATA : STD_LOGIC_VECTOR(c_sdp_S_pn-1 downto 0); + SIGNAL JESD204B_SERIAL_DATA : STD_LOGIC_VECTOR(c_sdp_S_pn-1 DOWNTO 0); SIGNAL JESD204B_REFCLK : STD_LOGIC := '1'; -- jesd204b syncronization signals @@ -203,6 +248,7 @@ BEGIN tb_clk <= NOT tb_clk AFTER c_tb_clk_period/2; -- Testbench MM clock p_mm_stimuli : PROCESS + VARIABLE v_bsn : NATURAL; BEGIN -- Wait for DUT power up after reset WAIT FOR 1 us; @@ -219,6 +265,32 @@ BEGIN WAIT FOR 1 us; pps_rst <= '0'; + ---------------------------------------------------------------------------- + -- Enable and start WG + ---------------------------------------------------------------------------- + -- 0 : mode[7:0] --> off=0, calc=1, repeat=2, single=3) + -- nof_samples[31:16] --> <= c_ram_wg_size=1024 + -- 1 : phase[15:0] + -- 2 : freq[30:0] + -- 3 : ampl[16:0] + FOR I IN 0 TO c_sdp_S_pn-1 LOOP + mmf_mm_bus_wr(c_mm_file_reg_diag_wg, I*4 + 0, 1024*2**16 + 1, tb_clk); -- nof_samples, mode calc + mmf_mm_bus_wr(c_mm_file_reg_diag_wg, I*4 + 1, INTEGER(0.0 * c_diag_wg_phase_unit), tb_clk); -- phase offset in degrees + mmf_mm_bus_wr(c_mm_file_reg_diag_wg, I*4 + 2, INTEGER(REAL(c_wg_subband) * c_sdp_wg_subband_freq_unit), tb_clk); -- freq + mmf_mm_bus_wr(c_mm_file_reg_diag_wg, I*4 + 3, INTEGER(REAL(c_wg_ampl) * c_sdp_wg_ampl_lsb), tb_clk); -- ampl + END LOOP; + + -- Read current BSN + mmf_mm_bus_rd(c_mm_file_reg_bsn_scheduler_wg, 0, current_bsn_wg(31 DOWNTO 0), tb_clk); + mmf_mm_bus_rd(c_mm_file_reg_bsn_scheduler_wg, 1, current_bsn_wg(63 DOWNTO 32), tb_clk); + proc_common_wait_some_cycles(tb_clk, 1); + + -- Write scheduler BSN to trigger start of WG at next block + v_bsn := TO_UINT(current_bsn_wg) + 2; + ASSERT v_bsn <= c_bsn_start_wg REPORT "Too late to start WG: " & int_to_str(v_bsn) & " > " & int_to_str(c_bsn_start_wg) SEVERITY ERROR; + mmf_mm_bus_wr(c_mm_file_reg_bsn_scheduler_wg, 0, c_bsn_start_wg, tb_clk); -- first write low then high part + mmf_mm_bus_wr(c_mm_file_reg_bsn_scheduler_wg, 1, 0, tb_clk); -- assume v_bsn < 2**31-1 + ---------------------------------------------------------------------------- -- Setup and enable xsub ---------------------------------------------------------------------------- @@ -274,14 +346,14 @@ BEGIN eth_rx_data <= eth_rx_sosi.data(c_32-1 DOWNTO 0); - -- . Verify XST packet header + -- . View / verify XST packet header u_rx_statistics : ENTITY dp_lib.dp_offload_rx GENERIC MAP ( g_nof_streams => 1, g_data_w => c_word_w, g_hdr_field_arr => c_sdp_stat_hdr_field_arr, - g_remove_crc => FALSE, - g_crc_nof_words => 0 + g_remove_crc => TRUE, + g_crc_nof_words => 1 ) PORT MAP ( mm_rst => pps_rst, @@ -300,4 +372,74 @@ BEGIN rx_sdp_stat_header <= func_sdp_map_stat_header(rx_hdr_fields_raw); + -- . View / verify XST packet payload + p_rx_sdp_view_stat_data : PROCESS(eth_clk(0)) + BEGIN + IF rising_edge(eth_clk(0)) THEN + rx_sdp_stat_re_val <= '0'; + rx_sdp_stat_im_val <= '0'; + IF rx_offload_sosi.valid = '1' THEN + -- Count words 0, 1, 2, 3 + rx_word_cnt <= 0; + IF rx_word_cnt < c_sdp_N_pol * c_nof_complex - 1 THEN + rx_word_cnt <= rx_word_cnt + 1; + END IF; + + -- Count words for the complex statistics with two 32bits words per 64 bit statistic, + -- high word part and real data received first. + CASE rx_word_cnt IS + WHEN 0 => rx_sdp_stat_data <= rx_offload_sosi.data(c_32-1 DOWNTO 0); + WHEN 1 => rx_sdp_stat_re <= rx_sdp_stat_data & rx_offload_sosi.data(c_32-1 DOWNTO 0); + rx_sdp_stat_re_val <= '1'; + WHEN 2 => rx_sdp_stat_data <= rx_offload_sosi.data(c_32-1 DOWNTO 0); + WHEN 3 => rx_sdp_stat_im <= rx_sdp_stat_data & rx_offload_sosi.data(c_32-1 DOWNTO 0); + rx_sdp_stat_im_val <= '1'; + WHEN OTHERS => NULL; + END CASE; + END IF; + + -- Count the complex statistics + IF rx_sdp_stat_im_val = '1' THEN + rx_sdp_stat_index <= rx_sdp_stat_index + 1; + END IF; + + IF rx_offload_sosi.sop = '1' THEN + rx_sdp_stat_index <= 0; -- restart per Rx packet + END IF; + END IF; + END PROCESS; + + p_rx_sdp_verify_stat_data : PROCESS(eth_clk(0)) + VARIABLE v_subband_ix : NATURAL; -- _ix = index + BEGIN + IF rising_edge(eth_clk(0)) THEN + v_subband_ix := TO_UINT(rx_sdp_stat_header.app.sdp_data_id_xst_subband_index); + -- real part + IF rx_sdp_stat_re_val = '1' THEN + IF v_subband_ix = c_wg_subband THEN + -- Expect the strong XST value at the WG subband + ASSERT almost_equal(TO_SREAL(rx_sdp_stat_re) / c_exp_subband_xst, 1.0, c_max_ratio) REPORT "Wrong XST real value at subband = " & int_to_str(v_subband_ix) SEVERITY ERROR; + ELSE + -- WG is only in one subband, so expect almost zero in the other subbands + ASSERT almost_zero(TO_SREAL(rx_sdp_stat_re) / c_exp_subband_xst, c_max_ratio) REPORT "Too large XST real value at subband = " & int_to_str(v_subband_ix) SEVERITY ERROR; + END IF; + END IF; + IF rx_sdp_stat_im_val = '1' THEN + -- All WG have same phase, so expect zero imaginary part. + -- . The imag part is exactly zero for signal inputs a and b that are both connected to the corresponding input of the WPFB. + -- . The imag part is almost zero for signal inputs a and b that are both connected to the opposite inputs of the WPFB, due + -- to crosstalk rounding difference from input a to b or from input b to a of the complex FFT. + IF (rx_a_sp MOD c_sdp_Q_fft) = (rx_b_sp MOD c_sdp_Q_fft) THEN + ASSERT SIGNED(rx_sdp_stat_im) = 0 REPORT "Non zero XST imaginary value at subband = " & int_to_str(v_subband_ix) SEVERITY ERROR; + ELSE + ASSERT almost_zero(TO_SREAL(rx_sdp_stat_im) / c_exp_subband_xst, c_max_ratio) REPORT "Too large XST imaginary value at subband = " & int_to_str(v_subband_ix) SEVERITY ERROR; + END IF; + END IF; + END IF; + END PROCESS; + + -- rx_sdp_stat_index counts the S_pn * S_pn = X_sq = 12 * 12 = 144 complex statistics + rx_a_sp <= rx_sdp_stat_index / c_sdp_S_pn; -- signal input A + rx_b_sp <= rx_sdp_stat_index MOD c_sdp_S_pn; -- signal input B + END tb; diff --git a/applications/lofar2/images/images.txt b/applications/lofar2/images/images.txt index 341a2e0d00c96fd10ee5e2f0f7915fe90bef5451..bad1d5352fff4084b933d82b756a78af8def09bf 100644 --- a/applications/lofar2/images/images.txt +++ b/applications/lofar2/images/images.txt @@ -11,7 +11,7 @@ lofar2_unb2b_sdp_station_xsub_one-r087d98be6 | 2021-06-14 | R vd Walle unb2b_minimal-rce6b96eed | 2021-08-26 | P. Donker | unb2b_minimal with new mmap, rbf maid with option --unb2_factory lofar2_unb2b_sdp_station_full-r9ff51058a | 2022-01-12 | R vd Walle | Old Lofar2 SDP station full design for UniBoard2b without ring. lofar2_unb2b_sdp_station_full-r2c3958e1f | 2022-04-29 | R vd Walle | Lofar2 SDP station full design for UniBoard2b. -lofar2_unb2b_sdp_station_full_wg-r70b28ffc3 | 2022-06-15 | R vd Walle | Lofar2 SDP station design without ADC inputs, only WG. Uses dp_clk + dp_pps instead of rx_clk + rx_sysref. -lofar2_unb2b_sdp_station_full_wg-rf8e898438 | 2022-07-11 | R vd Walle | Lofar2 SDP station design without ADC inputs, only WG. Uses dp_clk + dp_pps instead of rx_clk + rx_sysref. -lofar2_unb2c_sdp_station_full-r70484fd08 | 2022-04-29 | R vd Walle | Lofar2 SDP station full design for UniBoard2c. -lofar2_unb2c_sdp_station_full-rf8e898438 | 2022-07-11 | R vd Walle | Lofar2 SDP station full design for UniBoard2c. +lofar2_unb2b_sdp_station_full_wg-r70b28ffc3 | 2022-06-15 | R vd Walle | Do not use, has beamlet/subband weight bug, delete when r01205cbe4 is OK. +lofar2_unb2b_sdp_station_full_wg-r01205cbe4 | 2022-07-14 | R vd Walle | Lofar2 SDP station design without ADC inputs, only WG. Uses dp_clk + dp_pps instead of rx_clk + rx_sysref. +lofar2_unb2c_sdp_station_full-r70484fd08 | 2022-04-29 | R vd Walle | Do not use, has beamlet/subband weight bug, delete when r01205cbe4 is OK. +lofar2_unb2c_sdp_station_full-r01205cbe4 | 2022-07-14 | R vd Walle | Lofar2 SDP station full design for UniBoard2c. diff --git a/applications/lofar2/images/lofar2_unb2b_sdp_station_full_wg-rf8e898438.tar.gz b/applications/lofar2/images/lofar2_unb2b_sdp_station_full_wg-r01205cbe4.tar.gz similarity index 66% rename from applications/lofar2/images/lofar2_unb2b_sdp_station_full_wg-rf8e898438.tar.gz rename to applications/lofar2/images/lofar2_unb2b_sdp_station_full_wg-r01205cbe4.tar.gz index 9920dd7f307b96622cc35684b1d348a2f36be47d..186b0cf9ea654534ab82ddd1ffd7c9e28e0ad5b4 100644 Binary files a/applications/lofar2/images/lofar2_unb2b_sdp_station_full_wg-rf8e898438.tar.gz and b/applications/lofar2/images/lofar2_unb2b_sdp_station_full_wg-r01205cbe4.tar.gz differ diff --git a/applications/lofar2/images/lofar2_unb2c_sdp_station_full-rf8e898438.tar.gz b/applications/lofar2/images/lofar2_unb2c_sdp_station_full-r01205cbe4.tar.gz similarity index 67% rename from applications/lofar2/images/lofar2_unb2c_sdp_station_full-rf8e898438.tar.gz rename to applications/lofar2/images/lofar2_unb2c_sdp_station_full-r01205cbe4.tar.gz index 308eb264cbb7a46b94a3ba6db271e4b0e222d27a..5fcf627d167aeb69ff14debbc11ae0d4e394a6ea 100644 Binary files a/applications/lofar2/images/lofar2_unb2c_sdp_station_full-rf8e898438.tar.gz and b/applications/lofar2/images/lofar2_unb2c_sdp_station_full-r01205cbe4.tar.gz differ diff --git a/applications/lofar2/libraries/sdp/src/vhdl/node_sdp_beamformer.vhd b/applications/lofar2/libraries/sdp/src/vhdl/node_sdp_beamformer.vhd index 3053b5f21d4b25e3851a0c57cd02ddec09accbac..b1972f74aa3ad94953a3dcdb1587725903982b5c 100644 --- a/applications/lofar2/libraries/sdp/src/vhdl/node_sdp_beamformer.vhd +++ b/applications/lofar2/libraries/sdp/src/vhdl/node_sdp_beamformer.vhd @@ -310,7 +310,8 @@ BEGIN g_nof_stat => c_sdp_S_sub_bf*c_sdp_N_pol_bf, g_in_data_w => c_sdp_W_beamlet_sum, g_stat_data_w => c_longword_w, - g_stat_data_sz => c_longword_sz/c_word_sz + g_stat_data_sz => c_longword_sz/c_word_sz, + g_stat_multiplex=> c_sdp_N_pol_bf ) PORT MAP ( mm_rst => mm_rst, diff --git a/applications/lofar2/libraries/sdp/src/vhdl/node_sdp_correlator.vhd b/applications/lofar2/libraries/sdp/src/vhdl/node_sdp_correlator.vhd index 43c17b7a7734a746960722a9ccb37fe0a608027f..d7467674f8b7a78d568da9ea681077fe0a62cde1 100644 --- a/applications/lofar2/libraries/sdp/src/vhdl/node_sdp_correlator.vhd +++ b/applications/lofar2/libraries/sdp/src/vhdl/node_sdp_correlator.vhd @@ -22,11 +22,13 @@ -- -- Author: R. van der Walle -- Purpose: --- . Implements the functionality of the Subband Correlator in the +-- . Implements the functionality of the Subband Correlator (F_sub) in the -- LOFAR2 SDPFW design. -- Description: -- Remark: --- . +-- . Use new_interval to avoid offloading undefined XST data for the first +-- sync interval after an F_sub restart, because then there is no previous +-- sync interval with valid XST data yet. ------------------------------------------------------------------------------- LIBRARY IEEE, common_lib, dp_lib, reorder_lib, st_lib, mm_lib, ring_lib; @@ -118,6 +120,8 @@ ARCHITECTURE str OF node_sdp_correlator IS SIGNAL xsel_data_sosi : t_dp_sosi := c_dp_sosi_rst; SIGNAL local_sosi : t_dp_sosi := c_dp_sosi_rst; + SIGNAL new_interval : STD_LOGIC; + SIGNAL ring_mux_sosi : t_dp_sosi := c_dp_sosi_rst; SIGNAL ring_mux_siso : t_dp_siso := c_dp_siso_rdy; SIGNAL dp_fifo_fill_sosi : t_dp_sosi := c_dp_sosi_rst; @@ -131,7 +135,7 @@ ARCHITECTURE str OF node_sdp_correlator IS SIGNAL crosslets_cipo_arr : t_mem_cipo_arr(g_P_sq-1 DOWNTO 0) := (OTHERS => c_mem_cipo_rst); SIGNAL mon_xst_udp_sosi_arr : t_dp_sosi_arr(0 DOWNTO 0) := (OTHERS => c_dp_sosi_rst); - SIGNAL crosslets_info : STD_LOGIC_VECTOR(c_sdp_crosslets_info_reg_w-1 DOWNTO 0); + SIGNAL prev_crosslets_info_rec : t_sdp_crosslets_info; SIGNAL nof_crosslets_reg : STD_LOGIC_VECTOR(c_sdp_nof_crosslets_reg_w-1 DOWNTO 0); SIGNAL nof_crosslets : STD_LOGIC_VECTOR(c_sdp_nof_crosslets_reg_w-1 DOWNTO 0); BEGIN @@ -175,6 +179,8 @@ BEGIN in_sosi_arr => quant_sosi_arr, out_sosi => xsel_sosi, + new_interval => new_interval, + mm_rst => mm_rst, mm_clk => mm_clk, @@ -184,7 +190,8 @@ BEGIN reg_bsn_sync_scheduler_xsub_mosi => reg_bsn_sync_scheduler_xsub_copi, reg_bsn_sync_scheduler_xsub_miso => reg_bsn_sync_scheduler_xsub_cipo, - out_crosslets_info => crosslets_info + cur_crosslets_info_rec => OPEN, + prev_crosslets_info_rec => prev_crosslets_info_rec ); -- Use xsel_sosi as local bsn and sync reference since the sync @@ -425,6 +432,7 @@ BEGIN in_reg => nof_crosslets, out_reg => nof_crosslets_reg ); + -- Force nof crosslets to max nof crosslets if a higher value is written or to 1 if a lower value is written via MM. nof_crosslets <= TO_UVEC(1, c_sdp_nof_crosslets_reg_w) WHEN TO_UINT(nof_crosslets_reg) < 1 ELSE nof_crosslets_reg WHEN TO_UINT(nof_crosslets_reg) <= c_sdp_N_crosslets_max ELSE @@ -434,6 +442,7 @@ BEGIN -- XST UDP offload --------------------------------------------------------------- xst_udp_sosi <= mon_xst_udp_sosi_arr(0); + u_sdp_xst_udp_offload: ENTITY work.sdp_statistics_offload GENERIC MAP ( g_statistics_type => "XST", @@ -461,7 +470,9 @@ BEGIN reg_bsn_monitor_v2_offload_copi => reg_bsn_monitor_v2_xst_offload_copi, reg_bsn_monitor_v2_offload_cipo => reg_bsn_monitor_v2_xst_offload_cipo, - in_sosi => crosslets_sosi, + in_sosi => crosslets_sosi, + new_interval => new_interval, + out_sosi => mon_xst_udp_sosi_arr(0), out_siso => xst_udp_siso, @@ -472,9 +483,10 @@ BEGIN gn_index => TO_UINT(gn_id), ring_info => ring_info, sdp_info => sdp_info, - weighted_subbands_flag => '1', -- because XSub uses in_sosi_arr = fsub_sosi_arr, so weighted subbands - nof_crosslets => nof_crosslets, - crosslets_info => crosslets_info + weighted_subbands_flag => '1', -- because XSub uses in_sosi_arr = fsub_sosi_arr, so weighted subbands + + nof_crosslets => nof_crosslets, + crosslets_info_rec => prev_crosslets_info_rec ); END str; diff --git a/applications/lofar2/libraries/sdp/src/vhdl/node_sdp_filterbank.vhd b/applications/lofar2/libraries/sdp/src/vhdl/node_sdp_filterbank.vhd index e7796662df1ae18012395c10cfcc5897f5c49abf..5c11d1481a6dbf3c7ea9edb10ebb7dbdb7031fa8 100644 --- a/applications/lofar2/libraries/sdp/src/vhdl/node_sdp_filterbank.vhd +++ b/applications/lofar2/libraries/sdp/src/vhdl/node_sdp_filterbank.vhd @@ -262,7 +262,8 @@ BEGIN g_nof_stat => c_sdp_N_sub*c_sdp_Q_fft, g_in_data_w => c_sdp_W_subband, g_stat_data_w => g_wpfb.stat_data_w, - g_stat_data_sz => g_wpfb.stat_data_sz + g_stat_data_sz => g_wpfb.stat_data_sz, + g_stat_multiplex=> c_sdp_Q_fft ) PORT MAP ( mm_rst => mm_rst, diff --git a/applications/lofar2/libraries/sdp/src/vhdl/sdp_beamformer_output.vhd b/applications/lofar2/libraries/sdp/src/vhdl/sdp_beamformer_output.vhd index 2a7d53aedc234b28cc2e2a929add7cd0bfbf6a5c..b7638e6df68a210231533e47e986a953a95eba7d 100644 --- a/applications/lofar2/libraries/sdp/src/vhdl/sdp_beamformer_output.vhd +++ b/applications/lofar2/libraries/sdp/src/vhdl/sdp_beamformer_output.vhd @@ -78,9 +78,9 @@ ARCHITECTURE str OF sdp_beamformer_output IS CONSTANT c_data_w : NATURAL := c_nof_complex*c_sdp_W_beamlet; --16b CONSTANT c_beamlet_index : NATURAL := g_beamset_id * c_sdp_S_sub_bf; -- call beamset 'id' and beamlet 'index' - -- c_fifo_fill must be the exact size of a packet such that no packet gets stuck in the FIFO or the FIFO gets read out too soon. + -- c_fifo_fill must be the exact size of a payload such that no payload gets stuck in the FIFO or the FIFO gets read out too soon. -- For packets of variable length, dp_fifo_fill_eop must be used. In this case we can use the standard fill fifo. - CONSTANT c_fifo_fill : NATURAL := c_sdp_cep_nof_blocks_per_packet * c_sdp_cep_nof_beamlets_per_block / 2; -- Size of packet: 2 beamlets (dual pol) fit in 1 64bit longword + CONSTANT c_fifo_fill : NATURAL := c_sdp_cep_payload_nof_longwords; CONSTANT c_fifo_size : NATURAL := c_fifo_fill*2; -- Make fifo size large enough for adding header and muxing beamsets. SIGNAL snk_in_concat : t_dp_sosi; diff --git a/applications/lofar2/libraries/sdp/src/vhdl/sdp_bf_weights.vhd b/applications/lofar2/libraries/sdp/src/vhdl/sdp_bf_weights.vhd index 3dec6eb52968ae1f86598a42c32e9e7771852cf2..a32d05170126eac25662f7df361b93231825fd97 100644 --- a/applications/lofar2/libraries/sdp/src/vhdl/sdp_bf_weights.vhd +++ b/applications/lofar2/libraries/sdp/src/vhdl/sdp_bf_weights.vhd @@ -120,7 +120,10 @@ BEGIN g_gain_w => c_sdp_W_bf_weight, g_in_dat_w => c_sdp_W_subband, g_out_dat_w => c_gain_out_dat_w, - g_gains_file_name => g_gains_file_name + g_gains_file_name => g_gains_file_name, + -- extra input latency to ease timing. + g_pipeline_real_mult_input => 2, + g_pipeline_complex_mult_input => 2 ) PORT MAP ( -- System 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 2cc902a393ad0a179fe76657d4931681ca520549..2e9acfb004d6e586a1e032f21cabccc6994b5646 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 @@ -24,8 +24,18 @@ -- Purpose: -- Select subbands from incoming blocks -- Description: --- The Crosslet subband select selects N_crosslets from each incoming block. Per --- crosslet there are S_pn = 12 subbands, one from each signal input of the PN. +-- * The Crosslet subband select selects N_crosslets from each incoming block. +-- Per crosslet there are S_pn = 12 subbands, one from each signal input of +-- the PN. +-- * The cur_crosslets_info is valid at the out_sosi.sync and for the entire +-- sync interval. The cur_crosslets_info identifies the crosslets that are +-- being calculated during this out_sosi.sync interval. +-- The prev_crosslets_info identifies the crosslets that were calculated +-- during the previous out_sosi.sync interval, so the XST for those crosslets +-- are then pending to be offloaded. +-- * The new_interval is active before the first out_sosi.sync and inactive +-- before the next out_sosi.sync, so it can be used to know when a new +-- sequence of out_sosi.sync intervals starts. -- Remark: -- . See L5 SDPFW Design Document: Subband Correlator -- Link: https://support.astron.nl/confluence/pages/viewpage.action?spaceKey=L2M&title=L5+SDPFW+Design+Document%3A+Subband+Correlator @@ -45,14 +55,16 @@ ENTITY sdp_crosslets_subband_select IS g_ctrl_interval_size_min : NATURAL := c_sdp_xst_nof_clk_per_sync_min ); PORT ( - dp_clk : IN STD_LOGIC; - dp_rst : IN STD_LOGIC; + dp_clk : IN STD_LOGIC; + dp_rst : IN STD_LOGIC; - in_sosi_arr : IN t_dp_sosi_arr(c_sdp_P_pfb-1 DOWNTO 0); - out_sosi : OUT t_dp_sosi; + in_sosi_arr : IN t_dp_sosi_arr(c_sdp_P_pfb-1 DOWNTO 0); + out_sosi : OUT t_dp_sosi; - mm_rst : IN STD_LOGIC; - mm_clk : IN STD_LOGIC; + new_interval : OUT STD_LOGIC; + + mm_rst : IN STD_LOGIC; + mm_clk : IN STD_LOGIC; reg_crosslets_info_mosi : IN t_mem_mosi := c_mem_mosi_rst; reg_crosslets_info_miso : OUT t_mem_miso := c_mem_miso_rst; @@ -60,13 +72,13 @@ ENTITY sdp_crosslets_subband_select IS reg_bsn_sync_scheduler_xsub_mosi : IN t_mem_mosi := c_mem_mosi_rst; 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) + cur_crosslets_info_rec : OUT t_sdp_crosslets_info; + prev_crosslets_info_rec : OUT t_sdp_crosslets_info ); END sdp_crosslets_subband_select; ARCHITECTURE str OF sdp_crosslets_subband_select IS - CONSTANT c_crosslets_info_dly : NATURAL := 1; CONSTANT c_col_select_addr_w : NATURAL := ceil_log2(c_sdp_Q_fft * c_sdp_N_sub); CONSTANT c_row_select_slv_w : NATURAL := ceil_log2(c_sdp_P_pfb); @@ -91,7 +103,7 @@ ARCHITECTURE str OF sdp_crosslets_subband_select IS SIGNAL r : t_crosslets_control_reg; SIGNAL nxt_r : t_crosslets_control_reg; - SIGNAL start_trigger : STD_LOGIC := '0'; + SIGNAL start_trigger : STD_LOGIC := '0'; SIGNAL col_select_mosi : t_mem_mosi := c_mem_mosi_rst; SIGNAL col_select_miso : t_mem_miso := c_mem_miso_rst; @@ -104,13 +116,13 @@ 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'); + SIGNAL cur_crosslets_info : STD_LOGIC_VECTOR(c_sdp_crosslets_info_reg_w-1 DOWNTO 0) := (OTHERS => '0'); + SIGNAL prev_crosslets_info : STD_LOGIC_VECTOR(c_sdp_crosslets_info_reg_w-1 DOWNTO 0) := (OTHERS => '0'); -- Map crosslets_info slv to record for easier view in Wave window SIGNAL crosslets_info_rec : t_sdp_crosslets_info; SIGNAL crosslets_info_rec_inout : t_sdp_crosslets_info; SIGNAL active_crosslets_info_rec : t_sdp_crosslets_info; - SIGNAL out_crosslets_info_rec : t_sdp_crosslets_info; BEGIN @@ -135,7 +147,8 @@ BEGIN in_sosi_arr => in_sosi_arr, out_sosi_arr => dp_bsn_sync_scheduler_src_out_arr, - out_start => start_trigger + out_start => start_trigger, + out_start_interval => new_interval ); --------------------------------------------------------------- @@ -160,10 +173,10 @@ BEGIN out_reg => crosslets_info_reg ); - p_set_unused_crosslets : PROCESS(i_out_crosslets_info) + p_set_unused_crosslets : PROCESS(cur_crosslets_info) BEGIN -- 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) + crosslets_info_reg_in <= cur_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); @@ -319,7 +332,7 @@ BEGIN END GENERATE; -- pipeline for alignment with sync - u_common_pipeline : ENTITY common_lib.common_pipeline + u_common_pipeline_cur : ENTITY common_lib.common_pipeline GENERIC MAP( g_pipeline => c_crosslets_info_dly, g_in_dat_w => c_sdp_crosslets_info_reg_w, @@ -330,10 +343,22 @@ BEGIN clk => dp_clk, in_en => row_sosi.sync, in_dat => active_crosslets_info, - out_dat => i_out_crosslets_info + out_dat => cur_crosslets_info ); - out_crosslets_info <= i_out_crosslets_info; + u_common_pipeline_prev : ENTITY common_lib.common_pipeline + GENERIC MAP( + g_pipeline => c_crosslets_info_dly, + g_in_dat_w => c_sdp_crosslets_info_reg_w, + g_out_dat_w => c_sdp_crosslets_info_reg_w + ) + PORT MAP( + rst => dp_rst, + clk => dp_clk, + in_en => row_sosi.sync, + in_dat => cur_crosslets_info, + out_dat => prev_crosslets_info + ); --------------------------------------------------------------- -- Out sosi pipeline @@ -355,6 +380,8 @@ BEGIN crosslets_info_rec <= func_sdp_map_crosslets_info(crosslets_info_reg); crosslets_info_rec_inout <= func_sdp_map_crosslets_info(crosslets_info_reg_in); active_crosslets_info_rec <= func_sdp_map_crosslets_info(active_crosslets_info); - out_crosslets_info_rec <= func_sdp_map_crosslets_info(i_out_crosslets_info); + + cur_crosslets_info_rec <= func_sdp_map_crosslets_info(cur_crosslets_info); + prev_crosslets_info_rec <= func_sdp_map_crosslets_info(prev_crosslets_info); END str; diff --git a/applications/lofar2/libraries/sdp/src/vhdl/sdp_pkg.vhd b/applications/lofar2/libraries/sdp/src/vhdl/sdp_pkg.vhd index ff1b1565b89a30808872ffaf4392ce4ca297bac8..1f392030b12ec07086cbf4db03e3f304d44545a5 100644 --- a/applications/lofar2/libraries/sdp/src/vhdl/sdp_pkg.vhd +++ b/applications/lofar2/libraries/sdp/src/vhdl/sdp_pkg.vhd @@ -114,11 +114,13 @@ PACKAGE sdp_pkg is CONSTANT c_sdp_wg_subband_freq_unit : REAL := c_diag_wg_freq_unit/REAL(c_sdp_N_fft); -- subband freq = Fs/1024 = 200 MSps/1024 = 195312.5 Hz sinus CONSTANT c_sdp_N_clk_per_sync : NATURAL := c_sdp_f_adc_MHz*10**6; -- Default 200M clock cycles per second CONSTANT c_sdp_N_clk_sync_timeout : NATURAL := c_sdp_f_adc_MHz*10**6 + c_sdp_f_adc_MHz*10**5; -- 10% margin. - CONSTANT c_sdp_N_clk_sync_timeout_xsub : NATURAL := 2**31 - 1; -- 10.7 seconds = largest value for NATURAL. + CONSTANT c_sdp_N_clk_sync_timeout_xsub : NATURAL := 2147483647; -- = 2**31 - 1 = largest value for NATURAL for 10.7 seconds. Do not use 2*31 to avoid Modelsim NATURAL overflow warning. 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_f_sub_Hz : REAL := REAL(c_sdp_f_adc_MHz * 10**6) / REAL(c_sdp_N_fft); + CONSTANT c_sdp_f_sub_Hz : REAL := REAL(c_sdp_f_adc_MHz * 10**6) / REAL(c_sdp_N_fft); -- = 195312.5 CONSTANT c_sdp_N_int : NATURAL := c_sdp_f_adc_MHz * 10**6; -- nof ADC sample periods per 1 s integration interval CONSTANT c_sdp_N_int_sub : REAL := c_sdp_f_sub_Hz; -- nof subband sample periods per 1 s integration interval + CONSTANT c_sdp_N_int_sub_lo : NATURAL := NATURAL(FLOOR(c_sdp_N_int_sub)); -- = 195312 + CONSTANT c_sdp_N_int_sub_hi : NATURAL := NATURAL(CEIL(c_sdp_N_int_sub)); -- = 195313 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; -- = 5 ns @ 200MHz @@ -309,9 +311,10 @@ PACKAGE sdp_pkg is END RECORD; ----------------------------------------------------------------------------- - -- Beamlet output via 10GbE to CEP (= central processor) + -- Beamlet output via 10GbE to CEP (= central processor, see ICD STAT-CEP) ----------------------------------------------------------------------------- - CONSTANT c_sdp_marker_beamlets : NATURAL := 98; -- = x"62" = 'b' + CONSTANT c_sdp_cep_version_id : NATURAL := 5; + CONSTANT c_sdp_marker_beamlets : NATURAL := 98; -- = x"62" = 'b' CONSTANT c_sdp_cep_eth_dst_mac : STD_LOGIC_VECTOR(47 DOWNTO 0) := x"00074306C700"; -- 00074306C700 = DOP36-eth0 CONSTANT c_sdp_cep_eth_src_mac_47_16 : STD_LOGIC_VECTOR(31 DOWNTO 0) := x"00228608"; -- 47:16, 15:8 = backplane, 7:0 = node @@ -322,13 +325,16 @@ PACKAGE sdp_pkg is CONSTANT c_sdp_cep_udp_dst_port : STD_LOGIC_VECTOR(15 DOWNTO 0) := TO_UVEC(5000, 16); -- 0x1380 = 5000 CONSTANT c_sdp_cep_udp_src_port_15_8 : STD_LOGIC_VECTOR( 7 DOWNTO 0) := x"D0"; -- 15:8, 7:0 = gn_id (= ID[7:0] = backplane[5:0] & node[1:0]) - CONSTANT c_sdp_cep_app_header_len : NATURAL := 32; + CONSTANT c_sdp_cep_app_header_len : NATURAL := 32; -- octets, see ICD STAT-CEP + CONSTANT c_sdp_cep_header_len : NATURAL := 14 + 20 + 8 + c_sdp_cep_app_header_len; -- = eth + ip + udp + app = 74 octets, see ICD STAT-CEP - CONSTANT c_sdp_cep_version_id : NATURAL := 5; - CONSTANT c_sdp_cep_nof_blocks_per_packet : NATURAL := 4; - CONSTANT c_sdp_cep_nof_beamlets_per_block : NATURAL := c_sdp_S_sub_bf; -- number of dual pol beamlets (c_sdp_N_pol_bf = 2) + CONSTANT c_sdp_cep_nof_blocks_per_packet : NATURAL := 4; -- number of time blocks of beamlets per output packet + CONSTANT c_sdp_cep_nof_beamlets_per_block : NATURAL := c_sdp_S_sub_bf; -- number of dual pol beamlets (c_sdp_N_pol_bf = 2) + CONSTANT c_sdp_cep_nof_beamlets_per_longword : NATURAL := 2; -- 2 dual pol, complex, 8bit beamlets fit in 1 64bit longword + CONSTANT c_sdp_cep_payload_nof_longwords : NATURAL := c_sdp_cep_nof_blocks_per_packet * c_sdp_cep_nof_beamlets_per_block / c_sdp_cep_nof_beamlets_per_longword; -- = 976 + CONSTANT c_sdp_cep_packet_nof_longwords : NATURAL := ceil_div(c_sdp_cep_header_len, c_longword_sz) + c_sdp_cep_payload_nof_longwords; -- without tail CRC, the CRC is applied by 10GbE MAC - CONSTANT c_sdp_cep_nof_hdr_fields : NATURAL := 3+12+4+18+1; -- 592b; 9.25 64b words + CONSTANT c_sdp_cep_nof_hdr_fields : NATURAL := 3+12+4+18+1; -- c_sdp_cep_header_len / c_longword_sz = 74 / 8 = 9.25 64b words = 592b CONSTANT c_sdp_cep_hdr_field_sel : STD_LOGIC_VECTOR(c_sdp_cep_nof_hdr_fields-1 DOWNTO 0) := "101"&"111111111001"&"0111"&"1100"&"00000010"&"000110"&"0"; -- 0=data path, 1=MM controlled TODO --CONSTANT c_sdp_cep_hdr_field_sel : STD_LOGIC_VECTOR(c_sdp_cep_nof_hdr_fields-1 DOWNTO 0) := "100"&"000000010001"&"0100"&"0100"&"00000000"&"101000"&"0"; -- 0=data path, 1=MM controlled TODO @@ -494,6 +500,8 @@ PACKAGE sdp_pkg is step : NATURAL; END RECORD; + CONSTANT c_sdp_crosslets_info_rst : t_sdp_crosslets_info := (offset_arr => (OTHERS => 0), step => 0); + CONSTANT c_sdp_mm_reg_nof_crosslets : t_c_mem := (latency => 1, adr_w => 1, dat_w => ceil_log2(c_sdp_N_crosslets_max+1), diff --git a/applications/lofar2/libraries/sdp/src/vhdl/sdp_station.vhd b/applications/lofar2/libraries/sdp/src/vhdl/sdp_station.vhd index 7396bd3d3a6133dab982e8af25078f0f2114b1a7..7455fcaf62c5127110fd4ff974b0c1d6a6187b3d 100644 --- a/applications/lofar2/libraries/sdp/src/vhdl/sdp_station.vhd +++ b/applications/lofar2/libraries/sdp/src/vhdl/sdp_station.vhd @@ -26,7 +26,7 @@ -- Combines sdp nodes. Contains the UniBoard2 HW version independent LOFAR2 SDP application code. ------------------------------------------------------------------------------- -LIBRARY IEEE, common_lib, diag_lib, dp_lib, tech_jesd204b_lib, wpfb_lib, tech_pll_lib, tr_10gbe_lib, nw_10gbe_lib, eth_lib, ring_lib; +LIBRARY IEEE, common_lib, diag_lib, dp_lib, tech_jesd204b_lib, wpfb_lib, tech_pll_lib, tr_10GbE_lib, nw_10GbE_lib, eth_lib, ring_lib; USE IEEE.STD_LOGIC_1164.ALL; USE IEEE.NUMERIC_STD.ALL; USE common_lib.common_pkg.ALL; @@ -88,15 +88,6 @@ ENTITY sdp_station IS udp_tx_sosi_arr : OUT t_dp_sosi_arr(c_eth_nof_udp_ports-1 DOWNTO 0) := (OTHERS => c_dp_sosi_rst); udp_tx_siso_arr : IN t_dp_siso_arr(c_eth_nof_udp_ports-1 DOWNTO 0) := (OTHERS => c_dp_siso_rdy); - ---------------------------------------------- - -- 10 GbE - ---------------------------------------------- - reg_nw_10GbE_mac_copi : IN t_mem_copi := c_mem_copi_rst; - reg_nw_10GbE_mac_cipo : OUT t_mem_cipo := c_mem_cipo_rst; - - reg_nw_10GbE_eth10g_copi : IN t_mem_copi := c_mem_copi_rst; - reg_nw_10GbE_eth10g_cipo : OUT t_mem_cipo := c_mem_cipo_rst; - ---------------------------------------------- -- AIT ---------------------------------------------- @@ -170,6 +161,7 @@ ENTITY sdp_station IS -- SST UDP offload bsn monitor reg_bsn_monitor_v2_sst_offload_copi : IN t_mem_copi := c_mem_copi_rst; reg_bsn_monitor_v2_sst_offload_cipo : OUT t_mem_cipo := c_mem_cipo_rst; + ---------------------------------------------- -- SDP Info ---------------------------------------------- @@ -265,6 +257,18 @@ ENTITY sdp_station IS -- BF ring bsn at sync reg_dp_block_validate_bsn_at_sync_bf_copi : IN t_mem_copi := c_mem_copi_rst; reg_dp_block_validate_bsn_at_sync_bf_cipo : OUT t_mem_cipo := c_mem_cipo_rst; + + ---------------------------------------------- + -- BST + ---------------------------------------------- + -- Statistics Enable + reg_stat_enable_bst_copi : IN t_mem_copi := c_mem_copi_rst; + reg_stat_enable_bst_cipo : OUT t_mem_cipo := c_mem_cipo_rst; + + -- Statistics header info + reg_stat_hdr_dat_bst_copi : IN t_mem_copi := c_mem_copi_rst; + reg_stat_hdr_dat_bst_cipo : OUT t_mem_cipo := c_mem_cipo_rst; + ---------------------------------------------- -- SST ---------------------------------------------- @@ -321,35 +325,38 @@ ENTITY sdp_station IS reg_dp_block_validate_bsn_at_sync_xst_copi : IN t_mem_copi := c_mem_copi_rst; reg_dp_block_validate_bsn_at_sync_xst_cipo : OUT t_mem_cipo := c_mem_cipo_rst; - -- XST ring MAC + ---------------------------------------------- + -- tr 10 GbE for ring + ---------------------------------------------- + reg_tr_10GbE_mac_copi : IN t_mem_copi := c_mem_copi_rst; reg_tr_10GbE_mac_cipo : OUT t_mem_cipo := c_mem_cipo_rst; - -- XST ring ETH reg_tr_10GbE_eth10g_copi : IN t_mem_copi := c_mem_copi_rst; reg_tr_10GbE_eth10g_cipo : OUT t_mem_cipo := c_mem_cipo_rst; + -- RING_0 serial + RING_0_TX: OUT STD_LOGIC_VECTOR(c_quad - 1 DOWNTO 0) := (OTHERS => '0'); + RING_0_RX: IN STD_LOGIC_VECTOR(c_quad - 1 DOWNTO 0) := (OTHERS => '0'); + + -- RING_1 serial + RING_1_TX : OUT STD_LOGIC_VECTOR(c_quad - 1 DOWNTO 0) := (OTHERS => '0'); + RING_1_RX : IN STD_LOGIC_VECTOR(c_quad - 1 DOWNTO 0) := (OTHERS => '0'); ---------------------------------------------- - -- BST + -- nw 10 GbE for beamlet output ---------------------------------------------- - -- Statistics Enable - reg_stat_enable_bst_copi : IN t_mem_copi := c_mem_copi_rst; - reg_stat_enable_bst_cipo : OUT t_mem_cipo := c_mem_cipo_rst; - - -- Statistics header info - reg_stat_hdr_dat_bst_copi : IN t_mem_copi := c_mem_copi_rst; - reg_stat_hdr_dat_bst_cipo : OUT t_mem_cipo := c_mem_cipo_rst; + reg_nw_10GbE_mac_copi : IN t_mem_copi := c_mem_copi_rst; + reg_nw_10GbE_mac_cipo : OUT t_mem_cipo := c_mem_cipo_rst; - -- RING_0 serial - RING_0_TX: OUT STD_LOGIC_VECTOR( c_quad - 1 DOWNTO 0) := (OTHERS => '0'); - RING_0_RX: IN STD_LOGIC_VECTOR( c_quad - 1 DOWNTO 0) := (OTHERS => '0'); + reg_nw_10GbE_eth10g_copi : IN t_mem_copi := c_mem_copi_rst; + reg_nw_10GbE_eth10g_cipo : OUT t_mem_cipo := c_mem_cipo_rst; - -- RING_1 serial - RING_1_TX : OUT STD_LOGIC_VECTOR( c_quad - 1 DOWNTO 0) := (OTHERS => '0'); - RING_1_RX : IN STD_LOGIC_VECTOR( c_quad - 1 DOWNTO 0) := (OTHERS => '0'); + ---------------------------------------------- + -- QSFP for beamlet output and for ring cable + ---------------------------------------------- - -- QSFP serial + -- QSFP serial (6 QSFP ports per FPGA) unb2_board_front_io_serial_tx_arr : OUT STD_LOGIC_VECTOR(6 * c_quad-1 DOWNTO 0) := (OTHERS => '0'); unb2_board_front_io_serial_rx_arr : IN STD_LOGIC_VECTOR(6 * c_quad-1 DOWNTO 0) := (OTHERS => '0'); @@ -363,14 +370,17 @@ END sdp_station; ARCHITECTURE str OF sdp_station IS - -- 10 GbE Interface - CONSTANT c_nof_10GbE_offload_streams : NATURAL := 1; - CONSTANT c_nof_blocks_per_packet : NATURAL := 4; - CONSTANT c_nof_beamlets_per_block : NATURAL := c_sdp_N_pol * c_sdp_S_sub_bf; - CONSTANT c_10GbE_block_size : NATURAL := c_nof_blocks_per_packet * c_nof_beamlets_per_block / 4; -- 4 beamlets fit in 1 64bit longword - CONSTANT c_fifo_tx_fill : NATURAL := c_10GbE_block_size; - CONSTANT c_fifo_tx_size : NATURAL := c_fifo_tx_fill + 11; -- Make fifo size large enough for adding header. - + -- Make Tx FIFOs at least c_fifo_tx_fill_margin larger than needed to fit the largest Tx packet + CONSTANT c_fifo_tx_fill_margin : NATURAL := 10; -- >= c_fifo_fill_margin = 6 that is used in dp_fifo_fill_eop + + -- 10 GbE Interface for beamlet output + CONSTANT c_nof_10GbE_beamlet_output : NATURAL := 1; + + -- The nw_10GbE/tr_10GbE uses dp_fifo_fill_eop, so rely on releasing packets (beamlets, arp and ping) at eop instead + -- of at fill level. Make fifo size large enough to fit one packet and the c_fifo_tx_fill_margin. + CONSTANT c_fifo_tx_size_beamlet_output : NATURAL := true_log_pow2(c_sdp_cep_packet_nof_longwords + c_fifo_tx_fill_margin); -- = 976 + 6 --> 1024 + CONSTANT c_fifo_tx_fill_beamlet_output : NATURAL := c_fifo_tx_size_beamlet_output - c_fifo_tx_fill_margin; -- = maximum fill level, so rely on eop + -- Address widths of a single MM instance CONSTANT c_addr_w_ram_ss_ss_wide : NATURAL := ceil_log2(c_sdp_P_pfb * c_sdp_S_sub_bf * c_sdp_Q_fft); CONSTANT c_addr_w_ram_bf_weights : NATURAL := ceil_log2(c_sdp_N_pol * c_sdp_P_pfb * c_sdp_S_sub_bf * c_sdp_Q_fft); @@ -386,27 +396,37 @@ ARCHITECTURE str OF sdp_station IS CONSTANT c_f_adc : STD_LOGIC := '1'; -- '0' => 160M, '1' => 200M CONSTANT c_fsub_type : STD_LOGIC := '0'; -- '0' => critical sampled PFB, '1' => oversampled PFB - CONSTANT c_use_dp_layer : BOOLEAN := TRUE; - CONSTANT c_lane_packet_length_xst : NATURAL := c_sdp_N_crosslets_max * c_sdp_S_pn / 2; -- = crosslet subband select block size devided by 2 as it is repacked from 32b to 64b. = 42 words - CONSTANT c_lane_packet_length_bf : NATURAL := (c_sdp_S_sub_bf * c_sdp_N_pol_bf * 9) / 16; -- = beamlet block size repacked from 36b to 64b (9/16 = 36/64). = 549 words - CONSTANT c_err_bi : NATURAL := 0; + CONSTANT c_lane_payload_nof_longwords_xst : NATURAL := c_sdp_N_crosslets_max * c_sdp_S_pn / 2; -- = crosslet subband select block size divided by 2 as it is repacked from 32b to 64b. = 42 longwords + CONSTANT c_lane_payload_nof_longwords_bf : NATURAL := (c_sdp_S_sub_bf * c_sdp_N_pol_bf * 9) / 16; -- = beamlet block size repacked from 36b to 64b (9/16 = 36/64). = 549 longwords + CONSTANT c_lane_payload_nof_longwords_max : NATURAL := largest(c_lane_payload_nof_longwords_xst, c_lane_payload_nof_longwords_bf); + CONSTANT c_lane_packet_nof_longwords_max : NATURAL := c_lane_payload_nof_longwords_max + c_ring_dp_hdr_field_size; -- = 549 + 3 = 552 + + CONSTANT c_err_bi : NATURAL := 0; CONSTANT c_nof_err_counts : NATURAL := 8; CONSTANT c_bsn_at_sync_check_channel : NATURAL := 1; CONSTANT c_validate_channel : BOOLEAN := TRUE; CONSTANT c_validate_channel_mode : STRING := "="; - CONSTANT c_sync_timeout : NATURAL := sel_a_b(g_sim, g_sim_sync_timeout, c_sdp_N_clk_sync_timeout ); - CONSTANT c_xsub_fifo_tx_fill : NATURAL := c_lane_packet_length_bf + sel_a_b(c_use_dp_layer, c_ring_dp_hdr_field_size, c_ring_eth_hdr_field_size); --total max packet length (bf has largest packets) - CONSTANT c_xsub_fifo_tx_size : NATURAL := 2 * c_lane_packet_length_bf; + CONSTANT c_sync_timeout : NATURAL := sel_a_b(g_sim, g_sim_sync_timeout, c_sdp_N_clk_sync_timeout); + + -- Use same Tx FIFO size for all lanes in the ring to ease the code, no need to optimize Tx FIFO RAM usage per lane. + -- The tr_10GbE uses dp_fifo_fill_eop, so rely on releasing packets (beamlets, crosslets) at eop instead + -- of at fill level. Make fifo size large enough to fit one packet and the c_fifo_tx_fill_margin. + CONSTANT c_fifo_tx_size_ring : NATURAL := true_log_pow2(c_lane_packet_nof_longwords_max + c_fifo_tx_fill_margin); -- = 552 + 6 --> 1024 + CONSTANT c_fifo_tx_fill_ring : NATURAL := c_fifo_tx_size_ring - c_fifo_tx_fill_margin; -- = maximum fill level, so rely on eop CONSTANT c_nof_lane : NATURAL := 3; -- 0 = XST, 1 = BF_0, 2 = BF_1. CONSTANT c_nof_if : NATURAL := 3; -- 3 different interfaces, QSFP, RING_0 and RING_1 CONSTANT c_qsfp_if_offset : NATURAL := 0; -- QSFP signals are indexed at c_nof_if * I. CONSTANT c_ring_0_if_offset : NATURAL := 1; -- RING_0 signals are indexed at c_nof_if * I + 1. CONSTANT c_ring_1_if_offset : NATURAL := 2; -- RING_1 signals are indexed at c_nof_if * I + 2. - CONSTANT c_nof_mac : NATURAL := 12; -- Using 9 out of 12 (this is NOT optimized away during synthesis), must match one of the MAC IP variations, e.g. 1, 3, 4, 12, 24, 48 + CONSTANT c_ring_nof_mac : NATURAL := 12; -- Using 9 out of 12 (this is NOT optimized away during synthesis), must match one of the MAC IP variations, e.g. 1, 3, 4, 12, 24, 48 + + SIGNAL gn_index : NATURAL := 0; + SIGNAL this_rn : STD_LOGIC_VECTOR(c_byte_w-1 DOWNTO 0); + + SIGNAL sdp_info : t_sdp_info := c_sdp_info_rst; + SIGNAL ring_info : t_ring_info; - SIGNAL gn_index : NATURAL := 0; - SIGNAL this_rn : STD_LOGIC_VECTOR(c_byte_w-1 DOWNTO 0); ---------------------------------------------- -- BF ---------------------------------------------- @@ -505,26 +525,29 @@ ARCHITECTURE str OF sdp_station IS SIGNAL bf_udp_siso_arr : t_dp_siso_arr(c_sdp_N_beamsets-1 DOWNTO 0); SIGNAL bf_10GbE_hdr_fields_out_arr : t_slv_1024_arr(c_sdp_N_beamsets-1 DOWNTO 0); - -- 10GbE + -- 10GbE clock SIGNAL tr_ref_clk_312 : STD_LOGIC; SIGNAL tr_ref_clk_156 : STD_LOGIC; SIGNAL tr_ref_rst_156 : STD_LOGIC; - SIGNAL tr_10gbe_serial_tx_arr : STD_LOGIC_VECTOR(c_nof_mac-1 DOWNTO 0) := (OTHERS => '0'); - SIGNAL tr_10gbe_serial_rx_arr : STD_LOGIC_VECTOR(c_nof_mac-1 DOWNTO 0) := (OTHERS => '0'); + -- 10GbE ring + SIGNAL tr_10gbe_ring_serial_tx_arr : STD_LOGIC_VECTOR(c_ring_nof_mac-1 DOWNTO 0) := (OTHERS => '0'); + SIGNAL tr_10gbe_ring_serial_rx_arr : STD_LOGIC_VECTOR(c_ring_nof_mac-1 DOWNTO 0) := (OTHERS => '0'); - SIGNAL nw_10gbe_snk_in_arr : t_dp_sosi_arr(c_nof_10GbE_offload_streams-1 DOWNTO 0) := (OTHERS => c_dp_sosi_rst); - SIGNAL nw_10gbe_snk_out_arr : t_dp_siso_arr(c_nof_10GbE_offload_streams-1 DOWNTO 0) := (OTHERS => c_dp_siso_rdy); - SIGNAL nw_10gbe_src_out_arr : t_dp_sosi_arr(c_nof_10GbE_offload_streams-1 DOWNTO 0) := (OTHERS => c_dp_sosi_rst); - SIGNAL nw_10gbe_src_in_arr : t_dp_siso_arr(c_nof_10GbE_offload_streams-1 DOWNTO 0) := (OTHERS => c_dp_siso_rdy); + SIGNAL tr_10gbe_ring_snk_in_arr : t_dp_sosi_arr(c_ring_nof_mac-1 DOWNTO 0) := (OTHERS => c_dp_sosi_rst); + SIGNAL tr_10gbe_ring_snk_out_arr : t_dp_siso_arr(c_ring_nof_mac-1 DOWNTO 0) := (OTHERS => c_dp_siso_rdy); + SIGNAL tr_10gbe_ring_src_out_arr : t_dp_sosi_arr(c_ring_nof_mac-1 DOWNTO 0) := (OTHERS => c_dp_sosi_rst); + SIGNAL tr_10gbe_ring_src_in_arr : t_dp_siso_arr(c_ring_nof_mac-1 DOWNTO 0) := (OTHERS => c_dp_siso_rdy); - SIGNAL nw_10GbE_hdr_fields_in_arr : t_slv_1024_arr(c_nof_10GbE_offload_streams-1 DOWNTO 0); - - SIGNAL tr_10gbe_src_out_arr : t_dp_sosi_arr(c_nof_mac-1 DOWNTO 0) := (OTHERS => c_dp_sosi_rst); - SIGNAL tr_10gbe_snk_in_arr : t_dp_sosi_arr(c_nof_mac-1 DOWNTO 0) := (OTHERS => c_dp_sosi_rst); - SIGNAL tr_10gbe_src_in_arr : t_dp_siso_arr(c_nof_mac-1 DOWNTO 0) := (OTHERS => c_dp_siso_rdy); - SIGNAL tr_10gbe_snk_out_arr : t_dp_siso_arr(c_nof_mac-1 DOWNTO 0) := (OTHERS => c_dp_siso_rdy); + -- 10GbE beamlet output + SIGNAL nw_10gbe_beamlet_output_snk_in_arr : t_dp_sosi_arr(c_nof_10GbE_beamlet_output-1 DOWNTO 0) := (OTHERS => c_dp_sosi_rst); + SIGNAL nw_10gbe_beamlet_output_snk_out_arr : t_dp_siso_arr(c_nof_10GbE_beamlet_output-1 DOWNTO 0) := (OTHERS => c_dp_siso_rdy); + SIGNAL nw_10gbe_beamlet_output_src_out_arr : t_dp_sosi_arr(c_nof_10GbE_beamlet_output-1 DOWNTO 0) := (OTHERS => c_dp_sosi_rst); + SIGNAL nw_10gbe_beamlet_output_src_in_arr : t_dp_siso_arr(c_nof_10GbE_beamlet_output-1 DOWNTO 0) := (OTHERS => c_dp_siso_rdy); + + SIGNAL nw_10GbE_hdr_fields_in_arr : t_slv_1024_arr(c_nof_10GbE_beamlet_output-1 DOWNTO 0); + -- Network mac, ip, udp SIGNAL cep_eth_src_mac : STD_LOGIC_VECTOR(c_network_eth_mac_addr_w-1 DOWNTO 0); SIGNAL cep_ip_src_addr : STD_LOGIC_VECTOR(c_network_ip_addr_w-1 DOWNTO 0); SIGNAL cep_udp_src_port : STD_LOGIC_VECTOR(c_network_udp_port_w-1 DOWNTO 0); @@ -534,10 +557,6 @@ ARCHITECTURE str OF sdp_station IS SIGNAL bst_udp_src_port : STD_LOGIC_VECTOR(c_network_udp_port_w-1 DOWNTO 0); SIGNAL xst_udp_src_port : STD_LOGIC_VECTOR(c_network_udp_port_w-1 DOWNTO 0); - SIGNAL sdp_info : t_sdp_info := c_sdp_info_rst; - SIGNAL ring_info : t_ring_info; - - BEGIN ----------------------------------------------------------------------------- @@ -993,7 +1012,7 @@ BEGIN ); ----------------------------------------------------------------------------- - -- DP MUX + -- DP MUX to multiplex the c_sdp_N_beamsets via one beamlet output 10GbE link ----------------------------------------------------------------------------- -- Assign hdr_fields to nw_10GbE for ARP/PING functionality. Only the fields: -- eth_src_mac, ip_src_addr and ip_dst_addr are used. Which are identical for @@ -1014,21 +1033,21 @@ BEGIN snk_in_arr => bf_udp_sosi_arr, snk_out_arr => bf_udp_siso_arr, - src_out => nw_10gbe_snk_in_arr(0), - src_in => nw_10gbe_snk_out_arr(0) + src_out => nw_10gbe_beamlet_output_snk_in_arr(0), + src_in => nw_10gbe_beamlet_output_snk_out_arr(0) ); --------------- - -- nw_10GbE + -- nw_10GbE beamlet output --------------- - u_nw_10GbE: ENTITY nw_10GbE_lib.nw_10GbE + u_nw_10GbE_beamlet_output: ENTITY nw_10GbE_lib.nw_10GbE GENERIC MAP ( g_sim => g_sim, g_sim_level => 1, - g_nof_macs => c_nof_10GbE_offload_streams, + g_nof_macs => c_nof_10GbE_beamlet_output, g_direction => "TX_RX", - g_tx_fifo_fill => c_fifo_tx_fill, - g_tx_fifo_size => c_fifo_tx_size, + g_tx_fifo_fill => c_fifo_tx_fill_beamlet_output, + g_tx_fifo_size => c_fifo_tx_size_beamlet_output, g_ip_hdr_field_arr => c_sdp_cep_hdr_field_arr ) @@ -1054,15 +1073,15 @@ BEGIN dp_clk => dp_clk, dp_pps => dp_pps, - src_out_arr => nw_10gbe_src_out_arr, - src_in_arr => nw_10gbe_src_in_arr, - - snk_out_arr => nw_10gbe_snk_out_arr, - snk_in_arr => nw_10gbe_snk_in_arr, + snk_out_arr => nw_10gbe_beamlet_output_snk_out_arr, + snk_in_arr => nw_10gbe_beamlet_output_snk_in_arr, + src_out_arr => nw_10gbe_beamlet_output_src_out_arr, + src_in_arr => nw_10gbe_beamlet_output_src_in_arr, + -- Serial IO - serial_tx_arr => unb2_board_front_io_serial_tx_arr(c_nof_10GbE_offload_streams+c_quad-1 DOWNTO c_quad), - serial_rx_arr => unb2_board_front_io_serial_rx_arr(c_nof_10GbE_offload_streams+c_quad-1 DOWNTO c_quad), + serial_tx_arr => unb2_board_front_io_serial_tx_arr(c_nof_10GbE_beamlet_output+c_quad-1 DOWNTO c_quad), + serial_rx_arr => unb2_board_front_io_serial_rx_arr(c_nof_10GbE_beamlet_output+c_quad-1 DOWNTO c_quad), hdr_fields_in_arr => nw_10GbE_hdr_fields_in_arr ); @@ -1074,8 +1093,8 @@ BEGIN GENERIC MAP ( g_lane_direction => 1, -- transport in positive direction. g_lane_data_w => c_longword_w, - g_lane_packet_length => c_lane_packet_length_xst, - g_use_dp_layer => c_use_dp_layer, + g_lane_packet_length => c_lane_payload_nof_longwords_xst, + g_use_dp_layer => TRUE, g_nof_rx_monitors => c_sdp_N_pn_max, g_nof_tx_monitors => c_sdp_N_pn_max, g_err_bi => c_err_bi, @@ -1123,8 +1142,8 @@ BEGIN GENERIC MAP ( g_lane_direction => 1, -- transport in positive direction. g_lane_data_w => c_longword_w, - g_lane_packet_length => c_lane_packet_length_bf, - g_use_dp_layer => c_use_dp_layer, + g_lane_packet_length => c_lane_payload_nof_longwords_bf, + g_use_dp_layer => TRUE, g_nof_rx_monitors => 1, g_nof_tx_monitors => 1, g_err_bi => c_err_bi, @@ -1231,30 +1250,30 @@ BEGIN -- Combine seperate signals into array for tr_10GbE ----------------------------------------------------------------------------- gen_lane_wires : FOR I IN 0 TO c_nof_lane-1 GENERATE - -- QSFP_RX - lane_rx_cable_sosi_arr(I) <= tr_10gbe_src_out_arr(c_nof_if * I + c_qsfp_if_offset) WHEN ring_info.use_cable_to_previous_rn = '1' ELSE c_dp_sosi_rst; -- use_cable_to_previous_rn=1 -> even lanes receive from cable + -- QSFP_RX, use_cable_to_previous_rn=1 -> even lanes receive from cable + lane_rx_cable_sosi_arr(I) <= tr_10gbe_ring_src_out_arr(c_nof_if * I + c_qsfp_if_offset) WHEN ring_info.use_cable_to_previous_rn = '1' ELSE c_dp_sosi_rst; - -- QSFP_TX - tr_10gbe_snk_in_arr(c_nof_if * I + c_qsfp_if_offset) <= lane_tx_cable_sosi_arr(I) WHEN ring_info.use_cable_to_next_rn = '1' ELSE c_dp_sosi_rst; -- use_cable_to_next_rn=1 -> even lanes transmit to cable + -- QSFP_TX, use_cable_to_next_rn=1 -> even lanes transmit to cable + tr_10gbe_ring_snk_in_arr(c_nof_if * I + c_qsfp_if_offset) <= lane_tx_cable_sosi_arr(I) WHEN ring_info.use_cable_to_next_rn = '1' ELSE c_dp_sosi_rst; - -- RING_0_RX even lanes receive from RING_0 (from the left) - lane_rx_board_sosi_arr(I) <= tr_10gbe_src_out_arr(c_nof_if * I + c_ring_0_if_offset); + -- RING_0_RX even lanes receive from RING_0 (from the left) + lane_rx_board_sosi_arr(I) <= tr_10gbe_ring_src_out_arr(c_nof_if * I + c_ring_0_if_offset); - -- RING_1_TX even lanes transmit to RING_1 (to the right) - tr_10gbe_snk_in_arr(c_nof_if * I + c_ring_1_if_offset) <= lane_tx_board_sosi_arr(I); + -- RING_1_TX even lanes transmit to RING_1 (to the right) + tr_10gbe_ring_snk_in_arr(c_nof_if * I + c_ring_1_if_offset) <= lane_tx_board_sosi_arr(I); END GENERATE; ----------------------------------------------------------------------------- - -- tr_10GbE + -- tr_10GbE ring ----------------------------------------------------------------------------- - u_tr_10GbE: ENTITY tr_10GbE_lib.tr_10GbE + u_tr_10GbE_ring: ENTITY tr_10GbE_lib.tr_10GbE GENERIC MAP ( g_sim => g_sim, g_sim_level => 1, - g_nof_macs => c_nof_mac, + g_nof_macs => c_ring_nof_mac, g_direction => "TX_RX", - g_tx_fifo_fill => c_xsub_fifo_tx_fill, - g_tx_fifo_size => c_xsub_fifo_tx_size + g_tx_fifo_fill => c_fifo_tx_fill_ring, + g_tx_fifo_size => c_fifo_tx_size_ring ) PORT MAP ( -- Transceiver PLL reference clock @@ -1277,15 +1296,15 @@ BEGIN dp_rst => dp_rst, dp_clk => dp_clk, - src_out_arr => tr_10gbe_src_out_arr, - src_in_arr => tr_10gbe_src_in_arr, + src_out_arr => tr_10gbe_ring_src_out_arr, + src_in_arr => tr_10gbe_ring_src_in_arr, - snk_out_arr => tr_10gbe_snk_out_arr, - snk_in_arr => tr_10gbe_snk_in_arr, + snk_out_arr => tr_10gbe_ring_snk_out_arr, + snk_in_arr => tr_10gbe_ring_snk_in_arr, -- Serial IO - serial_tx_arr => tr_10gbe_serial_tx_arr, - serial_rx_arr => tr_10gbe_serial_rx_arr + serial_tx_arr => tr_10gbe_ring_serial_tx_arr, + serial_rx_arr => tr_10gbe_ring_serial_rx_arr ); ----------------------------------------------------------------------------- @@ -1295,19 +1314,19 @@ BEGIN -- QSFP port, RING_0 port and RING_1 port. gen_serial_wires : FOR I IN 0 TO c_nof_lane-1 GENERATE -- QSFP_TX - unb2_board_front_io_serial_tx_arr(I) <= tr_10gbe_serial_tx_arr(c_nof_if * I + c_qsfp_if_offset); + unb2_board_front_io_serial_tx_arr(I) <= tr_10gbe_ring_serial_tx_arr(c_nof_if * I + c_qsfp_if_offset); -- QSFP_RX - tr_10gbe_serial_rx_arr(c_nof_if * I + c_qsfp_if_offset) <= unb2_board_front_io_serial_rx_arr(I); + tr_10gbe_ring_serial_rx_arr(c_nof_if * I + c_qsfp_if_offset) <= unb2_board_front_io_serial_rx_arr(I); -- RING_0_TX - RING_0_TX(I) <= tr_10gbe_serial_tx_arr(c_nof_if * I + c_ring_0_if_offset); + RING_0_TX(I) <= tr_10gbe_ring_serial_tx_arr(c_nof_if * I + c_ring_0_if_offset); -- RING_0_RX - tr_10gbe_serial_rx_arr(c_nof_if * I + c_ring_0_if_offset) <= RING_0_RX(I); + tr_10gbe_ring_serial_rx_arr(c_nof_if * I + c_ring_0_if_offset) <= RING_0_RX(I); -- RING_1_TX - RING_1_TX(I) <= tr_10gbe_serial_tx_arr(c_nof_if * I + c_ring_1_if_offset); + RING_1_TX(I) <= tr_10gbe_ring_serial_tx_arr(c_nof_if * I + c_ring_1_if_offset); -- RING_1_RX - tr_10gbe_serial_rx_arr(c_nof_if * I + c_ring_1_if_offset) <= RING_1_RX(I); + tr_10gbe_ring_serial_rx_arr(c_nof_if * I + c_ring_1_if_offset) <= RING_1_RX(I); END GENERATE; END GENERATE; @@ -1328,12 +1347,12 @@ BEGIN -- LEDs ------------ -- QSFP 1 - Beamlets - unb2_board_qsfp_leds_tx_siso_arr(c_nof_10GbE_offload_streams+c_quad-1 DOWNTO c_quad) <= nw_10gbe_snk_out_arr; - unb2_board_qsfp_leds_tx_sosi_arr(c_nof_10GbE_offload_streams+c_quad-1 DOWNTO c_quad) <= nw_10gbe_snk_in_arr; - unb2_board_qsfp_leds_rx_sosi_arr(c_nof_10GbE_offload_streams+c_quad-1 DOWNTO c_quad) <= nw_10gbe_src_out_arr; + unb2_board_qsfp_leds_tx_siso_arr(c_nof_10GbE_beamlet_output+c_quad-1 DOWNTO c_quad) <= nw_10gbe_beamlet_output_snk_out_arr; + unb2_board_qsfp_leds_tx_sosi_arr(c_nof_10GbE_beamlet_output+c_quad-1 DOWNTO c_quad) <= nw_10gbe_beamlet_output_snk_in_arr; + unb2_board_qsfp_leds_rx_sosi_arr(c_nof_10GbE_beamlet_output+c_quad-1 DOWNTO c_quad) <= nw_10gbe_beamlet_output_src_out_arr; -- QSFP 0 - Ring - unb2_board_qsfp_leds_tx_siso_arr(0 DOWNTO 0) <= tr_10gbe_snk_out_arr(0 DOWNTO 0); - unb2_board_qsfp_leds_tx_sosi_arr(0 DOWNTO 0) <= tr_10gbe_snk_in_arr(0 DOWNTO 0); - unb2_board_qsfp_leds_rx_sosi_arr(0 DOWNTO 0) <= tr_10gbe_src_out_arr(0 DOWNTO 0); + unb2_board_qsfp_leds_tx_siso_arr(0 DOWNTO 0) <= tr_10gbe_ring_snk_out_arr(0 DOWNTO 0); + unb2_board_qsfp_leds_tx_sosi_arr(0 DOWNTO 0) <= tr_10gbe_ring_snk_in_arr(0 DOWNTO 0); + unb2_board_qsfp_leds_rx_sosi_arr(0 DOWNTO 0) <= tr_10gbe_ring_src_out_arr(0 DOWNTO 0); END str; 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 1338fe6d15b0c5bec083dd968b12817a003e259c..b9815e98407b87317b19f63ed24da1f6c0b7fc98 100644 --- a/applications/lofar2/libraries/sdp/src/vhdl/sdp_statistics_offload.vhd +++ b/applications/lofar2/libraries/sdp/src/vhdl/sdp_statistics_offload.vhd @@ -142,7 +142,8 @@ ENTITY sdp_statistics_offload IS -- Input timing regarding the integration interval of the statistics in_sosi : IN t_dp_sosi; - + new_interval : IN STD_LOGIC := '0'; + -- Streaming output of offloaded statistics packets out_sosi : OUT t_dp_sosi; out_siso : IN t_dp_siso; @@ -156,8 +157,9 @@ ENTITY sdp_statistics_offload IS ring_info : IN t_ring_info := c_ring_info_rst; -- only needed for XST sdp_info : IN t_sdp_info; weighted_subbands_flag : IN STD_LOGIC := '0'; + nof_crosslets : IN STD_LOGIC_VECTOR(c_sdp_nof_crosslets_reg_w-1 DOWNTO 0) := (OTHERS => '0'); - crosslets_info : IN STD_LOGIC_VECTOR(c_sdp_crosslets_info_reg_w-1 DOWNTO 0) := (OTHERS => '0') + crosslets_info_rec : IN t_sdp_crosslets_info := c_sdp_crosslets_info_rst ); END sdp_statistics_offload; @@ -202,8 +204,7 @@ ARCHITECTURE str OF sdp_statistics_offload IS crosslets_info_rec : t_sdp_crosslets_info; END RECORD; - CONSTANT c_crosslets_info_rst : t_sdp_crosslets_info := (offset_arr => (OTHERS => 0), step => 0); - CONSTANT c_reg_rst : t_reg := (0, 0, '0', '0', (OTHERS => '0'), '0', 0, 0, 0, 0, 0, 0, 0, 0, c_crosslets_info_rst); + CONSTANT c_reg_rst : t_reg := (0, 0, '0', '0', (OTHERS => '0'), '0', 0, 0, 0, 0, 0, 0, 0, 0, c_sdp_crosslets_info_rst); SIGNAL r : t_reg; SIGNAL nxt_r : t_reg; @@ -225,6 +226,7 @@ ARCHITECTURE str OF sdp_statistics_offload IS SIGNAL data_id_rec : t_sdp_stat_data_id; SIGNAL data_id_slv : STD_LOGIC_VECTOR(31 DOWNTO 0) := (OTHERS => '0'); + SIGNAL in_trigger : STD_LOGIC; SIGNAL trigger_en : STD_LOGIC := '0'; SIGNAL trigger_offload : STD_LOGIC := '0'; SIGNAL mm_done : STD_LOGIC := '0'; @@ -239,6 +241,8 @@ ARCHITECTURE str OF sdp_statistics_offload IS SIGNAL bsn_at_sync : STD_LOGIC_VECTOR(c_dp_stream_bsn_w-1 DOWNTO 0) := (OTHERS => '0'); SIGNAL dp_header_info : STD_LOGIC_VECTOR(1023 DOWNTO 0):= (OTHERS => '0'); + SIGNAL r_dp_header_sop : STD_LOGIC; + SIGNAL r_dp_header_rec : t_sdp_stat_header; -- Debug signals for view in Wave window SIGNAL dbg_c_marker : NATURAL := c_marker; @@ -353,7 +357,7 @@ BEGIN data_id_slv <= func_sdp_map_stat_data_id(g_statistics_type, data_id_rec); - p_control_packet_offload : PROCESS(r, in_sosi, local_si_offset, trigger_offload, nof_crosslets, crosslets_info, nof_packets, dp_sop, dp_header_info) + p_control_packet_offload : PROCESS(r, in_sosi, nof_crosslets, crosslets_info_rec, trigger_offload, dp_sop, dp_header_info, nof_packets) -- in order of appearance VARIABLE v : t_reg; VARIABLE v_index : NATURAL; BEGIN @@ -376,19 +380,18 @@ BEGIN END IF; END IF; - - -- For XST offload capture nof_crosslets and crosslets_info at in_sosi.sync, + -- For XST offload capture nof_crosslets and crosslets_info_rec at in_sosi.sync, -- to make sure they do not change during packets offload. -- . The sdp_crosslets_subband_select.vhd in [2] takes care that - -- nof_crosslets and crosslets_info are valid at the xsel_sosi.sync. The + -- nof_crosslets and crosslets_info_rec are valid at the xsel_sosi.sync. The -- mmp_dp_bsn_align_v2 in [2] then aligns the local xsel_sosi with the -- remote data and passes on the sync. After some latency the sync -- arrives at the sdp_statistics_offload. This latency is very short - -- compared to the sync period, so the nof_crosslets and crosslet_info + -- compared to the sync period, so the nof_crosslets and crosslets_info_rec -- are still valid at the in_sosi.sync. IF in_sosi.sync = '1' THEN v.nof_crosslets := TO_UINT(nof_crosslets); - v.crosslets_info_rec := func_sdp_map_crosslets_info(crosslets_info); + v.crosslets_info_rec := crosslets_info_rec; END IF; -- The trigger_offload occurs nof_cycles_dly after the in_sosi.sync and the @@ -476,6 +479,14 @@ BEGIN nxt_r <= v; END PROCESS; + -- The in_trigger can skip the first in_sosi.sync. This is necessary if the + -- in_sosi input can be restarted, because then at every restart there is + -- no valid previous in_sosi.sync interval yet. This is used for XST offload, + -- because then the in_sync interval is MM programmable. For SST and BST the + -- new_interval = '0' is not used, because then the in_sosi typically + -- remains on after it was started. + in_trigger <= in_sosi.sync AND NOT new_interval; + u_mms_common_variable_delay : ENTITY common_lib.mms_common_variable_delay PORT MAP ( mm_rst => mm_rst, @@ -488,7 +499,7 @@ BEGIN reg_enable_miso => reg_enable_miso, delay => nof_cycles_dly, - trigger => in_sosi.sync, + trigger => in_trigger, trigger_en => trigger_en, trigger_dly => trigger_offload ); @@ -570,6 +581,10 @@ BEGIN hdr_fields_in_arr(0) => r.dp_header_info ); + -- Debug signal, r_dp_header_rec must be available at the r_dp_header_sop + r_dp_header_sop <= dp_offload_snk_in.sop; + r_dp_header_rec <= func_sdp_map_stat_header(r.dp_header_info); + out_sosi <= udp_sosi; u_bsn_mon_udp : ENTITY dp_lib.mms_dp_bsn_monitor_v2 diff --git a/applications/lofar2/libraries/sdp/src/vhdl/sdp_subband_equalizer.vhd b/applications/lofar2/libraries/sdp/src/vhdl/sdp_subband_equalizer.vhd index 05d222f417f158351779bbee469fc7b5543f3124..e5e7d4f12cc299106f3fa6856cf5b01cd87d068a 100644 --- a/applications/lofar2/libraries/sdp/src/vhdl/sdp_subband_equalizer.vhd +++ b/applications/lofar2/libraries/sdp/src/vhdl/sdp_subband_equalizer.vhd @@ -120,7 +120,10 @@ BEGIN g_gain_w => c_sdp_W_sub_weight, g_in_dat_w => c_sdp_W_subband, g_out_dat_w => c_gain_out_dat_w, - g_gains_file_name => g_gains_file_name + g_gains_file_name => g_gains_file_name, + -- extra input latency to ease timing. + g_pipeline_real_mult_input => 2, + g_pipeline_complex_mult_input => 2 ) PORT MAP ( -- System 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 d58cd1b58e1de6fbc64612736e5f3bad2ce48e72..800b255c457e678d9da3d4d7f8771321b5033873 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 @@ -30,7 +30,7 @@ -- Description: The tb starts the dut by writing a scheduled bsn to the bsn_scheduler -- via MM. The offsets and step are configured using MM. The dut makes the subband -- selection based on the MM configuration and N_crosslets. The TB then verifies out_sosi --- and out_crosslets_info of the dut by comparing it to the expected output. +-- and cur_crosslets_info of the dut by comparing it to the expected output. LIBRARY IEEE, common_lib, dp_lib; USE IEEE.std_logic_1164.ALL; @@ -84,20 +84,19 @@ ARCHITECTURE tb OF tb_sdp_crosslets_subband_select IS SIGNAL mm_trigger_miso : t_mem_miso; SIGNAL st_en : STD_LOGIC := '1'; + SIGNAL st_bsn : NATURAL := c_scheduled_bsn - c_nof_block_dly; SIGNAL st_siso_arr : t_dp_siso_arr(c_sdp_P_pfb-1 DOWNTO 0) := (OTHERS => c_dp_siso_rdy); SIGNAL st_sosi_arr : t_dp_sosi_arr(c_sdp_P_pfb-1 DOWNTO 0) := (OTHERS => c_dp_sosi_rst); SIGNAL exp_sosi : t_dp_sosi := c_dp_sosi_rst; - SIGNAL bsn : NATURAL := c_scheduled_bsn - c_nof_block_dly; - SIGNAL in_sosi_arr : t_dp_sosi_arr(c_sdp_P_pfb-1 DOWNTO 0) := (OTHERS => c_dp_sosi_rst); SIGNAL out_sosi : t_dp_sosi; - 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; + SIGNAL exp_cur_crosslets_info_rec : t_sdp_crosslets_info; + SIGNAL cur_crosslets_info_rec : t_sdp_crosslets_info; + SIGNAL exp_prev_crosslets_info_rec : t_sdp_crosslets_info; + SIGNAL prev_crosslets_info_rec : t_sdp_crosslets_info; BEGIN @@ -106,7 +105,7 @@ BEGIN rst <= '1', '0' AFTER c_clk_period*7; p_mm_stimuli : PROCESS - VARIABLE k : NATURAL; + 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 @@ -141,7 +140,7 @@ BEGIN END LOOP; ASSERT rd_crosslet_step = 0 REPORT "Wrong crosslet step after rst." SEVERITY ERROR; - -- b) Read crosslet_info in every sync interval + -- b) Read crosslets_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); @@ -157,9 +156,9 @@ BEGIN 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; + ASSERT rd_crosslet_offsets(I) = exp_cur_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; + ASSERT rd_crosslet_step = exp_cur_crosslets_info_rec.step REPORT "Wrong active crosslet step in output sync interval." SEVERITY ERROR; END LOOP; WAIT; @@ -198,14 +197,14 @@ BEGIN END GENERATE; -- Time stimuli - bsn <= bsn + 1 WHEN rising_edge(clk) AND (st_sosi_arr(0).eop='1'); + st_bsn <= st_bsn + 1 WHEN rising_edge(clk) AND (st_sosi_arr(0).eop='1'); -- Add BSN to the ST data - p_in_sosi : PROCESS(st_sosi_arr, bsn) + p_in_sosi : PROCESS(st_sosi_arr, st_bsn) BEGIN + in_sosi_arr <= st_sosi_arr; FOR I IN 0 TO c_sdp_P_pfb-1 LOOP - in_sosi_arr(I) <= st_sosi_arr(I); - in_sosi_arr(I).bsn <= TO_DP_BSN(bsn); + in_sosi_arr(I).bsn <= TO_DP_BSN(st_bsn); END LOOP; END PROCESS; @@ -216,19 +215,28 @@ BEGIN VARIABLE v_col : NATURAL := 0; VARIABLE v_row : NATURAL := 0; VARIABLE v_offset : NATURAL := 0; - VARIABLE v_sync_ix : NATURAL := 0; + VARIABLE v_sync_ix : NATURAL := 0; -- ix = index VARIABLE v_k : NATURAL := 0; BEGIN FOR I IN 0 TO c_nof_sync*c_nof_block_per_sync-1 LOOP v_sync_ix := I / c_nof_block_per_sync; exp_sosi <= c_dp_sosi_rst; + + -- In a tb it is ok and it can be handy to use rising_edge() on a combinatorial signal WAIT UNTIL rising_edge(out_sosi.sop); - 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); + -- Current sync interval crosslets_info + exp_cur_crosslets_info_rec.step <= c_crosslet_step; FOR C IN 0 TO c_nof_ch_sel_col-1 LOOP - 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); + exp_cur_crosslets_info_rec.offset_arr(C) <= c_crosslet_offsets(C) + v_sync_ix * c_crosslet_step; END LOOP; + -- Previous sync interval crosslets_info + IF out_sosi.sync = '1' THEN + exp_prev_crosslets_info_rec <= exp_cur_crosslets_info_rec; + END IF; + + -- Crosslet data 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; @@ -241,7 +249,6 @@ BEGIN exp_sosi.sop <= '1'; IF I MOD c_nof_block_per_sync = 0 THEN exp_sosi.sync <= '1'; - END IF; ELSIF j = c_nof_ch_sel-1 THEN exp_sosi.eop <= '1'; @@ -250,8 +257,8 @@ BEGIN 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; + exp_sosi <= c_dp_sosi_rst; END LOOP; WAIT; @@ -260,14 +267,17 @@ BEGIN p_verify_out_data : PROCESS(clk) BEGIN IF rising_edge(clk) THEN - ASSERT out_sosi.valid = exp_sosi.valid REPORT "Wrong out_sosi.valid" SEVERITY ERROR; - 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_slv = exp_crosslets_info_slv REPORT "Wrong out_crosslets_info_slv" SEVERITY ERROR; + ASSERT out_sosi.valid = exp_sosi.valid REPORT "Wrong out_sosi.valid" SEVERITY ERROR; + 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 cur_crosslets_info_rec = exp_cur_crosslets_info_rec REPORT "Wrong cur_crosslets_info" SEVERITY ERROR; + ASSERT prev_crosslets_info_rec = exp_prev_crosslets_info_rec REPORT "Wrong prev_crosslets_info" 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; + 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; END IF; END IF; END PROCESS; @@ -294,11 +304,8 @@ BEGIN in_sosi_arr => in_sosi_arr, out_sosi => out_sosi, - out_crosslets_info => out_crosslets_info_slv + cur_crosslets_info_rec => cur_crosslets_info_rec, + prev_crosslets_info_rec => prev_crosslets_info_rec ); - -- 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 1193efc51d1626ac76565c476870d39bcff62236..5298580a65d5c2f3be3ffb750a21a60821eb7e3f 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 @@ -172,9 +172,9 @@ ARCHITECTURE tb OF tb_sdp_statistics_offload IS SIGNAL offload_rx_hdr_dat_mosi : t_mem_mosi := c_mem_mosi_rst; SIGNAL offload_rx_hdr_dat_miso : t_mem_miso; + SIGNAL new_interval : STD_LOGIC := '0'; SIGNAL in_sosi : t_dp_sosi := c_dp_sosi_rst; SIGNAL in_crosslets_info_rec : t_sdp_crosslets_info; - SIGNAL in_crosslets_info_slv : STD_LOGIC_VECTOR(c_sdp_crosslets_info_reg_w-1 DOWNTO 0); SIGNAL sdp_offload_data : STD_LOGIC_VECTOR(c_word_w-1 DOWNTO 0); -- 32 bit SIGNAL sdp_offload_sosi : t_dp_sosi; @@ -242,6 +242,9 @@ ARCHITECTURE tb OF tb_sdp_statistics_offload IS 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; + SIGNAL dbg_c_nof_block_per_sync : NATURAL := c_nof_block_per_sync; + SIGNAL dbg_c_nof_clk_per_block : NATURAL := c_nof_clk_per_block; + SIGNAL dbg_c_nof_clk_per_sync : NATURAL := c_nof_clk_per_sync ; BEGIN @@ -282,7 +285,9 @@ BEGIN in_sosi.bsn <= TO_DP_BSN(c_bsn_init); in_sosi.valid <= '1'; in_crosslets_info_rec <= c_crosslets_info_rec; + new_interval <= '1'; -- mark first in_sosi.sync interval WHILE TRUE LOOP + -- One in_sosi.sync interval FOR i IN 0 TO c_nof_block_per_sync-1 LOOP FOR j IN 0 TO c_nof_clk_per_block-1 LOOP in_sosi.sync <= '0'; @@ -305,17 +310,15 @@ BEGIN proc_common_wait_some_cycles(dp_clk, 1); END LOOP; END LOOP; + new_interval <= '0'; END LOOP; WAIT; END PROCESS; - in_crosslets_info_slv <= func_sdp_map_crosslets_info(in_crosslets_info_rec); - -- Enable the statistics offload when input is running p_enable_trigger : PROCESS BEGIN - -- Wait at least one sync interval, so that DUT can have measured the integration_interval - proc_common_wait_until_hi_lo(dp_clk, in_sosi.sync); + proc_common_wait_until_low(dp_clk, mm_rst); proc_common_wait_some_cycles(mm_clk, 10); -- Enable common variable delay. proc_mem_mm_bus_wr(c_reg_enable_mm_addr_enable, 1, mm_clk, enable_miso, enable_mosi); @@ -648,6 +651,8 @@ BEGIN -- ST in_sosi => in_sosi, + new_interval => new_interval, + out_sosi => sdp_offload_sosi, out_siso => sdp_offload_siso, @@ -660,11 +665,12 @@ BEGIN ring_info => c_exp_ring_info, sdp_info => c_exp_sdp_info, weighted_subbands_flag => weighted_subbands_flag, + nof_crosslets => c_mm_nof_crosslets, - crosslets_info => in_crosslets_info_slv + crosslets_info_rec => in_crosslets_info_rec ); - -- Check crosslet_info functions + -- Verify crosslets_info functions ASSERT c_crosslets_info_rec = func_sdp_map_crosslets_info(c_crosslets_info_slv) REPORT "Error in func_sdp_map_crosslets_info()" SEVERITY FAILURE; -- To view the 32 bit 1GbE offload data more easily in the Wave window 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 22099bf168a065ce4064308f9e30c4a84b12f1e0..62e5956eca69267ecf4434ab5fc0570419f82d3a 100644 --- a/libraries/base/dp/src/vhdl/dp_bsn_sync_scheduler.vhd +++ b/libraries/base/dp/src/vhdl/dp_bsn_sync_scheduler.vhd @@ -63,6 +63,9 @@ -- * out_start: -- Pulse at out_sosi.sync with out_sosi.bsn = ctrl_start_bsn. The first -- out_sosi.sync interval will have nof_blk_max blocks. +-- * out_start_interval: +-- Active from out_start until next out_sosi.sync, so active during the +-- first out_sosi.sync interval of a new out_sosi sequence. -- * out_enable: -- Goes high at first out_sosi.sync. In case of a restart when ctrl_enable -- was already '1', then the out_enable will go low and high to ensure that @@ -135,6 +138,7 @@ ENTITY dp_bsn_sync_scheduler IS 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_start_interval : OUT STD_LOGIC; -- active during first out_sosi.sync interval out_enable : OUT STD_LOGIC -- for tb verification purposes ); END dp_bsn_sync_scheduler; @@ -166,9 +170,13 @@ ARCHITECTURE rtl OF dp_bsn_sync_scheduler IS SIGNAL r : t_reg; SIGNAL nxt_r : t_reg; - SIGNAL output_start : STD_LOGIC; - SIGNAL output_sync : STD_LOGIC; - SIGNAL output_sosi : t_dp_sosi; + SIGNAL output_enable : STD_LOGIC; + SIGNAL output_next : STD_LOGIC; -- active at next output_sync's + SIGNAL output_start : STD_LOGIC; -- active at first output_sync + SIGNAL output_start_interval : STD_LOGIC; -- active during first output_sync interval + SIGNAL output_start_interval_reg : STD_LOGIC := '0'; + SIGNAL output_sync : STD_LOGIC; + SIGNAL output_sosi : t_dp_sosi; BEGIN @@ -371,14 +379,16 @@ BEGIN nxt_r <= v; END PROCESS; + output_enable <= nxt_r.output_enable; + ----------------------------------------------------------------------------- -- Output in_sosi with programmed sync interval or disable the output ----------------------------------------------------------------------------- -- . note this is part of p_comb, but using a separate process is fine too. - p_output_sosi : PROCESS(in_sosi, nxt_r, output_sync) + p_output_sosi : PROCESS(in_sosi, output_enable, output_sync) BEGIN output_sosi <= in_sosi; - IF nxt_r.output_enable = '1' THEN + IF output_enable = '1' THEN output_sosi.sync <= output_sync; ELSE output_sosi.sync <= '0'; @@ -389,7 +399,30 @@ BEGIN END PROCESS; ----------------------------------------------------------------------------- - -- Pipeline output to avoid timing closure problems due to use of nxt_r.output_enable + -- Determine output_start_interval + ----------------------------------------------------------------------------- + output_next <= output_sync AND NOT output_start; + + p_output_start_interval : PROCESS(output_start_interval_reg, output_start, output_next, output_enable) + BEGIN + -- Hold output_start until next sync interval + output_start_interval <= output_start_interval_reg; + IF output_start = '1' THEN + output_start_interval <= '1'; + ELSIF output_next = '1' THEN + output_start_interval <= '0'; + END IF; + -- provided that output_enable is still active + IF output_enable = '0' THEN + output_start_interval <= '0'; + END IF; + END PROCESS; + + output_start_interval_reg <= output_start_interval WHEN rising_edge(clk); + + + ----------------------------------------------------------------------------- + -- Pipeline output to avoid timing closure problems due to use of output_enable ----------------------------------------------------------------------------- u_out_sosi : ENTITY work.dp_pipeline GENERIC MAP ( @@ -406,11 +439,13 @@ BEGIN gen_pipe_out_start : IF g_pipeline = 1 GENERATE out_start <= output_start WHEN rising_edge(clk); + out_start_interval <= output_start_interval_reg; out_enable <= r.output_enable; END GENERATE; no_pipe_out_start : IF g_pipeline = 0 GENERATE out_start <= output_start; - out_enable <= nxt_r.output_enable; + out_start_interval <= output_start_interval; + out_enable <= output_enable; END GENERATE; END rtl; diff --git a/libraries/base/dp/src/vhdl/dp_fifo_fill_eop.vhd b/libraries/base/dp/src/vhdl/dp_fifo_fill_eop.vhd index 21063d1e94390343e93984f694530cb543810f59..381cd124bba1ff193c3423fc76e24d20af32a686 100644 --- a/libraries/base/dp/src/vhdl/dp_fifo_fill_eop.vhd +++ b/libraries/base/dp/src/vhdl/dp_fifo_fill_eop.vhd @@ -19,7 +19,7 @@ ------------------------------------------------------------------------------- ------------------------------------------------------------------------------- --- Author: R. van der Walle +-- Author: R. van der Walle, E. Kooistra -- Purpose: -- The FIFO starts outputting data when the output is ready and it has been @@ -32,6 +32,22 @@ -- after the fifo has been filled sufficiently, a frame is also available when -- the in_eop has been received earlier than the specified g_fifo_fill. For -- more details, please consult the description of dp_fill_fifo_core. +-- Usage: +-- * Typically rely only on eop to release any block from the FIFO. This can +-- be achieved by choosing: +-- . g_fifo_size >= largest block size + c_fifo_fill_margin. +-- . g_fifo_fill = largest block size, or equivalently choose: +-- g_fifo_fill = g_fifo_size - c_fifo_fill_margin +-- It is not adviced to choose g_fifo_fill = g_fifo_size, because then +-- internally the FIFO becomes c_fifo_fill_margin bigger and may then use +-- more RAM. Default c_fifo_fill_margin = 4 + 2 = 6 words. +-- * Often it is possible to make full use of a block RAM by using a FIFO size +-- that is a power of 2, so g_fifo_size = true_log_pow2(largest block size + +-- c_fifo_tx_fill_margin). +-- Remark: +-- * The dp_fifo_fill_eop cannot handle continues stream of blocks without a +-- gap between blocks it needs 1 cycle to process a block. +-- ------------------------------------------------------------------------------- LIBRARY IEEE, common_lib, technology_lib; 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 9cfe48f8dba79806999f160015e2e625b4753190..513fc0e7efb6600ab29ea46932670cd0340b7508 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 @@ -79,10 +79,11 @@ ENTITY mmp_dp_bsn_sync_scheduler IS reg_miso : OUT t_mem_miso; -- Streaming - in_sosi : IN t_dp_sosi; - out_sosi : OUT t_dp_sosi; - out_start : OUT STD_LOGIC; - out_enable : OUT STD_LOGIC + in_sosi : IN t_dp_sosi; + out_sosi : OUT t_dp_sosi; + out_start : OUT STD_LOGIC; + out_start_interval : OUT STD_LOGIC; + out_enable : OUT STD_LOGIC ); END mmp_dp_bsn_sync_scheduler; @@ -215,6 +216,7 @@ BEGIN in_sosi => in_sosi, out_sosi => out_sosi, out_start => out_start, + out_start_interval => out_start_interval, out_enable => out_enable ); diff --git a/libraries/base/dp/src/vhdl/mmp_dp_bsn_sync_scheduler_arr.vhd b/libraries/base/dp/src/vhdl/mmp_dp_bsn_sync_scheduler_arr.vhd index 38a473d061ab50d2a974dc5bc071b5a8d8f9225f..708f83cc5b3fbd31e88817a699f0866910d0b294 100644 --- a/libraries/base/dp/src/vhdl/mmp_dp_bsn_sync_scheduler_arr.vhd +++ b/libraries/base/dp/src/vhdl/mmp_dp_bsn_sync_scheduler_arr.vhd @@ -50,10 +50,11 @@ ENTITY mmp_dp_bsn_sync_scheduler_arr IS reg_miso : OUT t_mem_miso; -- Streaming - in_sosi_arr : IN t_dp_sosi_arr(g_nof_streams-1 DOWNTO 0); - out_sosi_arr : OUT t_dp_sosi_arr(g_nof_streams-1 DOWNTO 0); - out_start : OUT STD_LOGIC; - out_enable : OUT STD_LOGIC + in_sosi_arr : IN t_dp_sosi_arr(g_nof_streams-1 DOWNTO 0); + out_sosi_arr : OUT t_dp_sosi_arr(g_nof_streams-1 DOWNTO 0); + out_start : OUT STD_LOGIC; + out_start_interval : OUT STD_LOGIC; + out_enable : OUT STD_LOGIC ); END mmp_dp_bsn_sync_scheduler_arr; @@ -84,8 +85,9 @@ BEGIN in_sosi => in_sosi_arr(0), out_sosi => single_src_out, - out_start => out_start, - out_enable => out_enable + out_start => out_start, + out_start_interval => out_start_interval, + out_enable => out_enable ); -- Pipeline in_sosi_arr to compensate for the latency in mmp_dp_bsn_sync_scheduler diff --git a/libraries/base/dp/src/vhdl/mms_dp_gain_serial_arr.vhd b/libraries/base/dp/src/vhdl/mms_dp_gain_serial_arr.vhd index 25551f29f88ba7b36582739de336065b9bcd1c6a..7e8174fa8f8f52c878ebf7f3f6af51087179eab3 100644 --- a/libraries/base/dp/src/vhdl/mms_dp_gain_serial_arr.vhd +++ b/libraries/base/dp/src/vhdl/mms_dp_gain_serial_arr.vhd @@ -100,7 +100,7 @@ ARCHITECTURE str OF mms_dp_gain_serial_arr IS -- dat_w : NATURAL; -- nof_dat : NATURAL; -- optional, nof dat words <= 2**adr_w -- init_sl : STD_LOGIC; -- optional, init all dat words to std_logic '0', '1' or 'X' - CONSTANT c_mm_ram : t_c_mem := (latency => 2, -- set latency to 2 to ease timing + CONSTANT c_mm_ram : t_c_mem := (latency => 1, adr_w => ceil_log2(g_nof_gains), dat_w => sel_a_b(g_complex_gain, c_nof_complex, 1) * g_gain_w, nof_dat => g_nof_gains, diff --git a/libraries/base/dp/tb/vhdl/tb_dp_bsn_sync_scheduler.vhd b/libraries/base/dp/tb/vhdl/tb_dp_bsn_sync_scheduler.vhd index 67939303a128f1791853c3c7ea1314f5296d2f48..930588f18e0c8b0114dd064c864f1449a19ea81a 100644 --- a/libraries/base/dp/tb/vhdl/tb_dp_bsn_sync_scheduler.vhd +++ b/libraries/base/dp/tb/vhdl/tb_dp_bsn_sync_scheduler.vhd @@ -34,7 +34,7 @@ -- > as 4 -- > run -all -- View in Wave window u_dut: r, nxt_r, and tb: in_sosi, out_sosi, --- out_sync, out_start +-- out_sync, out_start, out_start_interval -- -- Development steps: -- . Step 1 ~1 day work (idea started earlier, so requirements were clear), @@ -76,13 +76,14 @@ USE dp_lib.tb_dp_pkg.ALL; ENTITY tb_dp_bsn_sync_scheduler IS GENERIC ( -- Input sync period and sosi ctrl - g_nof_input_sync : NATURAL := 10; + g_nof_input_sync : NATURAL := 10; -- Use c_nof_input_sync > g_block_size, see tb_tb_dp_bsn_sync_scheduler g_nof_block_per_input_sync : NATURAL := 17; g_block_size : NATURAL := 2; g_input_gap_size : NATURAL := 0; -- Output sync period - g_nof_samples_per_output_sync : NATURAL := 45 -- 45 / g_block_size = 4.5 + g_nof_samples_per_output_sync : NATURAL := 45; -- 45 / g_block_size = 4.5 + g_pipeline : NATURAL := 0 -- 0 or 1 ); END tb_dp_bsn_sync_scheduler; @@ -108,6 +109,8 @@ ARCHITECTURE tb OF tb_dp_bsn_sync_scheduler IS CONSTANT c_output_nof_blocks_min : NATURAL := g_nof_samples_per_output_sync / g_block_size; CONSTANT c_enable_init_nof_bsn : NATURAL := ceil_value(c_output_nof_blocks_min / g_block_size + 10, g_nof_block_per_input_sync); + CONSTANT c_out_enable_margin : NATURAL := g_block_size; + SIGNAL clk : STD_LOGIC := '1'; SIGNAL rst : STD_LOGIC := '1'; SIGNAL cnt : INTEGER := 0; @@ -145,28 +148,36 @@ ARCHITECTURE tb OF tb_dp_bsn_sync_scheduler IS -- Output SIGNAL out_sync : STD_LOGIC; -- declared next to in_sync, out_start and out_sosi for easier comparison in Wave window SIGNAL out_start : STD_LOGIC; + SIGNAL out_start_interval : STD_LOGIC; + SIGNAL exp_start_interval : STD_LOGIC := '0'; + SIGNAL first_interval : STD_LOGIC := '0'; SIGNAL out_enable : STD_LOGIC; + SIGNAL expected_out_enable : STD_LOGIC := '0'; SIGNAL out_sosi : t_dp_sosi := c_dp_sosi_init; -- Verify + SIGNAL in_sosi_integer_comb : t_dp_sosi_integer; + SIGNAL in_sosi_integer_pipe : t_dp_sosi_integer; SIGNAL in_sosi_integer : t_dp_sosi_integer; SIGNAL out_sosi_integer : t_dp_sosi_integer; - SIGNAL verify_sosi_equal : STD_LOGIC := '0'; - SIGNAL verify_sync : STD_LOGIC := '1'; - SIGNAL recover_from_in_lost : STD_LOGIC := '0'; + SIGNAL verify_sosi_equal : STD_LOGIC := '0'; + SIGNAL verify_sosi_equal_at_sop : STD_LOGIC := '0'; + SIGNAL verify_sosi_equal_at_valid : STD_LOGIC := '0'; + SIGNAL verify_sync : STD_LOGIC := '1'; + SIGNAL recover_from_in_lost : STD_LOGIC := '0'; - SIGNAL verifying_sync_equal : STD_LOGIC := '0'; + SIGNAL verifying_sync_equal : STD_LOGIC := '0'; - SIGNAL prev_out_enable : STD_LOGIC := '0'; - SIGNAL pending_out_disable : STD_LOGIC := '0'; - SIGNAL expected_out_enable : STD_LOGIC := '0'; - SIGNAL expected_out_enable1 : STD_LOGIC := '0'; - SIGNAL expected_out_enable2 : STD_LOGIC := '0'; - SIGNAL expecting_out_start : STD_LOGIC := '0'; - SIGNAL hold_out_eop : STD_LOGIC := '0'; - SIGNAL hold_out_sop : STD_LOGIC := '0'; - SIGNAL out_sop_cnt : NATURAL := 0; + SIGNAL prev_ctrl_enable : STD_LOGIC := '0'; + SIGNAL prev_out_enable : STD_LOGIC := '0'; + SIGNAL out_enable_cnt : NATURAL := 0; + SIGNAL nxt_out_enable_cnt : NATURAL := 0; + SIGNAL expected_out_enable_comb : STD_LOGIC := '0'; + SIGNAL expected_out_enable_pipe : STD_LOGIC := '0'; + SIGNAL expecting_out_start : STD_LOGIC := '0'; + SIGNAL hold_out_sop : STD_LOGIC := '0'; + SIGNAL out_sop_cnt : NATURAL := 0; SIGNAL dbg_out_sosi_sync : STD_LOGIC; SIGNAL dbg_out_sosi_sop : STD_LOGIC; @@ -346,75 +357,53 @@ BEGIN ----------------------------------------------------------------------------- -- . Verify out_enable ----------------------------------------------------------------------------- - p_hold_out_eop : PROCESS(clk) + -- The expected out_enable is difficult to determine cycle exact, because + -- it depends on g_block_size = 2 or > 2 and on g_pipeline. Therfore use + -- expected_out_enable_comb = '-' to define dont care. + -- * For g_block_size = 2 the use of r.enable (instead of v.enable) in + -- dp_bsn_sync_scheduler.vhd causes that the output can stay enabled 2 + -- cycles longer, which is ok. Using v.enable does avoid these extra + -- cycles, but for timing closure it is preferred to use r.enable. + + -- Verify out_enable + p_expected_out_enable : PROCESS(ctrl_enable, in_sosi, ctrl_start_bsn, ctrl_enable_evt, out_enable_cnt, ctrl_enable, in_sosi, ctrl_start_bsn) BEGIN - IF rising_edge(clk) THEN - IF out_sosi.eop = '1' THEN - hold_out_eop <= '1'; - ELSIF out_sosi.sop = '1' THEN - hold_out_eop <= '0'; - END IF; - END IF; - END PROCESS; + -- Default + expected_out_enable_comb <= '0'; - -- Determine expected out_enable - p_expected_out_enable : PROCESS(ctrl_enable, ctrl_enable_evt, in_sosi, ctrl_start_bsn, out_enable, pending_out_disable, hold_out_eop) - BEGIN - -- Expect output disable after ctrl_enable_evt - IF ctrl_enable_evt = '1' THEN - IF out_enable = '0' THEN - -- Output is already disabled - expected_out_enable <= '0'; - ELSE - -- Output is enabled, so this is a re-enable event. - IF hold_out_eop = '1' THEN - expected_out_enable <= '0'; -- end of block, so output can disable immediately - ELSE - pending_out_disable <= '1'; -- plan output disable before re-enable - END IF; - END IF; - END IF; - - IF pending_out_disable <= '1' THEN - IF hold_out_eop = '1' THEN - expected_out_enable <= '0'; -- end of block, so output can disable - pending_out_disable <= '0'; - END IF; - END IF; - - -- Expect output enable at start BSN + -- Expect output enable '1' when ctrl_enable is active, but after ctrl_start_bsn IF ctrl_enable = '1' THEN IF UNSIGNED(in_sosi.bsn) >= UNSIGNED(ctrl_start_bsn) THEN - expected_out_enable <= '1'; + expected_out_enable_comb <= '1'; END IF; END IF; + + -- Introduce some dont care margin in case of ctrl_enable_evt when ctrl_enable was active and may change. + -- The ctrl_enable may go inactive (= stop) or remain active (= restart). + IF ctrl_enable_evt = '1' AND prev_ctrl_enable = '1' THEN + nxt_out_enable_cnt <= 0; + expected_out_enable_comb <= '-'; + ELSIF out_enable_cnt < c_out_enable_margin THEN + nxt_out_enable_cnt <= out_enable_cnt + 1; + expected_out_enable_comb <= '-'; + END IF; END PROCESS; - expected_out_enable1 <= expected_out_enable WHEN rising_edge(clk); - expected_out_enable2 <= expected_out_enable1 WHEN rising_edge(clk); + prev_ctrl_enable <= ctrl_enable WHEN rising_edge(clk); + + out_enable_cnt <= nxt_out_enable_cnt WHEN rising_edge(clk); + + expected_out_enable_pipe <= expected_out_enable_comb WHEN rising_edge(clk); + + expected_out_enable <= expected_out_enable_comb WHEN g_pipeline = 0 ELSE expected_out_enable_pipe; p_verify_out_enable : PROCESS(clk) BEGIN - -- Use registered values to compare, to avoid combinatorial differences - -- that can occur during a simulation delta cycle. These combinatorial - -- differences are not relevant, because they get resolved after a few - -- delta cycles. IF rising_edge(clk) THEN - IF out_enable /= expected_out_enable THEN - IF out_enable = '1' THEN - IF g_block_size > 2 THEN - REPORT "Unexpected enabled out_enable" SEVERITY ERROR; - ELSIF out_enable /= expected_out_enable2 THEN - -- For g_block_size = 2 the use of r.enable (instead of v.enable) - -- in dp_bsn_sync_scheduler.vhd causes that the output can stay - -- enabled 2 cycles longer, which is ok. Using v.enable does - -- avoid this need to use expected_out_enable2, but for timing - -- closure it is preferred to use r.enable. - REPORT "Unexpected enabled out_enable2" SEVERITY ERROR; - END IF; - ELSE - REPORT "Unexpected disabled out_enable" SEVERITY ERROR; - END IF; + IF expected_out_enable = '1' THEN + ASSERT out_enable = '1' REPORT "Wrong out_enable, should be active" SEVERITY ERROR; + ELSIF expected_out_enable = '0' THEN + ASSERT out_enable = '0' REPORT "Wrong out_enable, should be inactive" SEVERITY ERROR; END IF; END IF; END PROCESS; @@ -471,6 +460,23 @@ BEGIN END IF; END PROCESS; + exp_start_interval <= out_start OR (first_interval AND NOT out_sync) WHEN rst = '0' ELSE '0'; + + p_verify_out_start_interval : PROCESS(clk) + BEGIN + IF rising_edge(clk) THEN + -- Create first_interval for exp_start_interval + IF out_start = '1' THEN + first_interval <= '1'; + ELSIF out_sync = '1' THEN + first_interval <= '0'; + END IF; + + -- Verify exp_start_interval + ASSERT exp_start_interval = out_start_interval REPORT "Wrong out_start_interval" SEVERITY ERROR; + END IF; + END PROCESS; + ----------------------------------------------------------------------------- -- . Verify out_sosi = in_sosi, for all fields except out_sosi.sync ----------------------------------------------------------------------------- @@ -480,14 +486,19 @@ BEGIN -- declaration is not sufficient. verify_sosi_equal <= out_enable WHEN rising_edge(clk); - in_sosi_integer <= func_dp_stream_slv_to_integer(in_sosi, c_natural_w) WHEN rising_edge(clk); - out_sosi_integer <= func_dp_stream_slv_to_integer(out_sosi, c_natural_w) WHEN rising_edge(clk); + verify_sosi_equal_at_sop <= verify_sosi_equal AND in_sosi_integer.sop; + verify_sosi_equal_at_valid <= verify_sosi_equal AND in_sosi_integer.valid; + + in_sosi_integer_comb <= func_dp_stream_slv_to_integer(in_sosi, c_natural_w) WHEN rising_edge(clk); + in_sosi_integer_pipe <= in_sosi_integer_comb WHEN rising_edge(clk); + in_sosi_integer <= in_sosi_integer_comb WHEN g_pipeline = 0 ELSE in_sosi_integer_pipe; + out_sosi_integer <= func_dp_stream_slv_to_integer(out_sosi, c_natural_w) WHEN rising_edge(clk); - proc_dp_verify_sosi_equal( "bsn", clk, verify_sosi_equal, out_sosi_integer, in_sosi_integer); + proc_dp_verify_sosi_equal( "bsn", clk, verify_sosi_equal_at_sop, out_sosi_integer, in_sosi_integer); proc_dp_verify_sosi_equal( "sop", clk, verify_sosi_equal, out_sosi_integer, in_sosi_integer); proc_dp_verify_sosi_equal( "eop", clk, verify_sosi_equal, out_sosi_integer, in_sosi_integer); proc_dp_verify_sosi_equal("valid", clk, verify_sosi_equal, out_sosi_integer, in_sosi_integer); - proc_dp_verify_sosi_equal( "data", clk, verify_sosi_equal, out_sosi_integer, in_sosi_integer); + proc_dp_verify_sosi_equal( "data", clk, verify_sosi_equal_at_valid, out_sosi_integer, in_sosi_integer); -- Verify that out_sosi blocks have sop and eop proc_dp_verify_sop_and_eop(clk, out_sosi.valid, out_sosi.sop, out_sosi.eop, hold_out_sop); @@ -558,7 +569,7 @@ BEGIN GENERIC MAP ( g_bsn_w => c_bsn_w, g_block_size => g_block_size, - g_pipeline => 0 + g_pipeline => g_pipeline ) PORT MAP ( rst => rst, @@ -578,6 +589,7 @@ BEGIN in_sosi => in_sosi, out_sosi => out_sosi, out_start => out_start, + out_start_interval => out_start_interval, out_enable => out_enable ); diff --git a/libraries/base/dp/tb/vhdl/tb_mms_dp_gain_serial_arr.vhd b/libraries/base/dp/tb/vhdl/tb_mms_dp_gain_serial_arr.vhd index 43da667fd785be1a580b1607b5eb35a361d1a3ce..23bc0cbdaaeeefce44a4b31ee61c3b660d9428f2 100644 --- a/libraries/base/dp/tb/vhdl/tb_mms_dp_gain_serial_arr.vhd +++ b/libraries/base/dp/tb/vhdl/tb_mms_dp_gain_serial_arr.vhd @@ -57,7 +57,7 @@ ARCHITECTURE tb OF tb_mms_dp_gain_serial_arr IS CONSTANT c_mm_clk_period : TIME := 20 ns; CONSTANT c_dp_clk_period : TIME := 10 ns; CONSTANT c_cross_clock_domain_latency : NATURAL := 20; - CONSTANT c_dut_latency : NATURAL := 5; -- = 3 for the real or complex multiplier + 2 for the RAM read latency + CONSTANT c_dut_latency : NATURAL := 4; -- = 3 for the real or complex multiplier + 1 for the RAM read latency CONSTANT c_real_multiply : BOOLEAN := g_complex_data=FALSE AND g_complex_gain=FALSE; CONSTANT c_nof_gains_w : NATURAL := ceil_log2(g_nof_gains); diff --git a/libraries/base/dp/tb/vhdl/tb_tb_dp_bsn_sync_scheduler.vhd b/libraries/base/dp/tb/vhdl/tb_tb_dp_bsn_sync_scheduler.vhd index aea05a239d8776863bee18a2457fe397579c8727..03f0254a6fc66f4851572fcf8438cdfe00e763f6 100644 --- a/libraries/base/dp/tb/vhdl/tb_tb_dp_bsn_sync_scheduler.vhd +++ b/libraries/base/dp/tb/vhdl/tb_tb_dp_bsn_sync_scheduler.vhd @@ -42,6 +42,7 @@ ARCHITECTURE tb OF tb_tb_dp_bsn_sync_scheduler IS -- repeat period of the sync pattern is visible by nxt_r.accumulate in -- dp_bsn_scheduler.vhd. CONSTANT c_nof_input_sync : NATURAL := 25; + CONSTANT c_pipeline : NATURAL := 1; BEGIN -- from tb_dp_bsn_scheduler.vhd @@ -54,27 +55,30 @@ BEGIN -- -- -- Output sync period -- g_nof_samples_per_output_sync : NATURAL := 45; -- = g_block_size * 9 / 2 + -- g_pipeline : NATURAL := 0 - u_output_is_input : ENTITY work.tb_dp_bsn_sync_scheduler GENERIC MAP (c_nof_input_sync, 17, 10, 3, 170); -- 170/10 = 17 block/out_sync, = in_sosi - u_output_is_input_no_gaps : ENTITY work.tb_dp_bsn_sync_scheduler GENERIC MAP (c_nof_input_sync, 17, 5, 0, 85); -- 85/5 = 17 block/out_sync, = in_sosi + gen_tb : FOR P IN 0 TO c_pipeline GENERATE + u_output_is_input : ENTITY work.tb_dp_bsn_sync_scheduler GENERIC MAP (c_nof_input_sync, 17, 10, 3, 170, P); -- 170/10 = 17 block/out_sync, = in_sosi + u_output_is_input_no_gaps : ENTITY work.tb_dp_bsn_sync_scheduler GENERIC MAP (c_nof_input_sync, 17, 5, 0, 85, P); -- 85/5 = 17 block/out_sync, = in_sosi - u_sync_interval_0_5x : ENTITY work.tb_dp_bsn_sync_scheduler GENERIC MAP (c_nof_input_sync, 17, 10, 3, 85); -- 85/10 = 8.5 block/out_sync, factor 85/170 = 0.5, - u_sync_interval_1_5x : ENTITY work.tb_dp_bsn_sync_scheduler GENERIC MAP (c_nof_input_sync, 17, 10, 3, 255); -- 255/10 = 25.5 block/out_sync, factor 255/170 = 1.5, - u_sync_interval_prime_251 : ENTITY work.tb_dp_bsn_sync_scheduler GENERIC MAP (c_nof_input_sync, 17, 10, 3, 251); -- 251/10 = 25.1 block/out_sync, 251 is a prime + u_sync_interval_0_5x : ENTITY work.tb_dp_bsn_sync_scheduler GENERIC MAP (c_nof_input_sync, 17, 10, 3, 85, P); -- 85/10 = 8.5 block/out_sync, factor 85/170 = 0.5, + u_sync_interval_1_5x : ENTITY work.tb_dp_bsn_sync_scheduler GENERIC MAP (c_nof_input_sync, 17, 10, 3, 255, P); -- 255/10 = 25.5 block/out_sync, factor 255/170 = 1.5, + u_sync_interval_prime_251 : ENTITY work.tb_dp_bsn_sync_scheduler GENERIC MAP (c_nof_input_sync, 17, 10, 3, 251, P); -- 251/10 = 25.1 block/out_sync, 251 is a prime - u_short_block_4_3_15 : ENTITY work.tb_dp_bsn_sync_scheduler GENERIC MAP (c_nof_input_sync, 4, 3, 3, 15); -- 15/3 = 5 block/out_sync, - u_short_block_5_3_16 : ENTITY work.tb_dp_bsn_sync_scheduler GENERIC MAP (c_nof_input_sync, 5, 3, 3, 16); -- 16/3 = 5.33 block/out_sync, - u_short_block_6_3_17 : ENTITY work.tb_dp_bsn_sync_scheduler GENERIC MAP (c_nof_input_sync, 6, 3, 3, 17); -- 17/3 = 5.66 block/out_sync, + u_short_block_4_3_15 : ENTITY work.tb_dp_bsn_sync_scheduler GENERIC MAP (c_nof_input_sync, 4, 3, 3, 15, P); -- 15/3 = 5 block/out_sync, + u_short_block_5_3_16 : ENTITY work.tb_dp_bsn_sync_scheduler GENERIC MAP (c_nof_input_sync, 5, 3, 3, 16, P); -- 16/3 = 5.33 block/out_sync, + u_short_block_6_3_17 : ENTITY work.tb_dp_bsn_sync_scheduler GENERIC MAP (c_nof_input_sync, 6, 3, 3, 17, P); -- 17/3 = 5.66 block/out_sync, - u_short_block_no_gaps_4_3_15 : ENTITY work.tb_dp_bsn_sync_scheduler GENERIC MAP (c_nof_input_sync, 4, 3, 0, 15); -- 15/3 = 5 block/out_sync, - u_short_block_no_gaps_5_3_16 : ENTITY work.tb_dp_bsn_sync_scheduler GENERIC MAP (c_nof_input_sync, 5, 3, 0, 16); -- 16/3 = 5.33 block/out_sync, - u_short_block_no_gaps_6_3_17 : ENTITY work.tb_dp_bsn_sync_scheduler GENERIC MAP (c_nof_input_sync, 6, 3, 0, 17); -- 17/3 = 5.66 block/out_sync, + u_short_block_no_gaps_4_3_15 : ENTITY work.tb_dp_bsn_sync_scheduler GENERIC MAP (c_nof_input_sync, 4, 3, 0, 15, P); -- 15/3 = 5 block/out_sync, + u_short_block_no_gaps_5_3_16 : ENTITY work.tb_dp_bsn_sync_scheduler GENERIC MAP (c_nof_input_sync, 5, 3, 0, 16, P); -- 16/3 = 5.33 block/out_sync, + u_short_block_no_gaps_6_3_17 : ENTITY work.tb_dp_bsn_sync_scheduler GENERIC MAP (c_nof_input_sync, 6, 3, 0, 17, P); -- 17/3 = 5.66 block/out_sync, - u_short_block_size_2 : ENTITY work.tb_dp_bsn_sync_scheduler GENERIC MAP (c_nof_input_sync, 7, 2, 3, 16); -- 16/2 = 8 block/out_sync, - u_short_block_size_2_no_gaps : ENTITY work.tb_dp_bsn_sync_scheduler GENERIC MAP (c_nof_input_sync, 7, 2, 0, 16); -- 16/2 = 8 block/out_sync, + u_short_block_size_2 : ENTITY work.tb_dp_bsn_sync_scheduler GENERIC MAP (c_nof_input_sync, 7, 2, 3, 16, P); -- 16/2 = 8 block/out_sync, + u_short_block_size_2_no_gaps : ENTITY work.tb_dp_bsn_sync_scheduler GENERIC MAP (c_nof_input_sync, 7, 2, 0, 16, P); -- 16/2 = 8 block/out_sync, - u_fraction_half : ENTITY work.tb_dp_bsn_sync_scheduler GENERIC MAP (c_nof_input_sync, 17, 10, 3, 45); -- 45/10 = 4.5 block/out_sync - u_fraction_0 : ENTITY work.tb_dp_bsn_sync_scheduler GENERIC MAP (c_nof_input_sync, 17, 10, 3, 50); -- 50/10 = 5 block/out_sync + u_fraction_half : ENTITY work.tb_dp_bsn_sync_scheduler GENERIC MAP (c_nof_input_sync, 17, 10, 3, 45, P); -- 45/10 = 4.5 block/out_sync + u_fraction_0 : ENTITY work.tb_dp_bsn_sync_scheduler GENERIC MAP (c_nof_input_sync, 17, 10, 3, 50, P); -- 50/10 = 5 block/out_sync + END GENERATE; END tb; diff --git a/libraries/base/ring/src/vhdl/ring_pkg.vhd b/libraries/base/ring/src/vhdl/ring_pkg.vhd index 41ecf785cedd835bc29d1b7270f45c6499d52560..da55bc2268dc5badf90243a91ae79e45123ceb61 100644 --- a/libraries/base/ring/src/vhdl/ring_pkg.vhd +++ b/libraries/base/ring/src/vhdl/ring_pkg.vhd @@ -78,8 +78,7 @@ PACKAGE ring_pkg is ( field_name_pad("eth_src_mac" ), "RW", 48, field_default(c_ring_eth_src_mac) ), ( field_name_pad("eth_type" ), "RW", 16, field_default(0) ) ); - CONSTANT c_ring_eth_hdr_field_size : NATURAL := ceil_div(field_slv_len(c_ring_eth_hdr_field_arr), c_longword_w); - + CONSTANT c_ring_eth_hdr_field_size : NATURAL := ceil_div(field_slv_len(c_ring_eth_hdr_field_arr), c_longword_w); -- = 14/8 = 2 longwords CONSTANT c_ring_dp_nof_hdr_fields : NATURAL := 6; CONSTANT c_ring_dp_hdr_field_sel : STD_LOGIC_VECTOR(c_ring_dp_nof_hdr_fields-1 DOWNTO 0) := "000"&"000"; @@ -91,7 +90,7 @@ PACKAGE ring_pkg is ( field_name_pad("dp_sync" ), "RW", 1, field_default(0) ), ( field_name_pad("dp_bsn" ), "RW", 63, field_default(0) ) ); - CONSTANT c_ring_dp_hdr_field_size : NATURAL := ceil_div(field_slv_len(c_ring_dp_hdr_field_arr), c_longword_w); + CONSTANT c_ring_dp_hdr_field_size : NATURAL := ceil_div(field_slv_len(c_ring_dp_hdr_field_arr), c_longword_w); -- = 24/8 = 3 longwords FUNCTION func_ring_nof_hops_to_source_rn(hops, this_rn, N_rn, lane_dir : NATURAL) RETURN NATURAL; FUNCTION func_ring_nof_hops_to_source_rn(hops, this_rn, N_rn : STD_LOGIC_VECTOR; lane_dir : NATURAL) RETURN STD_LOGIC_VECTOR; -- return vector length is same as hops vector length diff --git a/libraries/dsp/st/src/vhdl/st_sst.vhd b/libraries/dsp/st/src/vhdl/st_sst.vhd index b21195656a2cec221c3a4afdb74bf46efc740349..a0092862dae0d6ab6f159514e81f27f8f3f7459a 100644 --- a/libraries/dsp/st/src/vhdl/st_sst.vhd +++ b/libraries/dsp/st/src/vhdl/st_sst.vhd @@ -21,6 +21,7 @@ LIBRARY IEEE, common_lib, mm_lib, technology_lib, dp_lib; USE IEEE.std_logic_1164.ALL; +USE IEEE.math_real.ALL; -- for sim only USE common_lib.common_pkg.ALL; USE common_lib.common_mem_pkg.ALL; USE common_lib.common_field_pkg.ALL; @@ -43,6 +44,10 @@ USE technology_lib.technology_select_pkg.ALL; -- of the previous sync interval. The length of the sync interval determines -- the nof accumlations per statistic, hence the integration time. See st_calc -- for more details. +-- +-- View wrdata_power and stat_bin in Wave window to see the stat power +-- values series. +-- -- Remarks: -- . The in_sync is assumed to be a pulse an interpreted directly. -- . The MM register is single page RAM to save memory resources. Therefore @@ -56,12 +61,13 @@ USE technology_lib.technology_select_pkg.ALL; ENTITY st_sst IS GENERIC ( g_technology : NATURAL := c_tech_select_default; - g_nof_stat : NATURAL := 512; -- nof accumulators + g_nof_stat : NATURAL := 512; -- total nof accumulators g_xst_enable : BOOLEAN := FALSE; -- when set to true, an extra memory is instantiated to hold the imaginary part of the cross-correlation results g_in_data_w : NATURAL := 18; -- width o dth edata to be accumulated g_stat_data_w : NATURAL := 54; -- statistics accumulator width - g_stat_data_sz : NATURAL := 2 -- statistics word width >= statistics accumulator width and fit in a power of 2 multiple 32b MM words - ); + g_stat_data_sz : NATURAL := 2; -- statistics word width >= statistics accumulator width and fit in a power of 2 multiple 32b MM words + g_stat_multiplex: NATURAL := 2 -- number of accumulators per stat_bin, for debug purposes with view in Wave window + ); PORT ( mm_rst : IN STD_LOGIC; mm_clk : IN STD_LOGIC; @@ -103,7 +109,7 @@ ARCHITECTURE str OF st_sst IS CONSTANT c_field_arr : t_common_field_arr(0 DOWNTO 0) := (0=> ( field_name_pad("treshold"), "RW", c_nof_stat_w, field_default(0) )); SIGNAL mm_fields_out : STD_LOGIC_VECTOR(field_slv_out_len(c_field_arr)-1 DOWNTO 0); - SIGNAL treshold : STD_LOGIC_VECTOR(c_nof_stat_w-1 DOWNTO 0); + SIGNAL treshold : STD_LOGIC_VECTOR(c_nof_stat_w-1 DOWNTO 0); TYPE reg_type IS RECORD in_sosi_reg : t_dp_sosi; @@ -113,14 +119,20 @@ ARCHITECTURE str OF st_sst IS SIGNAL r, rin : reg_type; SIGNAL in_sync : STD_LOGIC; - SIGNAL stat_data_re : STD_LOGIC_VECTOR(g_stat_data_w-1 DOWNTO 0); + + SIGNAL stat_data_re : STD_LOGIC_VECTOR(g_stat_data_w-1 DOWNTO 0); SIGNAL stat_data_im : STD_LOGIC_VECTOR(g_stat_data_w-1 DOWNTO 0); SIGNAL wrdata_re : STD_LOGIC_VECTOR(c_mem_data_w-1 DOWNTO 0); SIGNAL wrdata_im : STD_LOGIC_VECTOR(c_mem_data_w-1 DOWNTO 0); - - SIGNAL stat_mosi : t_mem_mosi; - SIGNAL count : STD_LOGIC_VECTOR(c_nof_stat_w-1 DOWNTO 0); + + -- Sim only signals for observing wrdata_power with indices in Wave window + SIGNAL wrdata_power : REAL; + SIGNAL stat_bin : NATURAL; + + SIGNAL stat_mosi : t_mem_mosi := c_mem_mosi_rst; + + SIGNAL treshold_count : STD_LOGIC_VECTOR(c_nof_stat_w-1 DOWNTO 0); SIGNAL ram_st_sst_mosi_arr : t_mem_mosi_arr(c_nof_complex-1 DOWNTO 0) := (OTHERS => c_mem_mosi_rst); SIGNAL ram_st_sst_miso_arr : t_mem_miso_arr(c_nof_complex-1 DOWNTO 0) := (OTHERS => c_mem_miso_rst); @@ -153,24 +165,23 @@ BEGIN ------------------------------------------------------------------------------ -- Input registers and preparation of the input data for the multiplier. ------------------------------------------------------------------------------ - comb : PROCESS(r, dp_rst, in_complex, count, treshold) + comb : PROCESS(r, dp_rst, in_complex, treshold_count, treshold) VARIABLE v : reg_type; BEGIN v := r; v.in_sosi_reg := in_complex; - IF(count = zeros OR treshold = zeros) THEN + IF treshold_count = zeros OR treshold = zeros THEN v.in_a_re := in_complex.re(g_in_data_w-1 DOWNTO 0); v.in_a_im := in_complex.im(g_in_data_w-1 DOWNTO 0); END IF; - IF(dp_rst = '1') THEN + IF dp_rst = '1' THEN v.in_a_re := (OTHERS => '0'); v.in_a_im := (OTHERS => '0'); END IF; - rin <= v; - + rin <= v; END PROCESS comb; regs : PROCESS(dp_clk) @@ -181,7 +192,7 @@ BEGIN END PROCESS; ------------------------------------------------------------------------------ - -- Counter used to detect when treshold is reached in order to load new + -- Counter used to detect when treshold is reached in order to load new -- input vlaues for the multiplier. ------------------------------------------------------------------------------ treshold_cnt : ENTITY common_lib.common_counter @@ -197,13 +208,13 @@ BEGIN clk => dp_clk, cnt_clr => in_complex.eop, cnt_en => in_complex.valid, - cnt_max => treshold, - count => count + cnt_max => treshold, + count => treshold_count ); in_sync <= in_complex.sync; - st_calc : ENTITY work.st_calc + st_calc : ENTITY work.st_calc GENERIC MAP ( g_technology => g_technology, g_nof_mux => 1, @@ -228,10 +239,19 @@ BEGIN out_val => stat_mosi.wr, out_val_m => OPEN ); - - wrdata_re <= RESIZE_MEM_UDATA(stat_data_re); - wrdata_im <= RESIZE_MEM_UDATA(stat_data_im); - + + -- Auto correlations are unsigned value, cross correlations are signed values + wrdata_re <= RESIZE_MEM_UDATA(stat_data_re) WHEN g_xst_enable=FALSE ELSE RESIZE_MEM_SDATA(stat_data_re); + wrdata_im <= RESIZE_MEM_UDATA(stat_data_im) WHEN g_xst_enable=FALSE ELSE RESIZE_MEM_SDATA(stat_data_im); + + -- synthesis translate_off + -- View SST or XST power values in wave window (stat_data_im = 0 for SST) + wrdata_power <= COMPLEX_RADIUS(TO_SREAL(stat_data_re), TO_SREAL(stat_data_im)) ** 2.0; + + stat_bin <= TO_UINT(stat_mosi.address(c_stat_ram.adr_w-1 DOWNTO 0)) / g_stat_multiplex; + -- synthesis translate_on + + -- For SST or for real part of XST stat_reg_re : ENTITY common_lib.common_ram_crw_crw_ratio GENERIC MAP ( g_technology => g_technology, @@ -261,12 +281,12 @@ BEGIN rd_val_b => OPEN ); - gen_re: IF g_xst_enable=FALSE GENERATE + gen_sst: IF g_xst_enable=FALSE GENERATE ram_st_sst_mosi_arr(0) <= ram_st_sst_mosi; ram_st_sst_miso <= ram_st_sst_miso_arr(0); END GENERATE; - gen_im: IF g_xst_enable=TRUE GENERATE + gen_xst: IF g_xst_enable=TRUE GENERATE --------------------------------------------------------------- -- COMBINE MEMORY MAPPED INTERFACES --------------------------------------------------------------- @@ -284,6 +304,7 @@ BEGIN miso_arr => ram_st_sst_miso_arr ); + -- For imaginary part of XST stat_reg_im : ENTITY common_lib.common_ram_crw_crw_ratio GENERIC MAP ( g_technology => g_technology, @@ -311,8 +332,7 @@ BEGIN rd_en_b => '0', rd_dat_b => OPEN, rd_val_b => OPEN - ); - + ); END GENERATE; -END str; \ No newline at end of file +END str; diff --git a/libraries/dsp/st/src/vhdl/st_xsq.vhd b/libraries/dsp/st/src/vhdl/st_xsq.vhd index 4378a4c7507b12ec38b0467b1f2ac923b9c2f998..89bcd301e434019512d0cd44d4ffe9c57d56ac07 100644 --- a/libraries/dsp/st/src/vhdl/st_xsq.vhd +++ b/libraries/dsp/st/src/vhdl/st_xsq.vhd @@ -27,6 +27,10 @@ -- of the previous sync interval. The length of the sync interval determines -- the nof accumlations per statistic, hence the integration time. See st_calc -- for more details. +-- +-- View wrdata_power and a_sp, b_sp and crosslet_index in Wave window to see +-- the stat power values series. +-- -- Remarks: -- . The in_sync is assumed to be a pulse an interpreted directly. -- . The MM register is single page RAM to save memory resources. Therefore @@ -42,11 +46,13 @@ LIBRARY IEEE, common_lib, mm_lib, technology_lib, dp_lib; USE IEEE.std_logic_1164.ALL; +USE IEEE.math_real.ALL; -- for sim only USE common_lib.common_pkg.ALL; USE common_lib.common_mem_pkg.ALL; USE common_lib.common_field_pkg.ALL; USE dp_lib.dp_stream_pkg.ALL; USE technology_lib.technology_select_pkg.ALL; + ENTITY st_xsq IS GENERIC ( g_nof_signal_inputs : NATURAL := 2; @@ -100,7 +106,14 @@ ARCHITECTURE str OF st_xsq IS SIGNAL wrdata_re : STD_LOGIC_VECTOR(c_mem_data_w-1 DOWNTO 0); SIGNAL wrdata_im : STD_LOGIC_VECTOR(c_mem_data_w-1 DOWNTO 0); - + + -- Sim only signals for observing wrdata_power with indices in Wave window + SIGNAL wrdata_power : REAL; + SIGNAL stat_index : NATURAL; + SIGNAL a_sp : NATURAL; + SIGNAL b_sp : NATURAL; + SIGNAL crosslet_index : NATURAL; + SIGNAL stat_mosi : t_mem_mosi := c_mem_mosi_rst; SIGNAL ram_st_xsq_mosi_arr : t_mem_mosi_arr(c_nof_complex-1 DOWNTO 0) := (OTHERS => c_mem_mosi_rst); @@ -165,9 +178,20 @@ BEGIN out_val_m => OPEN ); - wrdata_re <= RESIZE_MEM_UDATA(stat_data_re); - wrdata_im <= RESIZE_MEM_UDATA(stat_data_im); + -- Cross correlations are signed values + wrdata_re <= RESIZE_MEM_SDATA(stat_data_re); + wrdata_im <= RESIZE_MEM_SDATA(stat_data_im); + -- synthesis translate_off + wrdata_power <= COMPLEX_RADIUS(TO_SREAL(stat_data_re), TO_SREAL(stat_data_im)) ** 2.0; + + -- Indices for statistics [crosslets][in A][in B] + stat_index <= TO_UINT(stat_mosi.address(c_stat_ram.adr_w-1 DOWNTO 0)); + a_sp <= (stat_index / g_nof_signal_inputs) MOD g_nof_signal_inputs; + b_sp <= stat_index MOD g_nof_signal_inputs; + crosslet_index <= stat_index / c_xsq; + -- synthesis translate_on + --------------------------------------------------------------- -- COMBINE MEMORY MAPPED INTERFACES ---------------------------------------------------------------