diff --git a/applications/lofar2/libraries/sdp/src/vhdl/sdp_bdo_multiple_destinations.vhd b/applications/lofar2/libraries/sdp/src/vhdl/sdp_bdo_multiple_destinations.vhd index 9490efb8b0dee55a582acceef05f50a17bc198af..bf435936327d4cec914de36843cdb0103dccb0c9 100644 --- a/applications/lofar2/libraries/sdp/src/vhdl/sdp_bdo_multiple_destinations.vhd +++ b/applications/lofar2/libraries/sdp/src/vhdl/sdp_bdo_multiple_destinations.vhd @@ -22,7 +22,8 @@ -- Purpose: -- Construct beamformer data output (BDO) payloads for multiple destinations. -- Description: --- Merge, reorder and unmerge beamlet data for N_destinations > 1 from: +-- * Get N_destinations from sdp_bdo_destinations_reg. +-- * Merge, reorder and unmerge beamlet data for N_destinations > 1 from: -- (int8) [t] [N_blocks_per_packet][S_sub_bf / N_destinations] [N_pol_bf][N_complex] -- to: -- (int8) [t] [S_sub_bf / N_destinations][N_blocks_per_packet] [N_pol_bf][N_complex] @@ -50,41 +51,75 @@ entity sdp_bdo_multiple_destinations is g_use_transpose : boolean := false ); port ( + mm_clk : in std_logic; + mm_rst : in std_logic; + dp_clk : in std_logic; dp_rst : in std_logic; + reg_destinations_copi : in t_mem_copi; + reg_destinations_cipo : out t_mem_cipo; + + destinations_info : out t_sdp_bdo_destinations_info; + snk_in : in t_dp_sosi; src_out : out t_dp_sosi ); end sdp_bdo_multiple_destinations; architecture str of sdp_bdo_multiple_destinations is - -- Reorder c_nof_ch = c_nof_ch_sel = c_nof_ch_in constant c_nof_blocks_per_packet : natural := c_sdp_cep_nof_blocks_per_packet; -- = 4 constant c_nof_beamlets_per_block : natural := c_sdp_S_sub_bf; -- = 488 dual pol beamlets constant c_nof_words_per_beamlet : natural := 1; -- 1 dual pol beamlet data per 32b word - constant c_nof_ch : natural := c_nof_blocks_per_packet * c_nof_beamlets_per_block * c_nof_words_per_beamlet; -- = 1952 - - -- Use c_transpose_indices and c_transpose_indices_inv for debug view in Objects window. - -- Use c_transpose_indices for func_reorder_transpose() in this sdp_bdo_multiple_destinations, - -- a tb can then use c_transpose_indices_inv to undo the transpose. - constant c_transpose_indices : t_natural_arr(0 to c_nof_ch - 1) := - func_reorder_transpose_indices(c_nof_blocks_per_packet, - c_nof_beamlets_per_block, - c_nof_words_per_beamlet); - constant c_transpose_indices_inv : t_natural_arr(0 to c_nof_ch - 1) := - func_reorder_transpose_indices(c_nof_beamlets_per_block, - c_nof_blocks_per_packet, - c_nof_words_per_beamlet); - - -- Dynamic reorder block size control input - -- . The data consists of 1 word = 1 ch, because 1 word contains 1 dual pol beamlet. - -- . The input packet has nof_ch of data per packet. - -- . The transposed output packet will have blocks with nof_blocks_per_packet - -- data per block and nof_beamlets_per_block blocks per packet. - signal nof_ch : natural := c_nof_ch; - signal nof_blocks_per_packet : natural := c_nof_blocks_per_packet; - signal nof_beamlets_per_block : natural := c_nof_beamlets_per_block; + + -- Reorder c_nof_ch = c_nof_ch_sel = c_nof_ch_in + constant c_reorder_nof_blocks_max : natural := c_sdp_bdo_reorder_nof_blocks_max; -- = 16 + constant c_reorder_nof_blocks_w : natural := ceil_log2(c_reorder_nof_blocks_max + 1); + constant c_reorder_nof_ch_max : natural := c_reorder_nof_blocks_max * + c_nof_beamlets_per_block * + c_nof_words_per_beamlet; -- = 7808 + + -- Look up table constants as function of N_destinations + constant c_m : natural := c_sdp_bdo_nof_destinations_max; -- 16 + constant c_nof_blocks_per_packet_arr : t_natural_arr(1 to c_m) := func_sdp_bdo_nof_blocks_per_packet_look_up_table; + constant c_reorder_nof_blocks_arr : t_natural_arr(1 to c_m) := func_sdp_bdo_reorder_nof_blocks_look_up_table; + constant c_reorder_nof_ch_arr : t_natural_arr(1 to c_m) := func_sdp_bdo_reorder_nof_ch_look_up_table; + constant c_nof_beamlets_per_block_first_destination_arr : t_natural_arr(1 to c_m) := func_sdp_sdo_nof_beamlets_per_block_first_destination_look_up_table; + constant c_nof_beamlets_per_block_last_destination_arr : t_natural_arr(1 to c_m) := func_sdp_sdo_nof_beamlets_per_block_last_destination_look_up_table; + constant c_sdp_sdo_nof_ch_per_packet_first_destination_arr : t_natural_arr(1 to c_m) := func_sdp_sdo_nof_ch_per_packet_first_destination_look_up_table; + constant c_sdp_sdo_nof_ch_per_packet_last_destination_arr : t_natural_arr(1 to c_m) := func_sdp_sdo_nof_ch_per_packet_last_destination_look_up_table; + + constant c_beamlet_index_per_destination_mat : t_natural_matrix(1 to c_m, 0 to c_m - 1) := + func_sdp_sdo_beamlet_index_per_destination_look_up_matrix; + +-- -- Use c_transpose_indices and c_transpose_indices_inv for debug view in Objects window. +-- -- Use c_transpose_indices for func_reorder_transpose() in this sdp_bdo_multiple_destinations, +-- -- a tb can then use c_transpose_indices_inv to undo the transpose. +-- constant c_transpose_indices : t_natural_arr(0 to c_nof_ch - 1) := +-- func_reorder_transpose_indices(c_nof_blocks_per_packet, +-- c_nof_beamlets_per_block, +-- c_nof_words_per_beamlet); +-- constant c_transpose_indices_inv : t_natural_arr(0 to c_nof_ch - 1) := +-- func_reorder_transpose_indices(c_nof_beamlets_per_block, +-- c_nof_blocks_per_packet, +-- c_nof_words_per_beamlet); + + signal i_destinations_info : t_sdp_bdo_destinations_info; + + -- Dynamic merge, reorder, unmerge packet sizes + -- . default use values for N_destinations = 1 + signal nof_blocks_per_packet : natural := c_nof_blocks_per_packet_arr(1); + signal reorder_nof_blocks : natural := c_reorder_nof_blocks_arr(1); + signal reorder_nof_blocks_slv : std_logic_vector(c_reorder_nof_blocks_w - 1 downto 0); + signal reorder_nof_ch : natural := c_reorder_nof_ch_arr(1); + signal nof_beamlets_per_block_first_destination : natural := c_nof_beamlets_per_block_first_destination_arr(1); + signal nof_beamlets_per_block_last_destination : natural := c_nof_beamlets_per_block_last_destination_arr(1); + signal nof_beamlets_per_block : natural; + signal nof_ch_per_packet_first_destination : natural := c_sdp_sdo_nof_ch_per_packet_first_destination_arr(1); + signal nof_ch_per_packet_last_destination : natural := c_sdp_sdo_nof_ch_per_packet_last_destination_arr(1); + -- . default use values for N_destinations = 1 and destination index = 0 + signal beamlet_index_per_destination : natural := c_beamlet_index_per_destination_mat(1, 0); + signal select_copi : t_mem_copi := c_mem_copi_rst; signal select_cipo : t_mem_cipo := c_mem_cipo_rst; signal r_identity : t_reorder_identity; @@ -97,21 +132,74 @@ architecture str of sdp_bdo_multiple_destinations is signal reorder_src_out : t_dp_sosi; signal reorder_word : t_sdp_dual_pol_beamlet_in_word; signal reorder_busy : std_logic; + signal unmerge_src_out : t_dp_sosi; + signal unmerge_word : t_sdp_dual_pol_beamlet_in_word; begin - src_out <= reorder_src_out; + src_out <= unmerge_src_out; + destinations_info <= i_destinations_info; + + ----------------------------------------------------------------------------- + -- Multiple destinations info register + ----------------------------------------------------------------------------- + -- Use dynamic sizes for beamlet data output to multiple destination. + u_sdp_bdo_destinations_reg : entity work.sdp_bdo_destinations_reg + port map ( + -- Clocks and reset + mm_clk => mm_clk, + mm_rst => mm_rst, + + dp_clk => dp_clk, + dp_rst => dp_rst, + + reg_copi => reg_destinations_copi, + reg_cipo => reg_destinations_cipo, + + -- sdp info + destinations_info => i_destinations_info + ); + + ----------------------------------------------------------------------------- + -- Multiple destinations info look up values + ----------------------------------------------------------------------------- + -- Pipeline values from look up tables to ease timing closure + p_pipeline : process(dp_clk) + variable v_DN : natural; -- number of destinations + variable v_DI : natural; -- destination index + begin + if rising_edge(dp_clk) then + v_DN := i_destinations_info.nof_destinations_act; + nof_blocks_per_packet <= i_destinations_info.nof_blocks_per_packet_act; + reorder_nof_blocks <= c_reorder_nof_blocks_arr(v_DN); + reorder_nof_ch <= c_reorder_nof_ch_arr(v_DN); + nof_beamlets_per_block_first_destination <= c_nof_beamlets_per_block_first_destination_arr(v_DN); + nof_beamlets_per_block_last_destination <= c_nof_beamlets_per_block_last_destination_arr(v_DN); + v_DI := 0; + beamlet_index_per_destination <= c_beamlet_index_per_destination_mat(v_DN, v_DI); + end if; + end process; + + nof_beamlets_per_block <= nof_beamlets_per_block_first_destination; ----------------------------------------------------------------------------- -- dp_packet_merge ----------------------------------------------------------------------------- + -- Use slv in port map to avoid vcom-1436: Actual expression (function call + -- "TO_UVEC") of formal "nof_pkt" is not globally static. + reorder_nof_blocks_slv <= to_uvec(reorder_nof_blocks, c_reorder_nof_blocks_w); + u_dp_packet_merge : entity dp_lib.dp_packet_merge generic map( g_use_ready => false, -- no flow control - g_nof_pkt => c_nof_blocks_per_packet, + g_nof_pkt => c_reorder_nof_blocks_max, g_bsn_increment => 1 ) port map( rst => dp_rst, clk => dp_clk, + + nof_pkt => reorder_nof_blocks_slv, + nof_pkt_out => open, -- Valid at src_out.sop + snk_in => snk_in, src_out => merge_src_out ); @@ -127,8 +215,8 @@ begin u_reorder_col_select : entity reorder_lib.reorder_col_select generic map ( g_dsp_data_w => c_sdp_W_dual_pol_beamlet / c_nof_complex, -- = 32b / 2 - g_nof_ch_in => c_nof_ch, - g_nof_ch_sel => c_nof_ch, + g_nof_ch_in => c_reorder_nof_ch_max, + g_nof_ch_sel => c_reorder_nof_ch_max, g_use_complex => false ) port map ( @@ -138,8 +226,8 @@ begin reorder_busy => reorder_busy, -- Dynamic reorder block size control input - nof_ch_in => nof_ch, - nof_ch_sel => nof_ch, + nof_ch_in => reorder_nof_ch, + nof_ch_sel => reorder_nof_ch, -- Captured reorder block size control used for output_sosi output_nof_ch_in => open, @@ -169,12 +257,12 @@ begin -- Pass on beamlet data in original order or in transposed order select_copi <= r_transpose.select_copi when g_use_transpose else r_identity.select_copi; - p_reorder_identity : process(dp_rst, select_cipo, nof_ch, r_identity) + p_reorder_identity : process(dp_rst, select_cipo, reorder_nof_ch, r_identity) variable v : t_reorder_identity; begin if select_cipo.waitrequest = '0' then -- Read from reorder_col_select page - v := func_reorder_identity(nof_ch, r_identity); + v := func_reorder_identity(reorder_nof_ch, r_identity); else -- No read, new reorder_col_select page not available yet v := c_reorder_identity_rst; @@ -202,4 +290,29 @@ begin end if; d_transpose <= v; end process; + + ----------------------------------------------------------------------------- + -- dp_packet_unmerge for N_destinations + ----------------------------------------------------------------------------- + u_dp_packet_unmerge : entity dp_lib.dp_packet_unmerge + generic map ( + g_use_ready => false, -- no flow control + g_nof_pkt_max => c_reorder_nof_blocks_max, + g_pkt_len => 99, -- Length of the unmerged packets + g_bsn_increment => 1 + ) + port map ( + rst => dp_rst, + clk => dp_clk, + + snk_in => reorder_src_out, + src_out => unmerge_src_out + ); + + -- TODO: + -- . add dynamic pkt_len input port + -- . support unmerge of pkt_len and remaining last packet shorter than pkt_len. + + -- Debug signals for view in Wave window + unmerge_word <= unpack_data(unmerge_src_out.data(c_sdp_W_dual_pol_beamlet - 1 downto 0)); end str;