diff --git a/applications/lofar2/designs/lofar2_unb2b_sdp_station/lofar2_unb2b_sdp_station.fpga.yaml b/applications/lofar2/designs/lofar2_unb2b_sdp_station/lofar2_unb2b_sdp_station.fpga.yaml index 35ca819e6d42eb2f958e072ed62251d636cd526d..80766f3196f427ce134a766ca36eeccbb897c65e 100644 --- a/applications/lofar2/designs/lofar2_unb2b_sdp_station/lofar2_unb2b_sdp_station.fpga.yaml +++ b/applications/lofar2/designs/lofar2_unb2b_sdp_station/lofar2_unb2b_sdp_station.fpga.yaml @@ -204,27 +204,27 @@ peripherals: mm_port_names: - REG_STAT_HDR_DAT_SST -# ############################################################################# -# # Xsub = Subband Correlator (from node_sdp_correlator.vhd) -# ############################################################################# -# -# - peripheral_name: dp/dp_bsn_scheduler -# peripheral_group: xsub -# mm_port_names: -# - REG_BSN_SCHEDULER_XSUB -# -# - peripheral_name: dp/dp_sync_insert_v2 -# mm_port_names: -# - REG_DP_SYNC_INSERT_V2 -# -# - peripheral_name: st/st_xst -# mm_port_names: -# - RAM_ST_XSQ -# -# - peripheral_name: sdp/sdp_crosslets_subband_select -# mm_port_names: -# - REG_CROSSLETS_INFO -# + ############################################################################# + # Xsub = Subband Correlator (from node_sdp_correlator.vhd) + ############################################################################# + + - peripheral_name: dp/dp_bsn_scheduler + peripheral_group: xsub + mm_port_names: + - REG_BSN_SCHEDULER_XSUB + + - peripheral_name: dp/dp_sync_insert_v2 + mm_port_names: + - REG_DP_SYNC_INSERT_V2 + + - peripheral_name: st/st_xst_for_sdp + mm_port_names: + - RAM_ST_XSQ + + - peripheral_name: sdp/sdp_crosslets_subband_select + mm_port_names: + - REG_CROSSLETS_INFO + ############################################################################# # BF = Beamformer (from node_sdp_beamformer.vhd) ############################################################################# diff --git a/applications/lofar2/designs/lofar2_unb2b_sdp_station/quartus/lofar2_unb2b_sdp_station.sdc b/applications/lofar2/designs/lofar2_unb2b_sdp_station/quartus/lofar2_unb2b_sdp_station.sdc index a041aae6d83c1972821b3e27f333568006a8c93e..82c0df011c95f6503ba618f2fbe419b37c5765ab 100644 --- a/applications/lofar2/designs/lofar2_unb2b_sdp_station/quartus/lofar2_unb2b_sdp_station.sdc +++ b/applications/lofar2/designs/lofar2_unb2b_sdp_station/quartus/lofar2_unb2b_sdp_station.sdc @@ -97,8 +97,8 @@ set_clock_groups -asynchronous -group [get_clocks {*xcvr_native_a10_0|g_xcvr_nat #-group [get_clocks {inst2|xcvr_4ch_native_phy_inst|xcvr_native_a10_0|g_xcvr_native_insts[?]|rx_pma_clk}] \ #-group [get_clocks {inst2|xcvr_pll_inst|xcvr_fpll_a10_0|tx_bonding_clocks[0]}] -# false paths added for the jesd test design -set_false_path -from [get_clocks {*xcvr_fpll_a10_0|outclk2}] -to [get_clocks {*core_pll|link_clk}] -set_false_path -from [get_clocks {*core_pll|link_clk}] -to [get_clocks {*xcvr_fpll_a10_0|outclk2}] -set_false_path -from [get_clocks {*xcvr_fpll_a10_0|outclk2}] -to [get_clocks {*core_pll|frame_clk}] -set_false_path -from [get_clocks {*core_pll|frame_clk}] -to [get_clocks {*xcvr_fpll_a10_0|outclk2}] +# false paths added for the jesd interface as these clocks are independent. +set_false_path -from [get_clocks {*xcvr_fpll_a10_0|outclk2}] -to [get_clocks {*iopll_0|link_clk}] +set_false_path -from [get_clocks {*iopll_0|link_clk}] -to [get_clocks {*xcvr_fpll_a10_0|outclk2}] +set_false_path -from [get_clocks {*xcvr_fpll_a10_0|outclk2}] -to [get_clocks {*iopll_0|frame_clk}] +set_false_path -from [get_clocks {*iopll_0|frame_clk}] -to [get_clocks {*xcvr_fpll_a10_0|outclk2}] diff --git a/applications/lofar2/libraries/sdp/sdp.peripheral.yaml b/applications/lofar2/libraries/sdp/sdp.peripheral.yaml index d4b798dea57721a7e72ffd009397235d6e6ae11b..66cc0cc8cc6071bfb160780ab3c8db14694e8a7e 100644 --- a/applications/lofar2/libraries/sdp/sdp.peripheral.yaml +++ b/applications/lofar2/libraries/sdp/sdp.peripheral.yaml @@ -6,7 +6,7 @@ hdl_library_name: sdp hdl_library_description: "Station Digital Processor (SDP) for LOFAR2.0" peripherals: - - peripheral_name: sdp_info # pi_sdp_info.py ? + - peripheral_name: sdp_info # pi_sdp_info.py peripheral_description: "SDP info." mm_ports: # MM port for sdp_info.vhd @@ -32,6 +32,23 @@ peripherals: - - { field_name: block_period, mm_width: 16, access_mode: RO, address_offset: 0x4 } - - { field_name: beamlet_scale, mm_width: 16, access_mode: RW, address_offset: 0x0 } + + - peripheral_name: sdp_crosslets_subband_select # pi_sdp_crosslets_info.py + peripheral_description: "SDP crosslets info." + mm_ports: + # MM port for sdp_info.vhd + - mm_port_name: REG_CROSSLETS_INFO + mm_port_type: REG + mm_port_description: | + "The SDP crosslets info contains the step size and 15 offsets, that are used to select a new + crosslet subband for every integration interval" + fields: + - - { field_name: step, access_mode: RW, address_offset: 0x3C } + - - field_name: offset + number_of_fields: 15 + address_offset: 0x0 + + - peripheral_name: sdp_subband_equalizer # pi_sdp_subband_equalizer.py peripheral_description: "SDP Subband equalizer coefficients." parameters: diff --git a/applications/lofar2/libraries/sdp/src/vhdl/node_sdp_adc_input_and_timing.vhd b/applications/lofar2/libraries/sdp/src/vhdl/node_sdp_adc_input_and_timing.vhd index ab3d08b91f394964b07440c87d29a487bbe350b4..ae271ee613332fceee60cd871908b4d6690bd0a9 100644 --- a/applications/lofar2/libraries/sdp/src/vhdl/node_sdp_adc_input_and_timing.vhd +++ b/applications/lofar2/libraries/sdp/src/vhdl/node_sdp_adc_input_and_timing.vhd @@ -18,7 +18,7 @@ -- ------------------------------------------------------------------------------- --- Authors : J Hargreaves, L Hiemstra +-- Authors : J Hargreaves, L Hiemstra, R van der Walle -- Purpose: -- AIT - ADC (Jesd) receiver, input, timing and associated diagnostic blocks -- Description: @@ -124,7 +124,6 @@ ARCHITECTURE str OF node_sdp_adc_input_and_timing IS SIGNAL rx_rst : STD_LOGIC; SIGNAL rx_sysref : STD_LOGIC; - SIGNAL arst : STD_LOGIC; SIGNAL rx_bsn_source_restart : STD_LOGIC; -- Sosis and sosi arrays @@ -213,7 +212,7 @@ BEGIN GENERIC MAP ( g_nof_streams => c_sdp_S_pn, g_nof_words => c_sdp_V_sample_delay, - g_data_w => c_sdp_W_adc_jesd, + g_data_w => c_sdp_W_adc, g_use_sync_in => TRUE ) PORT MAP ( @@ -393,7 +392,7 @@ BEGIN GENERIC MAP ( g_cross_clock_domain => TRUE, g_nof_streams => c_sdp_S_pn, - g_symbol_w => c_sdp_W_adc_jesd, + g_symbol_w => c_sdp_W_adc, g_nof_symbols_per_data => 1, -- Wideband factor is 1 g_nof_accumulations => g_bsn_nof_clk_per_sync ) @@ -423,7 +422,7 @@ BEGIN GENERIC MAP ( g_technology => g_technology, g_nof_streams => c_sdp_S_pn, - g_data_w => c_sdp_W_adc_jesd, + g_data_w => c_sdp_W_adc, g_buf_nof_data => g_buf_nof_data, g_buf_use_sync => TRUE -- when TRUE start filling the buffer at the in_sync, else after the last word was read ) @@ -447,47 +446,31 @@ BEGIN -- Output Stage -- . Thin dual clock fifo to cross from jesd frame clock (rx_clk) to dp_clk domain ----------------------------------------------------------------------------- - - gen_dp_fifo_dc : FOR I IN 0 TO c_sdp_S_pn-1 GENERATE - u_dp_fifo_dc : ENTITY dp_lib.dp_fifo_dc - GENERIC MAP ( - g_data_w => c_sdp_W_adc_jesd, - g_bsn_w => c_bs_bsn_w, - g_use_empty => FALSE, --TRUE, - g_use_ctrl => TRUE, - g_use_sync => TRUE, - g_use_bsn => TRUE, - g_fifo_size => c_dp_fifo_dc_size - ) - PORT MAP ( - wr_rst => rx_rst, - wr_clk => rx_clk, - rd_rst => dp_rst, - rd_clk => dp_clk, - snk_in => st_sosi_arr(I), - src_out => out_sosi_arr(I) - ); - END GENERATE; - - -- use common dc fifo for restart signal - u_common_fifo_dc_restart : ENTITY common_lib.common_fifo_dc - GENERIC MAP ( - g_dat_w => 1, - g_nof_words => c_dp_fifo_dc_size - ) - PORT MAP ( - rst => arst, - wr_clk => rx_clk, - wr_dat(0) => rx_bsn_source_restart, - wr_req => bs_sosi.valid, - rd_clk => dp_clk, - rd_dat(0) => dp_bsn_source_restart, - rd_req => '1' - ); - - arst <= rx_rst OR dp_rst; + u_dp_fifo_dc_arr : ENTITY dp_lib.dp_fifo_dc_arr + GENERIC MAP ( + g_nof_streams => c_sdp_S_pn, + g_data_w => c_sdp_W_adc, + g_bsn_w => c_bs_bsn_w, + g_use_empty => FALSE, + g_use_ctrl => TRUE, + g_use_sync => TRUE, + g_use_bsn => TRUE, + g_use_aux => TRUE, + g_fifo_size => c_dp_fifo_dc_size + ) + PORT MAP ( + wr_rst => rx_rst, + wr_clk => rx_clk, + rd_rst => dp_rst, + rd_clk => dp_clk, + snk_in_arr => st_sosi_arr, + src_out_arr => out_sosi_arr, + in_aux(0) => rx_bsn_source_restart, + out_aux(0) => dp_bsn_source_restart + ); - ----------------------------------------------------------------------------- + +----------------------------------------------------------------------------- -- JESD Control register ----------------------------------------------------------------------------- u_mm_jesd_ctrl_reg : ENTITY common_lib.common_reg_r_w 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 69356104b26cf09270a30ac75a2be71193b51ce8..a30bf342f7766974952a2bc51bdb9824b95d587d 100644 --- a/applications/lofar2/libraries/sdp/src/vhdl/node_sdp_filterbank.vhd +++ b/applications/lofar2/libraries/sdp/src/vhdl/node_sdp_filterbank.vhd @@ -181,7 +181,8 @@ BEGIN g_use_prefilter => TRUE, g_stats_ena => FALSE, g_use_bg => FALSE, - g_coefs_file_prefix => c_coefs_file_prefix + g_coefs_file_prefix => c_coefs_file_prefix, + g_restart_on_valid => FALSE ) PORT MAP ( dp_rst => dp_rst, 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 5400b70e891a44d1835da0be6150ebb100f02824..6186496de7639b08c7c70444aa041e917c994603 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 @@ -167,6 +167,7 @@ BEGIN BEGIN v := r; v.col_select_mosi := c_mem_mosi_rst; + v_offsets := r.offsets; -- start/restart IF start_trigger = '1' THEN diff --git a/libraries/base/common/src/vhdl/common_pkg.vhd b/libraries/base/common/src/vhdl/common_pkg.vhd index 79591b0b305fbab6107ee2acb05afe6e709a73ef..ba09970a6f98b5f6896ef7036894ca27fa5b024f 100644 --- a/libraries/base/common/src/vhdl/common_pkg.vhd +++ b/libraries/base/common/src/vhdl/common_pkg.vhd @@ -325,36 +325,42 @@ PACKAGE common_pkg IS -- . Note that using func_slv_concat() without the BOOLEAN use_* is equivalent to using the -- slv concatenation operator & directly. However this overloaded func_slv_concat() is -- still nice to have, because it shows the relation with the inverse func_slv_extract(). - FUNCTION func_slv_concat( use_a, use_b, use_c, use_d, use_e, use_f, use_g : BOOLEAN; a, b, c, d, e, f, g : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR; - FUNCTION func_slv_concat( use_a, use_b, use_c, use_d, use_e, use_f : BOOLEAN; a, b, c, d, e, f : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR; - FUNCTION func_slv_concat( use_a, use_b, use_c, use_d, use_e : BOOLEAN; a, b, c, d, e : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR; - FUNCTION func_slv_concat( use_a, use_b, use_c, use_d : BOOLEAN; a, b, c, d : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR; - FUNCTION func_slv_concat( use_a, use_b, use_c : BOOLEAN; a, b, c : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR; - FUNCTION func_slv_concat( use_a, use_b : BOOLEAN; a, b : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR; - FUNCTION func_slv_concat( a, b, c, d, e, f, g : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR; - FUNCTION func_slv_concat( a, b, c, d, e, f : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR; - FUNCTION func_slv_concat( a, b, c, d, e : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR; - FUNCTION func_slv_concat( a, b, c, d : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR; - FUNCTION func_slv_concat( a, b, c : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR; - FUNCTION func_slv_concat( a, b : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR; - FUNCTION func_slv_concat_w(use_a, use_b, use_c, use_d, use_e, use_f, use_g : BOOLEAN; a_w, b_w, c_w, d_w, e_w, f_w, g_w : NATURAL) RETURN NATURAL; - FUNCTION func_slv_concat_w(use_a, use_b, use_c, use_d, use_e, use_f : BOOLEAN; a_w, b_w, c_w, d_w, e_w, f_w : NATURAL) RETURN NATURAL; - FUNCTION func_slv_concat_w(use_a, use_b, use_c, use_d, use_e : BOOLEAN; a_w, b_w, c_w, d_w, e_w : NATURAL) RETURN NATURAL; - FUNCTION func_slv_concat_w(use_a, use_b, use_c, use_d : BOOLEAN; a_w, b_w, c_w, d_w : NATURAL) RETURN NATURAL; - FUNCTION func_slv_concat_w(use_a, use_b, use_c : BOOLEAN; a_w, b_w, c_w : NATURAL) RETURN NATURAL; - FUNCTION func_slv_concat_w(use_a, use_b : BOOLEAN; a_w, b_w : NATURAL) RETURN NATURAL; - FUNCTION func_slv_extract( use_a, use_b, use_c, use_d, use_e, use_f, use_g : BOOLEAN; a_w, b_w, c_w, d_w, e_w, f_w, g_w : NATURAL; vec : STD_LOGIC_VECTOR; sel : NATURAL) RETURN STD_LOGIC_VECTOR; - FUNCTION func_slv_extract( use_a, use_b, use_c, use_d, use_e, use_f : BOOLEAN; a_w, b_w, c_w, d_w, e_w, f_w : NATURAL; vec : STD_LOGIC_VECTOR; sel : NATURAL) RETURN STD_LOGIC_VECTOR; - FUNCTION func_slv_extract( use_a, use_b, use_c, use_d, use_e : BOOLEAN; a_w, b_w, c_w, d_w, e_w : NATURAL; vec : STD_LOGIC_VECTOR; sel : NATURAL) RETURN STD_LOGIC_VECTOR; - FUNCTION func_slv_extract( use_a, use_b, use_c, use_d : BOOLEAN; a_w, b_w, c_w, d_w : NATURAL; vec : STD_LOGIC_VECTOR; sel : NATURAL) RETURN STD_LOGIC_VECTOR; - FUNCTION func_slv_extract( use_a, use_b, use_c : BOOLEAN; a_w, b_w, c_w : NATURAL; vec : STD_LOGIC_VECTOR; sel : NATURAL) RETURN STD_LOGIC_VECTOR; - FUNCTION func_slv_extract( use_a, use_b : BOOLEAN; a_w, b_w : NATURAL; vec : STD_LOGIC_VECTOR; sel : NATURAL) RETURN STD_LOGIC_VECTOR; - FUNCTION func_slv_extract( a_w, b_w, c_w, d_w, e_w, f_w, g_w : NATURAL; vec : STD_LOGIC_VECTOR; sel : NATURAL) RETURN STD_LOGIC_VECTOR; - FUNCTION func_slv_extract( a_w, b_w, c_w, d_w, e_w, f_w : NATURAL; vec : STD_LOGIC_VECTOR; sel : NATURAL) RETURN STD_LOGIC_VECTOR; - FUNCTION func_slv_extract( a_w, b_w, c_w, d_w, e_w : NATURAL; vec : STD_LOGIC_VECTOR; sel : NATURAL) RETURN STD_LOGIC_VECTOR; - FUNCTION func_slv_extract( a_w, b_w, c_w, d_w : NATURAL; vec : STD_LOGIC_VECTOR; sel : NATURAL) RETURN STD_LOGIC_VECTOR; - FUNCTION func_slv_extract( a_w, b_w, c_w : NATURAL; vec : STD_LOGIC_VECTOR; sel : NATURAL) RETURN STD_LOGIC_VECTOR; - FUNCTION func_slv_extract( a_w, b_w : NATURAL; vec : STD_LOGIC_VECTOR; sel : NATURAL) RETURN STD_LOGIC_VECTOR; + + FUNCTION func_slv_concat( use_a, use_b, use_c, use_d, use_e, use_f, use_g, use_h : BOOLEAN; a, b, c, d, e, f, g, h : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR; + FUNCTION func_slv_concat( use_a, use_b, use_c, use_d, use_e, use_f, use_g : BOOLEAN; a, b, c, d, e, f, g : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR; + FUNCTION func_slv_concat( use_a, use_b, use_c, use_d, use_e, use_f : BOOLEAN; a, b, c, d, e, f : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR; + FUNCTION func_slv_concat( use_a, use_b, use_c, use_d, use_e : BOOLEAN; a, b, c, d, e : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR; + FUNCTION func_slv_concat( use_a, use_b, use_c, use_d : BOOLEAN; a, b, c, d : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR; + FUNCTION func_slv_concat( use_a, use_b, use_c : BOOLEAN; a, b, c : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR; + FUNCTION func_slv_concat( use_a, use_b : BOOLEAN; a, b : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR; + FUNCTION func_slv_concat( a, b, c, d, e, f, g, h : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR; + FUNCTION func_slv_concat( a, b, c, d, e, f, g : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR; + FUNCTION func_slv_concat( a, b, c, d, e, f : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR; + FUNCTION func_slv_concat( a, b, c, d, e : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR; + FUNCTION func_slv_concat( a, b, c, d : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR; + FUNCTION func_slv_concat( a, b, c : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR; + FUNCTION func_slv_concat( a, b : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR; + FUNCTION func_slv_concat_w(use_a, use_b, use_c, use_d, use_e, use_f, use_g, use_h : BOOLEAN; a_w, b_w, c_w, d_w, e_w, f_w, g_w, h_w : NATURAL) RETURN NATURAL; + FUNCTION func_slv_concat_w(use_a, use_b, use_c, use_d, use_e, use_f, use_g : BOOLEAN; a_w, b_w, c_w, d_w, e_w, f_w, g_w : NATURAL) RETURN NATURAL; + FUNCTION func_slv_concat_w(use_a, use_b, use_c, use_d, use_e, use_f : BOOLEAN; a_w, b_w, c_w, d_w, e_w, f_w : NATURAL) RETURN NATURAL; + FUNCTION func_slv_concat_w(use_a, use_b, use_c, use_d, use_e : BOOLEAN; a_w, b_w, c_w, d_w, e_w : NATURAL) RETURN NATURAL; + FUNCTION func_slv_concat_w(use_a, use_b, use_c, use_d : BOOLEAN; a_w, b_w, c_w, d_w : NATURAL) RETURN NATURAL; + FUNCTION func_slv_concat_w(use_a, use_b, use_c : BOOLEAN; a_w, b_w, c_w : NATURAL) RETURN NATURAL; + FUNCTION func_slv_concat_w(use_a, use_b : BOOLEAN; a_w, b_w : NATURAL) RETURN NATURAL; + FUNCTION func_slv_extract( use_a, use_b, use_c, use_d, use_e, use_f, use_g, use_h : BOOLEAN; a_w, b_w, c_w, d_w, e_w, f_w, g_w, h_w : NATURAL; vec : STD_LOGIC_VECTOR; sel : NATURAL) RETURN STD_LOGIC_VECTOR; + FUNCTION func_slv_extract( use_a, use_b, use_c, use_d, use_e, use_f, use_g : BOOLEAN; a_w, b_w, c_w, d_w, e_w, f_w, g_w : NATURAL; vec : STD_LOGIC_VECTOR; sel : NATURAL) RETURN STD_LOGIC_VECTOR; + FUNCTION func_slv_extract( use_a, use_b, use_c, use_d, use_e, use_f : BOOLEAN; a_w, b_w, c_w, d_w, e_w, f_w : NATURAL; vec : STD_LOGIC_VECTOR; sel : NATURAL) RETURN STD_LOGIC_VECTOR; + FUNCTION func_slv_extract( use_a, use_b, use_c, use_d, use_e : BOOLEAN; a_w, b_w, c_w, d_w, e_w : NATURAL; vec : STD_LOGIC_VECTOR; sel : NATURAL) RETURN STD_LOGIC_VECTOR; + FUNCTION func_slv_extract( use_a, use_b, use_c, use_d : BOOLEAN; a_w, b_w, c_w, d_w : NATURAL; vec : STD_LOGIC_VECTOR; sel : NATURAL) RETURN STD_LOGIC_VECTOR; + FUNCTION func_slv_extract( use_a, use_b, use_c : BOOLEAN; a_w, b_w, c_w : NATURAL; vec : STD_LOGIC_VECTOR; sel : NATURAL) RETURN STD_LOGIC_VECTOR; + FUNCTION func_slv_extract( use_a, use_b : BOOLEAN; a_w, b_w : NATURAL; vec : STD_LOGIC_VECTOR; sel : NATURAL) RETURN STD_LOGIC_VECTOR; + FUNCTION func_slv_extract( a_w, b_w, c_w, d_w, e_w, f_w, g_w, h_w : NATURAL; vec : STD_LOGIC_VECTOR; sel : NATURAL) RETURN STD_LOGIC_VECTOR; + FUNCTION func_slv_extract( a_w, b_w, c_w, d_w, e_w, f_w, g_w : NATURAL; vec : STD_LOGIC_VECTOR; sel : NATURAL) RETURN STD_LOGIC_VECTOR; + FUNCTION func_slv_extract( a_w, b_w, c_w, d_w, e_w, f_w : NATURAL; vec : STD_LOGIC_VECTOR; sel : NATURAL) RETURN STD_LOGIC_VECTOR; + FUNCTION func_slv_extract( a_w, b_w, c_w, d_w, e_w : NATURAL; vec : STD_LOGIC_VECTOR; sel : NATURAL) RETURN STD_LOGIC_VECTOR; + FUNCTION func_slv_extract( a_w, b_w, c_w, d_w : NATURAL; vec : STD_LOGIC_VECTOR; sel : NATURAL) RETURN STD_LOGIC_VECTOR; + FUNCTION func_slv_extract( a_w, b_w, c_w : NATURAL; vec : STD_LOGIC_VECTOR; sel : NATURAL) RETURN STD_LOGIC_VECTOR; + FUNCTION func_slv_extract( a_w, b_w : NATURAL; vec : STD_LOGIC_VECTOR; sel : NATURAL) RETURN STD_LOGIC_VECTOR; FUNCTION TO_UINT(vec : STD_LOGIC_VECTOR) RETURN NATURAL; -- beware: NATURAL'HIGH = 2**31-1, not 2*32-1, use TO_SINT to avoid warning FUNCTION TO_SINT(vec : STD_LOGIC_VECTOR) RETURN INTEGER; @@ -1508,10 +1514,9 @@ PACKAGE BODY common_pkg IS RETURN v_mat; END; - - -- Support concatenation of up to 7 slv into 1 slv - FUNCTION func_slv_concat(use_a, use_b, use_c, use_d, use_e, use_f, use_g : BOOLEAN; a, b, c, d, e, f, g : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR IS - CONSTANT c_max_w : NATURAL := a'LENGTH + b'LENGTH + c'LENGTH + d'LENGTH + e'LENGTH + f'LENGTH + g'LENGTH; + -- Support concatenation of up to 8 slv into 1 slv + FUNCTION func_slv_concat(use_a, use_b, use_c, use_d, use_e, use_f, use_g, use_h : BOOLEAN; a, b, c, d, e, f, g, h : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR IS + CONSTANT c_max_w : NATURAL := a'LENGTH + b'LENGTH + c'LENGTH + d'LENGTH + e'LENGTH + f'LENGTH + g'LENGTH + h'LENGTH; VARIABLE v_res : STD_LOGIC_VECTOR(c_max_w-1 DOWNTO 0) := (OTHERS=>'0'); VARIABLE v_len : NATURAL := 0; BEGIN @@ -1522,34 +1527,45 @@ PACKAGE BODY common_pkg IS IF use_e = TRUE THEN v_res(e'LENGTH-1 + v_len DOWNTO v_len) := e; v_len := v_len + e'LENGTH; END IF; IF use_f = TRUE THEN v_res(f'LENGTH-1 + v_len DOWNTO v_len) := f; v_len := v_len + f'LENGTH; END IF; IF use_g = TRUE THEN v_res(g'LENGTH-1 + v_len DOWNTO v_len) := g; v_len := v_len + g'LENGTH; END IF; + IF use_h = TRUE THEN v_res(h'LENGTH-1 + v_len DOWNTO v_len) := h; v_len := v_len + h'LENGTH; END IF; RETURN v_res(v_len-1 DOWNTO 0); END func_slv_concat; - + + FUNCTION func_slv_concat(use_a, use_b, use_c, use_d, use_e, use_f, use_g : BOOLEAN; a, b, c, d, e, f, g : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR IS + BEGIN + RETURN func_slv_concat(use_a, use_b, use_c, use_d, use_e, use_f, use_g, FALSE, a, b, c, d, e, f, g, "0"); + END func_slv_concat; + FUNCTION func_slv_concat(use_a, use_b, use_c, use_d, use_e, use_f : BOOLEAN; a, b, c, d, e, f : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR IS BEGIN - RETURN func_slv_concat(use_a, use_b, use_c, use_d, use_e, use_f, FALSE, a, b, c, d, e, f, "0"); + RETURN func_slv_concat(use_a, use_b, use_c, use_d, use_e, use_f, FALSE, FALSE, a, b, c, d, e, f, "0", "0"); END func_slv_concat; FUNCTION func_slv_concat(use_a, use_b, use_c, use_d, use_e : BOOLEAN; a, b, c, d, e : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR IS BEGIN - RETURN func_slv_concat(use_a, use_b, use_c, use_d, use_e, FALSE, FALSE, a, b, c, d, e, "0", "0"); + RETURN func_slv_concat(use_a, use_b, use_c, use_d, use_e, FALSE, FALSE, FALSE, a, b, c, d, e, "0", "0", "0"); END func_slv_concat; FUNCTION func_slv_concat(use_a, use_b, use_c, use_d : BOOLEAN; a, b, c, d : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR IS BEGIN - RETURN func_slv_concat(use_a, use_b, use_c, use_d, FALSE, FALSE, FALSE, a, b, c, d, "0", "0", "0"); + RETURN func_slv_concat(use_a, use_b, use_c, use_d, FALSE, FALSE, FALSE, FALSE, a, b, c, d, "0", "0", "0", "0"); END func_slv_concat; FUNCTION func_slv_concat(use_a, use_b, use_c : BOOLEAN; a, b, c : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR IS BEGIN - RETURN func_slv_concat(use_a, use_b, use_c, FALSE, FALSE, FALSE, FALSE, a, b, c, "0", "0", "0", "0"); + RETURN func_slv_concat(use_a, use_b, use_c, FALSE, FALSE, FALSE, FALSE, FALSE, a, b, c, "0", "0", "0", "0", "0"); END func_slv_concat; FUNCTION func_slv_concat(use_a, use_b : BOOLEAN; a, b : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR IS BEGIN - RETURN func_slv_concat(use_a, use_b, FALSE, FALSE, FALSE, FALSE, FALSE, a, b, "0", "0", "0", "0", "0"); + RETURN func_slv_concat(use_a, use_b, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, a, b, "0", "0", "0", "0", "0", "0"); END func_slv_concat; - + + FUNCTION func_slv_concat(a, b, c, d, e, f, g, h : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR IS + BEGIN + RETURN func_slv_concat(TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, a, b, c, d, e, f, g, h); + END func_slv_concat; + FUNCTION func_slv_concat(a, b, c, d, e, f, g : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR IS BEGIN RETURN func_slv_concat(TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, a, b, c, d, e, f, g); @@ -1580,7 +1596,7 @@ PACKAGE BODY common_pkg IS RETURN func_slv_concat(TRUE, TRUE, a, b); END func_slv_concat; - FUNCTION func_slv_concat_w(use_a, use_b, use_c, use_d, use_e, use_f, use_g : BOOLEAN; a_w, b_w, c_w, d_w, e_w, f_w, g_w : NATURAL) RETURN NATURAL IS + FUNCTION func_slv_concat_w(use_a, use_b, use_c, use_d, use_e, use_f, use_g, use_h : BOOLEAN; a_w, b_w, c_w, d_w, e_w, f_w, g_w, h_w : NATURAL) RETURN NATURAL IS VARIABLE v_len : NATURAL := 0; BEGIN IF use_a = TRUE THEN v_len := v_len + a_w; END IF; @@ -1590,36 +1606,42 @@ PACKAGE BODY common_pkg IS IF use_e = TRUE THEN v_len := v_len + e_w; END IF; IF use_f = TRUE THEN v_len := v_len + f_w; END IF; IF use_g = TRUE THEN v_len := v_len + g_w; END IF; + IF use_h = TRUE THEN v_len := v_len + h_w; END IF; RETURN v_len; END func_slv_concat_w; - + + FUNCTION func_slv_concat_w(use_a, use_b, use_c, use_d, use_e, use_f, use_g : BOOLEAN; a_w, b_w, c_w, d_w, e_w, f_w, g_w : NATURAL) RETURN NATURAL IS + BEGIN + RETURN func_slv_concat_w(use_a, use_b, use_c, use_d, use_e, use_f, use_g, FALSE, a_w, b_w, c_w, d_w, e_w, f_w, g_w, 0); + END func_slv_concat_w; + FUNCTION func_slv_concat_w(use_a, use_b, use_c, use_d, use_e, use_f : BOOLEAN; a_w, b_w, c_w, d_w, e_w, f_w : NATURAL) RETURN NATURAL IS BEGIN - RETURN func_slv_concat_w(use_a, use_b, use_c, use_d, use_e, use_f, FALSE, a_w, b_w, c_w, d_w, e_w, f_w, 0); + RETURN func_slv_concat_w(use_a, use_b, use_c, use_d, use_e, use_f, FALSE, FALSE, a_w, b_w, c_w, d_w, e_w, f_w, 0, 0); END func_slv_concat_w; FUNCTION func_slv_concat_w(use_a, use_b, use_c, use_d, use_e : BOOLEAN; a_w, b_w, c_w, d_w, e_w : NATURAL) RETURN NATURAL IS BEGIN - RETURN func_slv_concat_w(use_a, use_b, use_c, use_d, use_e, FALSE, FALSE, a_w, b_w, c_w, d_w, e_w, 0, 0); + RETURN func_slv_concat_w(use_a, use_b, use_c, use_d, use_e, FALSE, FALSE, FALSE, a_w, b_w, c_w, d_w, e_w, 0, 0, 0); END func_slv_concat_w; FUNCTION func_slv_concat_w(use_a, use_b, use_c, use_d : BOOLEAN; a_w, b_w, c_w, d_w : NATURAL) RETURN NATURAL IS BEGIN - RETURN func_slv_concat_w(use_a, use_b, use_c, use_d, FALSE, FALSE, FALSE, a_w, b_w, c_w, d_w, 0, 0, 0); + RETURN func_slv_concat_w(use_a, use_b, use_c, use_d, FALSE, FALSE, FALSE, FALSE, a_w, b_w, c_w, d_w, 0, 0, 0, 0); END func_slv_concat_w; FUNCTION func_slv_concat_w(use_a, use_b, use_c : BOOLEAN; a_w, b_w, c_w : NATURAL) RETURN NATURAL IS BEGIN - RETURN func_slv_concat_w(use_a, use_b, use_c, FALSE, FALSE, FALSE, FALSE, a_w, b_w, c_w, 0, 0, 0, 0); + RETURN func_slv_concat_w(use_a, use_b, use_c, FALSE, FALSE, FALSE, FALSE, FALSE, a_w, b_w, c_w, 0, 0, 0, 0, 0); END func_slv_concat_w; FUNCTION func_slv_concat_w(use_a, use_b : BOOLEAN; a_w, b_w : NATURAL) RETURN NATURAL IS BEGIN - RETURN func_slv_concat_w(use_a, use_b, FALSE, FALSE, FALSE, FALSE, FALSE, a_w, b_w, 0, 0, 0, 0, 0); + RETURN func_slv_concat_w(use_a, use_b, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, a_w, b_w, 0, 0, 0, 0, 0, 0); END func_slv_concat_w; - + -- extract slv - FUNCTION func_slv_extract(use_a, use_b, use_c, use_d, use_e, use_f, use_g : BOOLEAN; a_w, b_w, c_w, d_w, e_w, f_w, g_w : NATURAL; vec : STD_LOGIC_VECTOR; sel : NATURAL) RETURN STD_LOGIC_VECTOR IS + FUNCTION func_slv_extract(use_a, use_b, use_c, use_d, use_e, use_f, use_g, use_h : BOOLEAN; a_w, b_w, c_w, d_w, e_w, f_w, g_w, h_w : NATURAL; vec : STD_LOGIC_VECTOR; sel : NATURAL) RETURN STD_LOGIC_VECTOR IS VARIABLE v_w : NATURAL := 0; VARIABLE v_lo : NATURAL := 0; BEGIN @@ -1660,36 +1682,55 @@ PACKAGE BODY common_pkg IS IF use_d = TRUE THEN v_lo := v_lo + d_w; END IF; IF use_e = TRUE THEN v_lo := v_lo + e_w; END IF; IF use_f = TRUE THEN v_lo := v_lo + f_w; END IF; + WHEN 7 => + IF use_h = TRUE THEN v_w := h_w; ELSE RETURN c_slv0(h_w-1 DOWNTO 0); END IF; + IF use_a = TRUE THEN v_lo := v_lo + a_w; END IF; + IF use_b = TRUE THEN v_lo := v_lo + b_w; END IF; + IF use_c = TRUE THEN v_lo := v_lo + c_w; END IF; + IF use_d = TRUE THEN v_lo := v_lo + d_w; END IF; + IF use_e = TRUE THEN v_lo := v_lo + e_w; END IF; + IF use_f = TRUE THEN v_lo := v_lo + f_w; END IF; + IF use_g = TRUE THEN v_lo := v_lo + g_w; END IF; WHEN OTHERS => REPORT "Unknown common_pkg func_slv_extract argument" SEVERITY FAILURE; END CASE; RETURN vec(v_w-1 + v_lo DOWNTO v_lo); -- extracted slv END func_slv_extract; - + + FUNCTION func_slv_extract(use_a, use_b, use_c, use_d, use_e, use_f, use_g : BOOLEAN; a_w, b_w, c_w, d_w, e_w, f_w, g_w : NATURAL; vec : STD_LOGIC_VECTOR; sel : NATURAL) RETURN STD_LOGIC_VECTOR IS + BEGIN + RETURN func_slv_extract(use_a, use_b, use_c, use_d, use_e, use_f, use_g, FALSE, a_w, b_w, c_w, d_w, e_w, f_w, g_w, 0, vec, sel); + END func_slv_extract; + FUNCTION func_slv_extract(use_a, use_b, use_c, use_d, use_e, use_f : BOOLEAN; a_w, b_w, c_w, d_w, e_w, f_w : NATURAL; vec : STD_LOGIC_VECTOR; sel : NATURAL) RETURN STD_LOGIC_VECTOR IS BEGIN - RETURN func_slv_extract(use_a, use_b, use_c, use_d, use_e, use_f, FALSE, a_w, b_w, c_w, d_w, e_w, f_w, 0, vec, sel); + RETURN func_slv_extract(use_a, use_b, use_c, use_d, use_e, use_f, FALSE, FALSE, a_w, b_w, c_w, d_w, e_w, f_w, 0, 0, vec, sel); END func_slv_extract; FUNCTION func_slv_extract(use_a, use_b, use_c, use_d, use_e : BOOLEAN; a_w, b_w, c_w, d_w, e_w : NATURAL; vec : STD_LOGIC_VECTOR; sel : NATURAL) RETURN STD_LOGIC_VECTOR IS BEGIN - RETURN func_slv_extract(use_a, use_b, use_c, use_d, use_e, FALSE, FALSE, a_w, b_w, c_w, d_w, e_w, 0, 0, vec, sel); + RETURN func_slv_extract(use_a, use_b, use_c, use_d, use_e, FALSE, FALSE, FALSE, a_w, b_w, c_w, d_w, e_w, 0, 0, 0, vec, sel); END func_slv_extract; FUNCTION func_slv_extract(use_a, use_b, use_c, use_d : BOOLEAN; a_w, b_w, c_w, d_w : NATURAL; vec : STD_LOGIC_VECTOR; sel : NATURAL) RETURN STD_LOGIC_VECTOR IS BEGIN - RETURN func_slv_extract(use_a, use_b, use_c, use_d, FALSE, FALSE, FALSE, a_w, b_w, c_w, d_w, 0, 0, 0, vec, sel); + RETURN func_slv_extract(use_a, use_b, use_c, use_d, FALSE, FALSE, FALSE, FALSE, a_w, b_w, c_w, d_w, 0, 0, 0, 0, vec, sel); END func_slv_extract; FUNCTION func_slv_extract(use_a, use_b, use_c : BOOLEAN; a_w, b_w, c_w : NATURAL; vec : STD_LOGIC_VECTOR; sel : NATURAL) RETURN STD_LOGIC_VECTOR IS BEGIN - RETURN func_slv_extract(use_a, use_b, use_c, FALSE, FALSE, FALSE, FALSE, a_w, b_w, c_w, 0, 0, 0, 0, vec, sel); + RETURN func_slv_extract(use_a, use_b, use_c, FALSE, FALSE, FALSE, FALSE, FALSE, a_w, b_w, c_w, 0, 0, 0, 0, 0, vec, sel); END func_slv_extract; FUNCTION func_slv_extract(use_a, use_b : BOOLEAN; a_w, b_w : NATURAL; vec : STD_LOGIC_VECTOR; sel : NATURAL) RETURN STD_LOGIC_VECTOR IS BEGIN - RETURN func_slv_extract(use_a, use_b, FALSE, FALSE, FALSE, FALSE, FALSE, a_w, b_w, 0, 0, 0, 0, 0, vec, sel); + RETURN func_slv_extract(use_a, use_b, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, a_w, b_w, 0, 0, 0, 0, 0, 0, vec, sel); END func_slv_extract; - + + FUNCTION func_slv_extract(a_w, b_w, c_w, d_w, e_w, f_w, g_w, h_w : NATURAL; vec : STD_LOGIC_VECTOR; sel : NATURAL) RETURN STD_LOGIC_VECTOR IS + BEGIN + RETURN func_slv_extract(TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, a_w, b_w, c_w, d_w, e_w, f_w, g_w, h_w, vec, sel); + END func_slv_extract; + FUNCTION func_slv_extract(a_w, b_w, c_w, d_w, e_w, f_w, g_w : NATURAL; vec : STD_LOGIC_VECTOR; sel : NATURAL) RETURN STD_LOGIC_VECTOR IS BEGIN RETURN func_slv_extract(TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, a_w, b_w, c_w, d_w, e_w, f_w, g_w, vec, sel); diff --git a/libraries/base/dp/dp.peripheral.yaml b/libraries/base/dp/dp.peripheral.yaml index fe7dacf6457d681bd0a7a90f0b4642790b4b3715..c8bdf04b6953d06ddbf0e68f0e4817b8fda350fb 100644 --- a/libraries/base/dp/dp.peripheral.yaml +++ b/libraries/base/dp/dp.peripheral.yaml @@ -338,3 +338,18 @@ peripherals: address_offset: 0x0 mm_width: 1 access_mode: RW + + + - peripheral_name: dp_sync_insert_v2 # pi_dp_sync_insert_v2.py + peripheral_description: "Every nof_blk_per_sync block a sync pulse is created at the output." + mm_ports: + # MM port for dp_sync_insert_v2.vhd + - mm_port_name: REG_DP_SYNC_INSERT_V2 + mm_port_type: REG + mm_port_description: "" + fields: + - - field_name: nof_blk_per_sync + field_description: | + "The block counter resets if a sync arrives at the input or when nof_blk_per_sync is reached." + address_offset: 0x0 + access_mode: RW diff --git a/libraries/base/dp/hdllib.cfg b/libraries/base/dp/hdllib.cfg index 35eb45f99ba31ed7867ddb948437b64012e445f1..39ca669c8f184bc1e880bf341840641e720fd402 100644 --- a/libraries/base/dp/hdllib.cfg +++ b/libraries/base/dp/hdllib.cfg @@ -43,8 +43,10 @@ synth_files = src/vhdl/dp_shiftreg.vhd src/vhdl/dp_fifo_info.vhd src/vhdl/dp_fifo_core.vhd + src/vhdl/dp_fifo_core_arr.vhd src/vhdl/dp_fifo_sc.vhd src/vhdl/dp_fifo_dc.vhd + src/vhdl/dp_fifo_dc_arr.vhd src/vhdl/dp_fifo_dc_mixed_widths.vhd src/vhdl/dp_fifo_fill_core.vhd src/vhdl/dp_fifo_fill_sc.vhd @@ -219,6 +221,7 @@ test_bench_files = tb/vhdl/tb_dp_fifo_fill_sc.vhd tb/vhdl/tb_dp_fifo_info.vhd tb/vhdl/tb_dp_fifo_dc.vhd + tb/vhdl/tb_dp_fifo_dc_arr.vhd tb/vhdl/tb_dp_fifo_dc_mixed_widths.vhd tb/vhdl/tb_dp_fifo_sc.vhd tb/vhdl/tb_dp_fifo_to_mm.vhd @@ -291,6 +294,7 @@ test_bench_files = tb/vhdl/tb_tb_dp_fifo_fill_sc.vhd tb/vhdl/tb_tb_dp_fifo_fill_eop.vhd tb/vhdl/tb_tb_dp_fifo_dc.vhd + tb/vhdl/tb_tb_dp_fifo_dc_arr.vhd tb/vhdl/tb_tb_dp_fifo_dc_mixed_widths.vhd tb/vhdl/tb_tb_dp_frame_scheduler.vhd tb/vhdl/tb_tb_dp_latency_fifo.vhd diff --git a/libraries/base/dp/src/vhdl/dp_bsn_source_reg_v2.vhd b/libraries/base/dp/src/vhdl/dp_bsn_source_reg_v2.vhd index eb5600b1832a4b802f2271f09ce347e7b3efb083..94535504404868246c757a796885e8c6f53738db 100644 --- a/libraries/base/dp/src/vhdl/dp_bsn_source_reg_v2.vhd +++ b/libraries/base/dp/src/vhdl/dp_bsn_source_reg_v2.vhd @@ -82,7 +82,7 @@ ARCHITECTURE rtl OF dp_bsn_source_reg_v2 IS CONSTANT c_mm_reg : t_c_mem := (latency => 1, adr_w => 3, dat_w => c_word_w, -- Use MM bus data width = c_word_w = 32 for all MM registers - nof_dat => 3**2, + nof_dat => 2**3, init_sl => '0'); -- Registers in mm_clk domain diff --git a/libraries/base/dp/src/vhdl/dp_fifo_core_arr.vhd b/libraries/base/dp/src/vhdl/dp_fifo_core_arr.vhd new file mode 100644 index 0000000000000000000000000000000000000000..83964e22b64cf0a3cdc95ad955082f8752e7d713 --- /dev/null +++ b/libraries/base/dp/src/vhdl/dp_fifo_core_arr.vhd @@ -0,0 +1,308 @@ +------------------------------------------------------------------------------- +-- +-- Copyright 2021 +-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/> +-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands +-- +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- +------------------------------------------------------------------------------- + +------------------------------------------------------------------------------- +-- +-- Author: R. van der Walle +-- Purpose: +-- Provide input ready control and use output ready control to the FIFO. +-- Pass sop and eop along with the data through the FIFO if g_use_ctrl=TRUE. +-- Default the RL=1, use g_fifo_rl=0 for a the show ahead FIFO. +-- Description: +-- Similar to dp_fifo_core but for multiple synchronous inputs. All data fields +-- of the in sosi's are concatenated in addition to the the control signals of +-- in_sosi_arr(0) and in_aux. So the control signals of in_sosi_arr(1 TO g_nof_streams-1) +-- are not used. It is useful to have dp_fifo_core_arr to ensure that all inputs +-- are crossed over to the rd_clk domain on the same clock cycle, this cannot +-- be guaranteed when using multiple dp_fifo_core instances. For single clock, +-- dp_fifo_core_arr is also useful as it saves logic on the control signals since +-- it only uses the control signals of in_sosi_arr(0). +-- Remark: +-- . dp_fifo_core_arr is not built on top of dp_fifo_core as the input of dp_fifo_core +-- is of type t_dp_sosi which has a limited size and could cause issues when concatenating +-- multiple input streams. +-- . It is assumed all inputs are synchronous (identical control signals). +-- If the inputs are asynchronous, better use multiple instances of +-- dp_fifo_core. +-- . It is possible to add additonal signals to the fifo using in_aux/out_aux. + +LIBRARY IEEE, common_lib, technology_lib; +USE IEEE.STD_LOGIC_1164.ALL; +USE IEEE.numeric_std.ALL; +USE common_lib.common_pkg.ALL; +USE work.dp_stream_pkg.ALL; +USE technology_lib.technology_select_pkg.ALL; + +ENTITY dp_fifo_core_arr IS + GENERIC ( + g_technology : NATURAL := c_tech_select_default; + g_nof_streams : NATURAL := 1; + g_note_is_ful : BOOLEAN := TRUE; -- when TRUE report NOTE when FIFO goes full, fifo overflow is always reported as FAILURE + g_use_dual_clock : BOOLEAN := FALSE; + g_use_lut_sc : BOOLEAN := FALSE; -- when TRUE then force using LUTs instead of block RAM for single clock FIFO (bot available for dual clock FIFO) + g_data_w : NATURAL := 16; -- Should be 2 times the c_complex_w if g_use_complex = TRUE + g_data_signed : BOOLEAN := FALSE; -- TRUE extends g_data_w bits with the sign bit, FALSE pads g_data_w bits with zeros. + g_bsn_w : NATURAL := 1; + g_empty_w : NATURAL := 1; + g_channel_w : NATURAL := 1; + g_error_w : NATURAL := 1; + g_aux_w : NATURAL := 1; + g_use_bsn : BOOLEAN := FALSE; + g_use_empty : BOOLEAN := FALSE; + g_use_channel : BOOLEAN := FALSE; + g_use_error : BOOLEAN := FALSE; + g_use_sync : BOOLEAN := FALSE; + g_use_aux : BOOLEAN := FALSE; -- extra signal in_aux/out_aux + g_use_ctrl : BOOLEAN := TRUE; -- sop & eop + g_use_complex : BOOLEAN := FALSE; -- TRUE feeds the concatenated complex fields (im & re) through the FIFO instead of the data field. + g_fifo_size : NATURAL := 512; -- (16+2) * 512 = 1 M9K, g_data_w+2 for sop and eop + g_fifo_af_margin : NATURAL := 4; -- >=4, Nof words below max (full) at which fifo is considered almost full + g_fifo_rl : NATURAL := 1 + ); + PORT ( + wr_rst : IN STD_LOGIC; + wr_clk : IN STD_LOGIC; + rd_rst : IN STD_LOGIC; + rd_clk : IN STD_LOGIC; + -- Monitor FIFO filling + wr_ful : OUT STD_LOGIC; -- corresponds to the carry bit of wr_usedw when FIFO is full + wr_usedw : OUT STD_LOGIC_VECTOR(ceil_log2(g_fifo_size)-1 DOWNTO 0); + rd_usedw : OUT STD_LOGIC_VECTOR(ceil_log2(g_fifo_size)-1 DOWNTO 0); + rd_emp : OUT STD_LOGIC; + -- ST sink + snk_out_arr : OUT t_dp_siso_arr(g_nof_streams-1 DOWNTO 0); + snk_in_arr : IN t_dp_sosi_arr(g_nof_streams-1 DOWNTO 0); + in_aux : IN STD_LOGIC_VECTOR(g_aux_w-1 DOWNTO 0) := (OTHERS => '0'); + -- ST source + src_in_arr : IN t_dp_siso_arr(g_nof_streams-1 DOWNTO 0); + src_out_arr : OUT t_dp_sosi_arr(g_nof_streams-1 DOWNTO 0); + out_aux : OUT STD_LOGIC_VECTOR(g_aux_w-1 DOWNTO 0) + ); +END dp_fifo_core_arr; + + +ARCHITECTURE str OF dp_fifo_core_arr IS + + CONSTANT c_use_data : BOOLEAN := TRUE; + CONSTANT c_total_data_w : NATURAL := g_nof_streams * g_data_w; + CONSTANT c_ctrl_w : NATURAL := 2; -- sop and eop + + CONSTANT c_complex_w : NATURAL := smallest(c_dp_stream_dsp_data_w, g_data_w/2); -- needed to cope with g_data_w > 2*c_dp_stream_dsp_data_w + + CONSTANT c_fifo_almost_full : NATURAL := g_fifo_size-g_fifo_af_margin; -- FIFO almost full level for snk_out.ready + CONSTANT c_fifo_dat_w : NATURAL := func_slv_concat_w(c_use_data, g_use_bsn, g_use_empty, g_use_channel, g_use_error, g_use_sync, g_use_ctrl, g_use_aux, + c_total_data_w, g_bsn_w, g_empty_w, g_channel_w, g_error_w, 1, c_ctrl_w, g_aux_w); -- concat via FIFO + + SIGNAL nxt_snk_out : t_dp_siso := c_dp_siso_rst; + + SIGNAL arst : STD_LOGIC; + + TYPE t_wr_data_complex_arr IS ARRAY (INTEGER RANGE <>) OF STD_LOGIC_VECTOR(2*c_complex_w-1 DOWNTO 0); + TYPE t_rd_data_arr IS ARRAY (INTEGER RANGE <>) OF STD_LOGIC_VECTOR(g_data_w-1 DOWNTO 0); + + SIGNAL wr_data_complex_arr : t_wr_data_complex_arr(g_nof_streams-1 DOWNTO 0); + SIGNAL wr_data : STD_LOGIC_VECTOR(c_total_data_w-1 DOWNTO 0); + SIGNAL rd_data : STD_LOGIC_VECTOR(c_total_data_w-1 DOWNTO 0); + SIGNAL rd_data_arr : t_rd_data_arr(g_nof_streams-1 DOWNTO 0); + + SIGNAL fifo_wr_dat : STD_LOGIC_VECTOR(c_fifo_dat_w-1 DOWNTO 0); + SIGNAL fifo_wr_req : STD_LOGIC; + SIGNAL fifo_wr_ful : STD_LOGIC; + SIGNAL fifo_wr_usedw : STD_LOGIC_VECTOR(wr_usedw'RANGE); + + SIGNAL fifo_rd_dat : STD_LOGIC_VECTOR(c_fifo_dat_w-1 DOWNTO 0) := (OTHERS=>'0'); + SIGNAL fifo_rd_val : STD_LOGIC; + SIGNAL fifo_rd_req : STD_LOGIC; + SIGNAL fifo_rd_emp : STD_LOGIC; + SIGNAL fifo_rd_usedw : STD_LOGIC_VECTOR(rd_usedw'RANGE); + + SIGNAL wr_sync : STD_LOGIC_VECTOR(0 DOWNTO 0); + SIGNAL rd_sync : STD_LOGIC_VECTOR(0 DOWNTO 0); + SIGNAL wr_ctrl : STD_LOGIC_VECTOR(1 DOWNTO 0); + SIGNAL rd_ctrl : STD_LOGIC_VECTOR(1 DOWNTO 0); + SIGNAL wr_aux : STD_LOGIC_VECTOR(g_aux_w-1 DOWNTO 0); + + SIGNAL rd_siso_arr : t_dp_siso_arr(g_nof_streams-1 DOWNTO 0); + SIGNAL rd_sosi_arr : t_dp_sosi_arr(g_nof_streams-1 DOWNTO 0) := (OTHERS => c_dp_sosi_rst); -- initialize default values for unused sosi fields + + SIGNAL in_aux_sosi : t_dp_sosi := c_dp_sosi_rst; + SIGNAL out_aux_sosi : t_dp_sosi := c_dp_sosi_rst; + +BEGIN + + -- Output monitor FIFO filling + wr_ful <= fifo_wr_ful; + wr_usedw <= fifo_wr_usedw; + rd_usedw <= fifo_rd_usedw; + rd_emp <= fifo_rd_emp; + + p_wr_clk: PROCESS(wr_clk, wr_rst) + BEGIN + IF wr_rst='1' THEN + snk_out_arr <= (OTHERS => c_dp_siso_rst); + ELSIF rising_edge(wr_clk) THEN + FOR I IN 0 TO g_nof_streams-1 LOOP + snk_out_arr(I) <= nxt_snk_out; + END LOOP; + END IF; + END PROCESS; + + wr_sync(0) <= snk_in_arr(0).sync; + wr_ctrl <= snk_in_arr(0).sop & snk_in_arr(0).eop; + wr_aux <= in_aux; + + -- Assign the snk_in_arr data field or concatenated complex fields to the FIFO wr_data depending on g_use_complex + gen_streams : FOR I IN 0 TO g_nof_streams-1 GENERATE + wr_data_complex_arr(I) <= snk_in_arr(I).im(c_complex_w-1 DOWNTO 0) & snk_in_arr(I).re(c_complex_w-1 DOWNTO 0); + wr_data((I+1) * g_data_w -1 DOWNTO I * g_data_w) <= snk_in_arr(I).data(g_data_w-1 DOWNTO 0) WHEN g_use_complex = FALSE ELSE RESIZE_UVEC(wr_data_complex_arr(I), g_data_w); + END GENERATE; + -- fifo wr wires + fifo_wr_req <= snk_in_arr(0).valid; + fifo_wr_dat <= func_slv_concat(c_use_data, g_use_bsn, g_use_empty, g_use_channel, g_use_error, g_use_sync, g_use_ctrl, g_use_aux, + wr_data, + snk_in_arr(0).bsn( g_bsn_w-1 DOWNTO 0), + snk_in_arr(0).empty( g_empty_w-1 DOWNTO 0), + snk_in_arr(0).channel(g_channel_w-1 DOWNTO 0), + snk_in_arr(0).err( g_error_w-1 DOWNTO 0), + wr_sync, + wr_ctrl, + wr_aux); + + -- pass on frame level flow control + nxt_snk_out.xon <= src_in_arr(0).xon; + + -- up stream use fifo almost full to control snk_out.ready + nxt_snk_out.ready <= '1' WHEN UNSIGNED(fifo_wr_usedw)<c_fifo_almost_full ELSE '0'; + + gen_common_fifo_sc : IF g_use_dual_clock=FALSE GENERATE + u_common_fifo_sc : ENTITY common_lib.common_fifo_sc + GENERIC MAP ( + g_technology => g_technology, + g_note_is_ful => g_note_is_ful, + g_use_lut => g_use_lut_sc, + g_dat_w => c_fifo_dat_w, + g_nof_words => g_fifo_size + ) + PORT MAP ( + rst => rd_rst, + clk => rd_clk, + wr_dat => fifo_wr_dat, + wr_req => fifo_wr_req, + wr_ful => fifo_wr_ful, + rd_dat => fifo_rd_dat, + rd_req => fifo_rd_req, + rd_emp => fifo_rd_emp, + rd_val => fifo_rd_val, + usedw => fifo_rd_usedw + ); + + fifo_wr_usedw <= fifo_rd_usedw; + END GENERATE; + + gen_common_fifo_dc : IF g_use_dual_clock=TRUE GENERATE + u_common_fifo_dc : ENTITY common_lib.common_fifo_dc + GENERIC MAP ( + g_technology => g_technology, + g_dat_w => c_fifo_dat_w, + g_nof_words => g_fifo_size + ) + PORT MAP ( + rst => arst, + wr_clk => wr_clk, + wr_dat => fifo_wr_dat, + wr_req => fifo_wr_req, + wr_ful => fifo_wr_ful, + wrusedw => fifo_wr_usedw, + rd_clk => rd_clk, + rd_dat => fifo_rd_dat, + rd_req => fifo_rd_req, + rd_emp => fifo_rd_emp, + rdusedw => fifo_rd_usedw, + rd_val => fifo_rd_val + ); + + arst <= wr_rst OR rd_rst; + END GENERATE; + + -- Extract the data from the wide FIFO output SLV. rd_data will be assigned to rd_sosi.data or rd_sosi.im & rd_sosi.re depending on g_use_complex. + rd_data <= func_slv_extract(c_use_data, g_use_bsn, g_use_empty, g_use_channel, g_use_error, g_use_sync, g_use_ctrl, g_use_aux, + c_total_data_w, g_bsn_w, g_empty_w, g_channel_w, g_error_w, 1, c_ctrl_w, g_aux_w, + fifo_rd_dat, 0); + + -- fifo rd wires + -- SISO + fifo_rd_req <= rd_siso_arr(0).ready; + rd_sync <= func_slv_extract(c_use_data, g_use_bsn, g_use_empty, g_use_channel, g_use_error, g_use_sync, g_use_ctrl, g_use_aux, c_total_data_w, g_bsn_w, g_empty_w, g_channel_w, g_error_w, 1, c_ctrl_w, g_aux_w, fifo_rd_dat, 5); + rd_ctrl <= func_slv_extract(c_use_data, g_use_bsn, g_use_empty, g_use_channel, g_use_error, g_use_sync, g_use_ctrl, g_use_aux, c_total_data_w, g_bsn_w, g_empty_w, g_channel_w, g_error_w, 1, c_ctrl_w, g_aux_w, fifo_rd_dat, 6); + + -- AUX + in_aux_sosi.data <= RESIZE_DP_DATA(func_slv_extract(c_use_data, g_use_bsn, g_use_empty, g_use_channel, g_use_error, g_use_sync, g_use_ctrl, g_use_aux, c_total_data_w, g_bsn_w, g_empty_w, g_channel_w, g_error_w, 1, c_ctrl_w, g_aux_w, fifo_rd_dat, 7)); + in_aux_sosi.valid <= fifo_rd_val; + out_aux <= out_aux_sosi.data(g_aux_w-1 DOWNTO 0); + + -- SOSI + gen_rd_streams : FOR I IN 0 TO g_nof_streams-1 GENERATE + rd_data_arr(I) <= rd_data( (I+1) * g_data_w -1 DOWNTO I * g_data_w); + rd_sosi_arr(I).data <= RESIZE_DP_SDATA(rd_data_arr(I)) WHEN g_data_signed=TRUE ELSE RESIZE_DP_DATA(rd_data_arr(I)); + rd_sosi_arr(I).re <= RESIZE_DP_DSP_DATA(rd_data_arr(I)( c_complex_w-1 DOWNTO 0)); + rd_sosi_arr(I).im <= RESIZE_DP_DSP_DATA(rd_data_arr(I)(2*c_complex_w-1 DOWNTO c_complex_w)); + rd_sosi_arr(I).bsn <= RESIZE_DP_BSN(func_slv_extract(c_use_data, g_use_bsn, g_use_empty, g_use_channel, g_use_error, g_use_sync, g_use_ctrl, g_use_aux, c_total_data_w, g_bsn_w, g_empty_w, g_channel_w, g_error_w, 1, c_ctrl_w, g_aux_w, fifo_rd_dat, 1)); + rd_sosi_arr(I).empty <= RESIZE_DP_EMPTY(func_slv_extract(c_use_data, g_use_bsn, g_use_empty, g_use_channel, g_use_error, g_use_sync, g_use_ctrl, g_use_aux, c_total_data_w, g_bsn_w, g_empty_w, g_channel_w, g_error_w, 1, c_ctrl_w, g_aux_w, fifo_rd_dat, 2)); + rd_sosi_arr(I).channel <= RESIZE_DP_CHANNEL(func_slv_extract(c_use_data, g_use_bsn, g_use_empty, g_use_channel, g_use_error, g_use_sync, g_use_ctrl, g_use_aux, c_total_data_w, g_bsn_w, g_empty_w, g_channel_w, g_error_w, 1, c_ctrl_w, g_aux_w, fifo_rd_dat, 3)); + rd_sosi_arr(I).err <= RESIZE_DP_ERROR(func_slv_extract(c_use_data, g_use_bsn, g_use_empty, g_use_channel, g_use_error, g_use_sync, g_use_ctrl, g_use_aux, c_total_data_w, g_bsn_w, g_empty_w, g_channel_w, g_error_w, 1, c_ctrl_w, g_aux_w, fifo_rd_dat, 4)); + rd_sosi_arr(I).sync <= fifo_rd_val AND rd_sync(0); + rd_sosi_arr(I).valid <= fifo_rd_val; + rd_sosi_arr(I).sop <= fifo_rd_val AND rd_ctrl(1); + rd_sosi_arr(I).eop <= fifo_rd_val AND rd_ctrl(0); + + u_ready_latency : ENTITY work.dp_latency_adapter + GENERIC MAP ( + g_in_latency => 1, + g_out_latency => g_fifo_rl + ) + PORT MAP ( + rst => rd_rst, + clk => rd_clk, + -- ST sink + snk_out => rd_siso_arr(I), + snk_in => rd_sosi_arr(I), + -- ST source + src_in => src_in_arr(I), + src_out => src_out_arr(I) + ); + END GENERATE; + + -- Using extra dp_latency_adapter for aux signal + u_ready_latency_aux : ENTITY work.dp_latency_adapter + GENERIC MAP ( + g_in_latency => 1, + g_out_latency => g_fifo_rl + ) + PORT MAP ( + rst => rd_rst, + clk => rd_clk, + -- ST sink + snk_in => in_aux_sosi, + -- ST source + src_in => src_in_arr(0), + src_out => out_aux_sosi + ); + +END str; diff --git a/libraries/base/dp/src/vhdl/dp_fifo_dc_arr.vhd b/libraries/base/dp/src/vhdl/dp_fifo_dc_arr.vhd new file mode 100644 index 0000000000000000000000000000000000000000..e788c2b57913f8cef7638e3288e83aa7ef55da3c --- /dev/null +++ b/libraries/base/dp/src/vhdl/dp_fifo_dc_arr.vhd @@ -0,0 +1,124 @@ +------------------------------------------------------------------------------- +-- +-- Copyright 2021 +-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/> +-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands +-- +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- +------------------------------------------------------------------------------- + +------------------------------------------------------------------------------- +-- +-- Author: R. van der Walle +-- Purpose: DP FIFO array for dual clock (= dc) domain wr and rd. +-- Description: See dp_fifo_core_arr.vhd. + +LIBRARY IEEE,common_lib, technology_lib; +USE IEEE.std_logic_1164.ALL; +USE IEEE.numeric_std.ALL; +USE common_lib.common_pkg.ALL; +USE work.dp_stream_pkg.ALL; +USE technology_lib.technology_select_pkg.ALL; + +ENTITY dp_fifo_dc_arr IS + GENERIC ( + g_technology : NATURAL := c_tech_select_default; + g_nof_streams : NATURAL := 1; + g_data_w : NATURAL := 16; -- Should be 2 times the c_complex_w if g_use_complex = TRUE + g_bsn_w : NATURAL := 1; + g_empty_w : NATURAL := 1; + g_channel_w : NATURAL := 1; + g_error_w : NATURAL := 1; + g_aux_w : NATURAL := 1; + g_use_bsn : BOOLEAN := FALSE; + g_use_empty : BOOLEAN := FALSE; + g_use_channel : BOOLEAN := FALSE; + g_use_error : BOOLEAN := FALSE; + g_use_sync : BOOLEAN := FALSE; + g_use_aux : BOOLEAN := FALSE; + g_use_ctrl : BOOLEAN := TRUE; -- sop & eop + g_use_complex : BOOLEAN := FALSE; -- TRUE feeds the concatenated complex fields (im & re) through the FIFO instead of the data field. + g_fifo_size : NATURAL := 512; -- (16+2) * 512 = 1 M9K, g_data_w+2 for sop and eop + g_fifo_af_margin : NATURAL := 4; -- >=4, Nof words below max (full) at which fifo is considered almost full + g_fifo_rl : NATURAL := 1 + ); + PORT ( + wr_rst : IN STD_LOGIC; + wr_clk : IN STD_LOGIC; + rd_rst : IN STD_LOGIC; + rd_clk : IN STD_LOGIC; + -- Monitor FIFO filling + wr_ful : OUT STD_LOGIC; + wr_usedw : OUT STD_LOGIC_VECTOR(ceil_log2(g_fifo_size)-1 DOWNTO 0); + rd_usedw : OUT STD_LOGIC_VECTOR(ceil_log2(g_fifo_size)-1 DOWNTO 0); + rd_emp : OUT STD_LOGIC; + -- ST sink + snk_out_arr : OUT t_dp_siso_arr(g_nof_streams-1 DOWNTO 0); + snk_in_arr : IN t_dp_sosi_arr(g_nof_streams-1 DOWNTO 0); + in_aux : IN STD_LOGIC_VECTOR(g_aux_w-1 DOWNTO 0); + -- ST source + src_in_arr : IN t_dp_siso_arr(g_nof_streams-1 DOWNTO 0) := (OTHERS => c_dp_siso_rdy); + src_out_arr : OUT t_dp_sosi_arr(g_nof_streams-1 DOWNTO 0); + out_aux : OUT STD_LOGIC_VECTOR(g_aux_w-1 DOWNTO 0) + ); +END dp_fifo_dc_arr; + + +ARCHITECTURE str OF dp_fifo_dc_arr IS +BEGIN + + u_dp_fifo_core_arr : ENTITY work.dp_fifo_core_arr + GENERIC MAP ( + g_technology => g_technology, + g_nof_streams => g_nof_streams, + g_use_dual_clock => TRUE, + g_data_w => g_data_w, + g_bsn_w => g_bsn_w, + g_empty_w => g_empty_w, + g_channel_w => g_channel_w, + g_error_w => g_error_w, + g_aux_w => g_aux_w, + g_use_bsn => g_use_bsn, + g_use_empty => g_use_empty, + g_use_channel => g_use_channel, + g_use_error => g_use_error, + g_use_sync => g_use_sync, + g_use_aux => g_use_aux, + g_use_ctrl => g_use_ctrl, + g_use_complex => g_use_complex, + g_fifo_size => g_fifo_size, + g_fifo_af_margin => g_fifo_af_margin, + g_fifo_rl => g_fifo_rl + ) + PORT MAP ( + wr_rst => wr_rst, + wr_clk => wr_clk, + rd_rst => rd_rst, + rd_clk => rd_clk, + -- Monitor FIFO filling + wr_ful => wr_ful, + wr_usedw => wr_usedw, + rd_usedw => rd_usedw, + rd_emp => rd_emp, + -- ST sink + snk_out_arr => snk_out_arr, + snk_in_arr => snk_in_arr, + in_aux => in_aux, + -- ST source + src_in_arr => src_in_arr, + src_out_arr => src_out_arr, + out_aux => out_aux + ); + +END str; diff --git a/libraries/base/dp/tb/vhdl/tb_dp_fifo_dc_arr.vhd b/libraries/base/dp/tb/vhdl/tb_dp_fifo_dc_arr.vhd new file mode 100644 index 0000000000000000000000000000000000000000..514ebe5def34235e3eab48d0502a83b7c860190d --- /dev/null +++ b/libraries/base/dp/tb/vhdl/tb_dp_fifo_dc_arr.vhd @@ -0,0 +1,251 @@ +------------------------------------------------------------------------------- +-- +-- Copyright 2021 +-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/> +-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands +-- +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- +------------------------------------------------------------------------------- + +------------------------------------------------------------------------------- +-- +-- Author: R. van der Walle +-- Purpose: Test dp_fifo_dc_arr. +-- Description: +-- Verifies output data and ctrl signals of DUT. This is configurable using generics. + +LIBRARY IEEE, common_lib; +USE IEEE.std_logic_1164.ALL; +USE IEEE.numeric_std.ALL; +USE common_lib.common_pkg.ALL; +USE work.dp_stream_pkg.ALL; +USE work.tb_dp_pkg.ALL; + +ENTITY tb_dp_fifo_dc_arr IS + GENERIC ( + -- Try FIFO settings + g_dut_nof_streams : NATURAL := 3; + g_dut_wr_clk_freq : POSITIVE := 2; -- normalized write clock frequency + g_dut_rd_clk_freq : POSITIVE := 3; -- normalized read clock frequency + g_dut_use_bsn : BOOLEAN := TRUE; + g_dut_use_empty : BOOLEAN := TRUE; + g_dut_use_channel : BOOLEAN := TRUE; + g_dut_use_sync : BOOLEAN := TRUE; + g_dut_use_ctrl : BOOLEAN := TRUE; + g_dut_use_aux : BOOLEAN := TRUE; + g_dut_out_latency : NATURAL := 1 -- selectable for dp_fifo_dc_arr: default 1 or 0 for look ahead FIFO + ); +END tb_dp_fifo_dc_arr; + + +ARCHITECTURE tb OF tb_dp_fifo_dc_arr IS + + -- See tb_dp_pkg.vhd for explanation and run time, increase the run time by g_dut_rd_clk_freq/g_dut_wr_clk_freq if g_dut_rd_clk_freq>g_dut_wr_clk_freq + + -- DUT + CONSTANT c_dut_fifo_size : NATURAL := 64; + CONSTANT c_dut_in_latency : NATURAL := 1; -- fixed for dp_fifo_dc_arr + + -- Stimuli + CONSTANT c_tx_latency : NATURAL := c_dut_in_latency; -- TX ready latency of TB + CONSTANT c_tx_void : NATURAL := sel_a_b(c_tx_latency, 1, 0); -- used to avoid empty range VHDL warnings when c_tx_latency=0 + CONSTANT c_tx_offset_sop : NATURAL := 3; + CONSTANT c_tx_period_sop : NATURAL := 7; -- sop in data valid cycle 3, 10, 17, ... + CONSTANT c_tx_offset_eop : NATURAL := 5; -- eop in data valid cycle 5, 12, 19, ... + CONSTANT c_tx_period_eop : NATURAL := c_tx_period_sop; + CONSTANT c_tx_offset_sync : NATURAL := 3; -- sync in data valid cycle 3, 20, 37, ... + CONSTANT c_tx_period_sync : NATURAL := 17; + CONSTANT c_rx_latency : NATURAL := g_dut_out_latency; -- RX ready latency from DUT + CONSTANT c_verify_en_wait : NATURAL := 20; -- wait some cycles before asserting verify enable + + CONSTANT c_bsn_offset : NATURAL := 1; + CONSTANT c_empty_offset : NATURAL := 2; + CONSTANT c_channel_offset : NATURAL := 3; + + CONSTANT c_random_w : NATURAL := 19; + + SIGNAL tb_end : STD_LOGIC := '0'; + SIGNAL wr_clk : STD_LOGIC := '0'; + SIGNAL rd_clk : STD_LOGIC := '0'; + SIGNAL rst : STD_LOGIC; + SIGNAL sync : STD_LOGIC; + SIGNAL lfsr1 : STD_LOGIC_VECTOR(c_random_w-1 DOWNTO 0) := (OTHERS=>'0'); + SIGNAL lfsr2 : STD_LOGIC_VECTOR(c_random_w DOWNTO 0) := (OTHERS=>'0'); + + SIGNAL cnt_dat : STD_LOGIC_VECTOR(c_dp_data_w-1 DOWNTO 0); + SIGNAL cnt_val : STD_LOGIC; + SIGNAL cnt_en : STD_LOGIC; + + SIGNAL tx_data : t_dp_data_arr(0 TO c_tx_latency + c_tx_void) := (OTHERS=>(OTHERS=>'0')); + SIGNAL tx_val : STD_LOGIC_VECTOR(0 TO c_tx_latency + c_tx_void) := (OTHERS=>'0'); + + SIGNAL in_ready : STD_LOGIC; + SIGNAL in_data : STD_LOGIC_VECTOR(c_dp_data_w-1 DOWNTO 0) := (OTHERS=>'0'); + SIGNAL in_bsn : STD_LOGIC_VECTOR(c_dp_data_w-1 DOWNTO 0) := (OTHERS=>'0'); + SIGNAL in_empty : STD_LOGIC_VECTOR(c_dp_data_w-1 DOWNTO 0) := (OTHERS=>'0'); + SIGNAL in_channel : STD_LOGIC_VECTOR(c_dp_data_w-1 DOWNTO 0) := (OTHERS=>'0'); + SIGNAL in_sync : STD_LOGIC; + SIGNAL in_val : STD_LOGIC; + SIGNAL in_sop : STD_LOGIC; + SIGNAL in_eop : STD_LOGIC; + SIGNAL in_aux : STD_LOGIC; + + SIGNAL in_siso_arr : t_dp_siso_arr(g_dut_nof_streams-1 DOWNTO 0); + SIGNAL in_sosi_arr : t_dp_sosi_arr(g_dut_nof_streams-1 DOWNTO 0) := (OTHERS => c_dp_sosi_rst); + SIGNAL out_siso_arr : t_dp_siso_arr(g_dut_nof_streams-1 DOWNTO 0); + SIGNAL out_sosi_arr : t_dp_sosi_arr(g_dut_nof_streams-1 DOWNTO 0); + + SIGNAL out_ready : STD_LOGIC; + SIGNAL prev_out_ready : STD_LOGIC_VECTOR(0 TO c_rx_latency); + SIGNAL out_data : STD_LOGIC_VECTOR(c_dp_data_w-1 DOWNTO 0); + SIGNAL out_bsn : STD_LOGIC_VECTOR(c_dp_data_w-1 DOWNTO 0) := (OTHERS=>'0'); + SIGNAL out_empty : STD_LOGIC_VECTOR(c_dp_data_w-1 DOWNTO 0) := (OTHERS=>'0'); + SIGNAL out_channel : STD_LOGIC_VECTOR(c_dp_data_w-1 DOWNTO 0) := (OTHERS=>'0'); + SIGNAL out_sync : STD_LOGIC; + SIGNAL out_val : STD_LOGIC; + SIGNAL out_sop : STD_LOGIC; + SIGNAL out_eop : STD_LOGIC; + SIGNAL out_aux : STD_LOGIC; + SIGNAL prev_out_data : STD_LOGIC_VECTOR(out_data'RANGE); + + SIGNAL state : t_dp_state_enum; + + SIGNAL verify_en : STD_LOGIC; + SIGNAL verify_done : STD_LOGIC; + + SIGNAL exp_data : STD_LOGIC_VECTOR(c_dp_data_w-1 DOWNTO 0) := TO_UVEC(19000/g_dut_wr_clk_freq, c_dp_data_w); + + SIGNAL usedw : STD_LOGIC_VECTOR(ceil_log2(c_dut_fifo_size)-1 DOWNTO 0); + +BEGIN + + wr_clk <= NOT wr_clk OR tb_end AFTER g_dut_rd_clk_freq*clk_period/2; + rd_clk <= NOT rd_clk OR tb_end AFTER g_dut_wr_clk_freq*clk_period/2; + rst <= '1', '0' AFTER clk_period*7; + + -- Sync interval + proc_dp_sync_interval(wr_clk, sync); + + -- Input data + cnt_val <= in_ready AND cnt_en; + + proc_dp_cnt_dat(rst, wr_clk, cnt_val, cnt_dat); + proc_dp_tx_data(c_tx_latency, rst, wr_clk, cnt_val, cnt_dat, tx_data, tx_val, in_data, in_val); + proc_dp_tx_ctrl(c_tx_offset_sync, c_tx_period_sync, in_data, in_val, in_sync); + proc_dp_tx_ctrl(c_tx_offset_sop, c_tx_period_sop, in_data, in_val, in_sop); + proc_dp_tx_ctrl(c_tx_offset_eop, c_tx_period_eop, in_data, in_val, in_eop); + + in_bsn <= INCR_UVEC(in_data, c_bsn_offset); + in_empty <= INCR_UVEC(in_data, c_empty_offset); + in_channel <= INCR_UVEC(in_data, c_channel_offset); + + -- Stimuli control + proc_dp_count_en(rst, wr_clk, sync, lfsr1, state, verify_done, tb_end, cnt_en); + proc_dp_out_ready(rst, wr_clk, sync, lfsr2, out_ready); + + -- Output verify + proc_dp_verify_en(c_verify_en_wait, rst, rd_clk, sync, verify_en); + proc_dp_verify_data("out_sosi.data", c_rx_latency, rd_clk, verify_en, out_ready, out_val, out_data, prev_out_data); + proc_dp_verify_valid(c_rx_latency, rd_clk, verify_en, out_ready, prev_out_ready, out_val); + + gen_verify_sync : IF g_dut_use_sync=TRUE GENERATE + proc_dp_verify_ctrl(c_tx_offset_sync, c_tx_period_sync, "sync", rd_clk, verify_en, out_data, out_val, out_sync); + END GENERATE; + + gen_verify_aux : IF g_dut_use_aux=TRUE GENERATE + proc_dp_verify_ctrl(c_tx_offset_sync, c_tx_period_sync, "aux", rd_clk, verify_en, out_data, out_val, out_aux); + END GENERATE; + + gen_verify_ctrl : IF g_dut_use_ctrl=TRUE GENERATE + proc_dp_verify_ctrl(c_tx_offset_sop, c_tx_period_sop, "sop", rd_clk, verify_en, out_data, out_val, out_sop); + proc_dp_verify_ctrl(c_tx_offset_eop, c_tx_period_eop, "eop", rd_clk, verify_en, out_data, out_val, out_eop); + END GENERATE; + + gen_verify_bsn : IF g_dut_use_bsn=TRUE GENERATE + proc_dp_verify_other_sosi("bsn", INCR_UVEC(out_data, c_bsn_offset), rd_clk, verify_en, out_bsn); + END GENERATE; + + gen_verify_empty : IF g_dut_use_empty=TRUE GENERATE + proc_dp_verify_other_sosi("empty", INCR_UVEC(out_data, c_empty_offset), rd_clk, verify_en, out_empty); + END GENERATE; + + gen_verify_channel : IF g_dut_use_channel=TRUE GENERATE + proc_dp_verify_other_sosi("channel", INCR_UVEC(out_data, c_channel_offset), rd_clk, verify_en, out_channel); + END GENERATE; + + -- Check that the test has ran at all + proc_dp_verify_value(e_at_least, rd_clk, verify_done, exp_data, out_data); + + ------------------------------------------------------------------------------ + -- DUT dp_fifo_dc_arr + ------------------------------------------------------------------------------ + + -- map sl, slv to record + in_ready <= in_siso_arr(0).ready; -- SISO + in_aux <= in_sync; -- use sync to test aux data + gen_streams : FOR I IN 0 TO g_dut_nof_streams -1 GENERATE + in_sosi_arr(I).data(c_dp_data_w-1 DOWNTO 0) <= in_data; -- SOSI + in_sosi_arr(I).bsn(c_dp_bsn_w-1 DOWNTO 0) <= in_bsn(c_dp_bsn_w-1 DOWNTO 0); + in_sosi_arr(I).empty <= in_empty(c_dp_empty_w-1 DOWNTO 0); + in_sosi_arr(I).channel <= in_channel(c_dp_channel_w-1 DOWNTO 0); + in_sosi_arr(I).sync <= in_sync; + in_sosi_arr(I).valid <= in_val; + in_sosi_arr(I).sop <= in_sop; + in_sosi_arr(I).eop <= in_eop; + out_siso_arr(I).ready <= out_ready; -- SISO + END GENERATE; + out_data <= out_sosi_arr(0).data(c_dp_data_w-1 DOWNTO 0); -- SOSI + out_bsn(c_dp_bsn_w-1 DOWNTO 0) <= out_sosi_arr(0).bsn(c_dp_bsn_w-1 DOWNTO 0); + out_empty(c_dp_empty_w-1 DOWNTO 0) <= out_sosi_arr(0).empty; + out_channel(c_dp_channel_w-1 DOWNTO 0) <= out_sosi_arr(0).channel; + out_sync <= out_sosi_arr(0).sync; + out_val <= out_sosi_arr(0).valid; + out_sop <= out_sosi_arr(0).sop; + out_eop <= out_sosi_arr(0).eop; + + dut : ENTITY work.dp_fifo_dc_arr + GENERIC MAP ( + g_nof_streams => g_dut_nof_streams, + g_data_w => c_dp_data_w, + g_bsn_w => c_dp_bsn_w, + g_empty_w => c_dp_empty_w, + g_channel_w => c_dp_channel_w, + g_error_w => 1, + g_aux_w => 1, + g_use_bsn => g_dut_use_bsn, + g_use_empty => g_dut_use_empty, + g_use_channel => g_dut_use_channel, + g_use_error => FALSE, + g_use_sync => g_dut_use_sync, + g_use_aux => g_dut_use_aux, + g_use_ctrl => g_dut_use_ctrl, + g_fifo_size => c_dut_fifo_size, + g_fifo_rl => g_dut_out_latency + ) + PORT MAP ( + wr_rst => rst, + wr_clk => wr_clk, + rd_rst => rst, + rd_clk => rd_clk, + snk_out_arr => in_siso_arr, -- OUT = request to upstream ST source + snk_in_arr => in_sosi_arr, + in_aux(0) => in_aux, + wr_usedw => usedw, + rd_usedw => OPEN, + src_in_arr => out_siso_arr, -- IN = request from downstream ST sink + src_out_arr => out_sosi_arr, + out_aux(0) => out_aux + ); + +END tb; diff --git a/libraries/base/dp/tb/vhdl/tb_tb_dp_fifo_dc_arr.vhd b/libraries/base/dp/tb/vhdl/tb_tb_dp_fifo_dc_arr.vhd new file mode 100644 index 0000000000000000000000000000000000000000..a5a8429a8e0cefa5eae73755b8df3b083df2b55b --- /dev/null +++ b/libraries/base/dp/tb/vhdl/tb_tb_dp_fifo_dc_arr.vhd @@ -0,0 +1,67 @@ +------------------------------------------------------------------------------- +-- +-- Copyright 2021 +-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/> +-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands +-- +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- +------------------------------------------------------------------------------- + +------------------------------------------------------------------------------- +-- +-- Author: R. van der Walle +-- Purpose: Test multiple instances of tb_dp_fifo_dc_arr. + +LIBRARY IEEE; +USE IEEE.std_logic_1164.ALL; + + +ENTITY tb_tb_dp_fifo_dc_arr IS +END tb_tb_dp_fifo_dc_arr; + + +ARCHITECTURE tb OF tb_tb_dp_fifo_dc_arr IS + SIGNAL tb_end : STD_LOGIC := '0'; -- declare tb_end to avoid 'No objects found' error on 'when -label tb_end' +BEGIN + + -- > as 10 + -- > run g_dut_rd_clk_freq * 330 us --> OK + + -- Try FIFO settings : GENERIC MAP (g_dut_wr_clk_freq, g_dut_rd_clk_freq, g_dut_use_bsn, g_dut_use_empty, g_dut_use_channel, g_dut_use_sync, g_dut_use_ctrl, g_dut_out_latency) + + u_use_all_rl_0 : ENTITY work.tb_dp_fifo_dc_arr GENERIC MAP (3, 1, 1, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, 0); + u_use_all_rl_0_clk_2_1 : ENTITY work.tb_dp_fifo_dc_arr GENERIC MAP (3, 2, 1, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, 0); + u_use_all_rl_0_clk_1_2 : ENTITY work.tb_dp_fifo_dc_arr GENERIC MAP (3, 1, 2, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, 0); + u_use_all_rl_0_clk_3_2 : ENTITY work.tb_dp_fifo_dc_arr GENERIC MAP (3, 3, 2, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, 0); + u_use_all_rl_0_clk_2_3 : ENTITY work.tb_dp_fifo_dc_arr GENERIC MAP (3, 2, 3, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, 0); + + u_use_all : ENTITY work.tb_dp_fifo_dc_arr GENERIC MAP (1, 1, 1, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, 1); + u_use_all_clk_3_1 : ENTITY work.tb_dp_fifo_dc_arr GENERIC MAP (3, 3, 1, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, 1); + u_use_all_clk_1_3 : ENTITY work.tb_dp_fifo_dc_arr GENERIC MAP (3, 1, 3, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, 1); + + u_use_ctrl_rl_0 : ENTITY work.tb_dp_fifo_dc_arr GENERIC MAP (1, 1, 1, FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, 0); + u_use_ctrl_rl_0_clk_1_3 : ENTITY work.tb_dp_fifo_dc_arr GENERIC MAP (3, 1, 3, FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, 0); + u_use_ctrl_rl_0_clk_3_1 : ENTITY work.tb_dp_fifo_dc_arr GENERIC MAP (3, 3, 1, FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, 0); + u_use_ctrl : ENTITY work.tb_dp_fifo_dc_arr GENERIC MAP (3, 1, 1, FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, 1); + u_use_ctrl_clk_1_2 : ENTITY work.tb_dp_fifo_dc_arr GENERIC MAP (3, 1, 2, FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, 1); + u_use_ctrl_clk_2_1 : ENTITY work.tb_dp_fifo_dc_arr GENERIC MAP (3, 2, 1, FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, 1); + + u_no_bsn : ENTITY work.tb_dp_fifo_dc_arr GENERIC MAP (3, 1, 1, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, 1); + u_no_empty : ENTITY work.tb_dp_fifo_dc_arr GENERIC MAP (3, 1, 1, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, 1); + u_no_channel : ENTITY work.tb_dp_fifo_dc_arr GENERIC MAP (3, 1, 1, TRUE, TRUE, FALSE, TRUE, TRUE, TRUE, 1); + u_no_sync : ENTITY work.tb_dp_fifo_dc_arr GENERIC MAP (3, 1, 1, TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, 1); + u_no_ctrl : ENTITY work.tb_dp_fifo_dc_arr GENERIC MAP (3, 1, 1, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, 1); + u_no_aux : ENTITY work.tb_dp_fifo_dc_arr GENERIC MAP (3, 1, 1, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, 1); + +END tb; diff --git a/libraries/dsp/st/src/vhdl/st_xsq_mm_to_dp.vhd b/libraries/dsp/st/src/vhdl/st_xsq_mm_to_dp.vhd index 0327d6162cd04d63f778800b4d4b2b04422743c3..7ba4f77b717a704897571900528cc7eba1ad8d99 100644 --- a/libraries/dsp/st/src/vhdl/st_xsq_mm_to_dp.vhd +++ b/libraries/dsp/st/src/vhdl/st_xsq_mm_to_dp.vhd @@ -62,17 +62,17 @@ ARCHITECTURE rtl OF st_xsq_mm_to_dp IS crosslets_index : NATURAL; in_a_index : NATURAL; in_b_index : NATURAL; + mm_mosi : t_mem_mosi; END RECORD; - CONSTANT c_reg_rst : t_reg := (c_dp_sosi_rst, c_dp_sosi_rst, '0', 0, 0, 0); + CONSTANT c_reg_rst : t_reg := (c_dp_sosi_rst, c_dp_sosi_rst, '0', 0, 0, 0, c_mem_mosi_rst); SIGNAL r : t_reg; SIGNAL nxt_r : t_reg; - SIGNAL mm_mosi : t_mem_mosi := c_mem_mosi_rst; BEGIN - mm_mosi_arr <= (OTHERS => mm_mosi); -- all mosi are identical. + mm_mosi_arr <= (OTHERS => nxt_r.mm_mosi); -- all mosi are identical. u_sosi : PROCESS(r, mm_miso_arr) BEGIN @@ -98,7 +98,7 @@ BEGIN BEGIN v := r; v.out_sosi_ctrl := c_dp_sosi_rst; - mm_mosi.rd <= '0'; + v.mm_mosi.rd := '0'; -- initiate next block and capture in_sosi strobe IF r.busy = '0' AND in_sosi.sop = '1' THEN @@ -106,8 +106,8 @@ BEGIN v.in_sosi_strobe := in_sosi; ELSIF r.busy = '1' THEN -- continue with block - mm_mosi.rd <= '1'; - mm_mosi.address <= TO_MEM_ADDRESS(r.crosslets_index * g_nof_signal_inputs + r.in_b_index); -- streams iterate over in_b_index + v.mm_mosi.rd := '1'; + v.mm_mosi.address := TO_MEM_ADDRESS(r.crosslets_index * g_nof_signal_inputs + r.in_b_index); -- streams iterate over in_b_index -- Indices counters to select data order IF r.in_b_index < g_nof_signal_inputs - 1 THEN diff --git a/libraries/dsp/st/src/vhdl/st_xst.vhd b/libraries/dsp/st/src/vhdl/st_xst.vhd index 6a03cbdc49a6395e090e4222ad068707e7ecdf5b..1a0e75770b67e3cbe3710b95062940c087bf3a82 100644 --- a/libraries/dsp/st/src/vhdl/st_xst.vhd +++ b/libraries/dsp/st/src/vhdl/st_xst.vhd @@ -69,9 +69,12 @@ ARCHITECTURE str OF st_xst IS busy : STD_LOGIC; in_a_index : NATURAL; in_b_index : NATURAL; + x_sosi_0_re : t_slv_64_arr(g_nof_signal_inputs-1 DOWNTO 0); + x_sosi_0_im : t_slv_64_arr(g_nof_signal_inputs-1 DOWNTO 0); + in_a_sosi_arr : t_dp_sosi_arr(g_nof_streams-1 DOWNTO 0); END RECORD; - CONSTANT c_reg_rst : t_reg := ('0', 0, 0); + CONSTANT c_reg_rst : t_reg := ('0', 0, 0, (OTHERS=>(OTHERS => '0')), (OTHERS=>(OTHERS => '0')), (OTHERS => c_dp_sosi_rst) ); SIGNAL r : t_reg; SIGNAL nxt_r : t_reg; @@ -80,8 +83,6 @@ ARCHITECTURE str OF st_xst IS SIGNAL in_b_sosi_arr : t_dp_sosi_arr(g_nof_streams-1 DOWNTO 0); SIGNAL x_sosi_arr : t_dp_sosi_arr(g_nof_streams-1 DOWNTO 0); - SIGNAL reg_x_sosi_0_re : t_slv_64_arr(g_nof_signal_inputs-1 DOWNTO 0); - SIGNAL reg_x_sosi_0_im : t_slv_64_arr(g_nof_signal_inputs-1 DOWNTO 0); BEGIN -- MM -> DP @@ -103,20 +104,7 @@ BEGIN -- in_b_sosi_arr = x_sosi_arr in_b_sosi_arr <= x_sosi_arr; - - -- Capture x_sosi_arr(0) data - reg_x_sosi_0_re(nxt_r.in_b_index) <= x_sosi_arr(0).re; - reg_x_sosi_0_im(nxt_r.in_b_index) <= x_sosi_arr(0).im; - - -- reorder x_sosi_arr(0) data to follow in_a_index instead of in_b_index. All sosi in in_a_sosi_arr are identical. - p_in_a : PROCESS(x_sosi_arr, reg_x_sosi_0_re, reg_x_sosi_0_im, nxt_r.in_a_index) - BEGIN - FOR I IN 0 TO g_nof_streams-1 LOOP - in_a_sosi_arr(I) <= x_sosi_arr(0); - in_a_sosi_arr(I).re <= reg_x_sosi_0_re(nxt_r.in_a_index); - in_a_sosi_arr(I).im <= reg_x_sosi_0_im(nxt_r.in_a_index); - END LOOP; - END PROCESS; + in_a_sosi_arr <= nxt_r.in_a_sosi_arr; -- Register process p_reg : PROCESS(dp_rst, dp_clk) @@ -128,11 +116,19 @@ BEGIN END IF; END PROCESS; - -- Combinatorial process to create in_a_index and in_b_index for reoredering x_sosi_arr(0) data. + -- Combinatorial process to create in_a_index and in_b_index and reoredering x_sosi_arr(0) data. p_comb : PROCESS(r, x_sosi_arr) VARIABLE v : t_reg; + VARIABLE v_in_a_index : NATURAL; + VARIABLE v_in_b_index : NATURAL; + VARIABLE v_x_sosi_0_re : t_slv_64_arr(g_nof_signal_inputs-1 DOWNTO 0); + VARIABLE v_x_sosi_0_im : t_slv_64_arr(g_nof_signal_inputs-1 DOWNTO 0); BEGIN v := r; + v_in_a_index := r.in_a_index; + v_in_b_index := r.in_b_index; + v_x_sosi_0_re := r.x_sosi_0_re; + v_x_sosi_0_im := r.x_sosi_0_im; -- initiate next block IF r.busy = '0' AND x_sosi_arr(0).sop = '1' THEN v.busy := '1'; @@ -140,22 +136,39 @@ BEGIN ELSIF r.busy = '1' THEN -- Indices counters to select data order IF r.in_b_index < g_nof_signal_inputs - 1 THEN - v.in_b_index := r.in_b_index + 1; + v_in_b_index := r.in_b_index + 1; ELSE - v.in_b_index := 0; + v_in_b_index := 0; IF r.in_a_index < g_nof_signal_inputs - 1 THEN - v.in_a_index := r.in_a_index + 1; + v_in_a_index := r.in_a_index + 1; ELSE - v.in_a_index := 0; + v_in_a_index := 0; END IF; END IF; END IF; -- End of block IF x_sosi_arr(0).eop = '1' THEN v.busy := '0'; - v.in_a_index := 0; - v.in_b_index := 0; + v_in_a_index := 0; + v_in_b_index := 0; END IF; + + -- Capture x_sosi_arr(0) data + v_x_sosi_0_re(v_in_b_index) := x_sosi_arr(0).re; + v_x_sosi_0_im(v_in_b_index) := x_sosi_arr(0).im; + + -- reorder x_sosi_arr(0) data to follow in_a_index instead of in_b_index. All sosi in in_a_sosi_arr are identical. + FOR I IN 0 TO g_nof_streams-1 LOOP + v.in_a_sosi_arr(I) := x_sosi_arr(0); + v.in_a_sosi_arr(I).re := v_x_sosi_0_re(v_in_a_index); + v.in_a_sosi_arr(I).im := v_x_sosi_0_im(v_in_a_index); + END LOOP; + + v.in_a_index := v_in_a_index; + v.in_b_index := v_in_b_index; + v.x_sosi_0_re := v_x_sosi_0_re; + v.x_sosi_0_im := v_x_sosi_0_im; + nxt_r <= v; END PROCESS; diff --git a/libraries/dsp/st/st.peripheral.yaml b/libraries/dsp/st/st.peripheral.yaml index d812b3ac307a4df560f42471719512de0907a2c2..23b11ddf8086194ade628fc1ec8e98d84e14d0b3 100644 --- a/libraries/dsp/st/st.peripheral.yaml +++ b/libraries/dsp/st/st.peripheral.yaml @@ -104,3 +104,36 @@ peripherals: mm_width: 32 user_width: g_stat_data_w radix: uint64 + + + - peripheral_name: st_xst_for_sdp # pi_st_xst.py + peripheral_description: | + "Calculate Crosslets Statistics during a sync interval for the crosslets statistics (XST) in LOFAR2.0 SDP" + parameters: + # Parameters of pi_st_xst.py, fixed in node_sdp_correlator.vhd / sdp_pkg.vhd + - { name: g_nof_streams, value: 9 } # P_sq + # Parameters of st_xst.vhd, fixed in node_sdp_correlator.vhd / sdp_pkg.vhd + - { name: g_nof_crosslets, value: 1 } # N_crosslets + - { name: g_nof_signal_inputs, value: 12 } # S_pn = 12 + - { name: g_in_data_w, value: 16 } # W_crosslet = 16 + - { name: g_stat_data_w, value: 64 } # W_statistic = 64 + - { name: g_stat_data_sz, value: 2 } # W_statistic_sz = 2 + mm_ports: + # MM port for st_sst.vhd + - mm_port_name: RAM_ST_XSQ + mm_port_type: RAM + mm_port_description: | + "The crosslets statistics per PN are stored in 1 block of + g_nof_crosslets * g_nof_signal_inputs**2 * c_nof_complex * g_stat_data_sz = 1 * 12 * 12 * 2 * 2 = 576 values as: + + (cint64)XST[] = (cint64)XST[crosslets][in A][in B][complex][word]" + + number_of_mm_ports: 1 + fields: + - - field_name: power + field_description: "" + number_of_fields: 576 + address_offset: 0x0 + mm_width: 32 + user_width: g_stat_data_w + radix: cint64_ir diff --git a/libraries/dsp/wpfb/src/vhdl/wpfb_unit_dev.vhd b/libraries/dsp/wpfb/src/vhdl/wpfb_unit_dev.vhd index 5188d93bd2cc1cc01f51cedbd5974a3e48a9eb5e..e63d1860dc244929c83b99be41d886fefff7c7cf 100644 --- a/libraries/dsp/wpfb/src/vhdl/wpfb_unit_dev.vhd +++ b/libraries/dsp/wpfb/src/vhdl/wpfb_unit_dev.vhd @@ -365,7 +365,8 @@ entity wpfb_unit_dev is g_use_prefilter : boolean := TRUE; g_stats_ena : boolean := TRUE; -- Enables the statistics unit g_use_bg : boolean := FALSE; - g_coefs_file_prefix : string := "data/coefs_wide" -- File prefix for the coefficients files. + g_coefs_file_prefix : string := "data/coefs_wide"; -- File prefix for the coefficients files. + g_restart_on_valid : boolean := TRUE ); port ( dp_rst : in std_logic := '0'; @@ -383,7 +384,7 @@ entity wpfb_unit_dev is in_sosi_arr : in t_dp_sosi_arr(g_wpfb.nof_wb_streams*g_wpfb.wb_factor-1 downto 0); fil_sosi_arr : out t_dp_sosi_arr(g_wpfb.nof_wb_streams*g_wpfb.wb_factor-1 downto 0); out_sosi_arr : out t_dp_sosi_arr(g_wpfb.nof_wb_streams*g_wpfb.wb_factor-1 downto 0); - dp_bsn_source_restart : in std_logic + dp_bsn_source_restart : in std_logic := '0' ); end entity wpfb_unit_dev; @@ -466,7 +467,11 @@ begin begin v := r; v.in_sosi_arr := in_sosi_arr; - v.bsn_source_restart := dp_bsn_source_restart; + IF g_restart_on_valid THEN + v.bsn_source_restart := (NOT r.in_sosi_arr(0).valid) AND in_sosi_arr(0).valid; + ELSE + v.bsn_source_restart := dp_bsn_source_restart; + END IF; rin <= v; end process comb; diff --git a/libraries/dsp/wpfb/tb/vhdl/tb_wpfb_unit_dev.vhd b/libraries/dsp/wpfb/tb/vhdl/tb_wpfb_unit_dev.vhd index 61eb02d33154f9d5913df6b2ca23e7f768f61a5b..f789359e1d3410443b43e3e84fa048ff4c21290c 100644 --- a/libraries/dsp/wpfb/tb/vhdl/tb_wpfb_unit_dev.vhd +++ b/libraries/dsp/wpfb/tb/vhdl/tb_wpfb_unit_dev.vhd @@ -330,8 +330,7 @@ BEGIN ram_bg_data_mosi => ram_diag_bg_pfb_mosi, ram_bg_data_miso => ram_diag_bg_pfb_miso, in_sosi_arr => bg_sosi_arr, - out_sosi_arr => out_sosi_arr, - dp_bsn_source_restart => bg_sosi_arr(0).sync + out_sosi_arr => out_sosi_arr ); time_map : process is diff --git a/libraries/dsp/wpfb/tb/vhdl/tb_wpfb_unit_wide.vhd b/libraries/dsp/wpfb/tb/vhdl/tb_wpfb_unit_wide.vhd index bf8e6cb17e5dfd61f20376510f7a5174c379d400..d385e8f7cfe41cbcfee9ae6e1713c7d263d71383 100644 --- a/libraries/dsp/wpfb/tb/vhdl/tb_wpfb_unit_wide.vhd +++ b/libraries/dsp/wpfb/tb/vhdl/tb_wpfb_unit_wide.vhd @@ -486,8 +486,7 @@ begin ram_bg_data_miso => open, in_sosi_arr => in_sosi_arr, fil_sosi_arr => fil_sosi_arr, - out_sosi_arr => out_sosi_arr, - dp_bsn_source_restart => in_sosi_arr(0).sync + out_sosi_arr => out_sosi_arr ); p_fil_sosi_arr : process(fil_sosi_arr)