diff --git a/libraries/base/dp/tb/vhdl/tb_dp_pkg.vhd b/libraries/base/dp/tb/vhdl/tb_dp_pkg.vhd index 3413d449e7dc43da01dac2132ae06d389a31544d..b52ebc9b105bae41ed196fa9caf775d93cda504a 100644 --- a/libraries/base/dp/tb/vhdl/tb_dp_pkg.vhd +++ b/libraries/base/dp/tb/vhdl/tb_dp_pkg.vhd @@ -450,6 +450,10 @@ package tb_dp_pkg is signal dut_sosi : in t_dp_sosi_integer; -- use func_dp_stream_slv_to_integer for conversion signal exp_sosi : in t_dp_sosi_integer); -- use func_dp_stream_slv_to_integer for conversion + procedure proc_dp_verify_sosi_equal(constant c_use_complex : in boolean; + signal dut_sosi : in t_dp_sosi; + signal exp_sosi : in t_dp_sosi); + procedure proc_dp_verify_valid(constant c_ready_latency : in natural; signal clk : in std_logic; signal verify_en : in std_logic; @@ -2261,6 +2265,32 @@ package body tb_dp_pkg is end if; end proc_dp_verify_sosi_equal; + procedure proc_dp_verify_sosi_equal(constant c_use_complex : in boolean; + signal dut_sosi : in t_dp_sosi; + signal exp_sosi : in t_dp_sosi) is + begin + assert dut_sosi.sync = exp_sosi.sync report "Wrong dut_sosi.sync" severity ERROR; + assert dut_sosi.sop = exp_sosi.sop report "Wrong dut_sosi.sop" severity ERROR; + assert dut_sosi.eop = exp_sosi.eop report "Wrong dut_sosi.eop" severity ERROR; + assert dut_sosi.valid = exp_sosi.valid report "Wrong dut_sosi.valid" severity ERROR; + if exp_sosi.sop = '1' then + assert dut_sosi.bsn = exp_sosi.bsn report "Wrong dut_sosi.bsn" severity ERROR; + assert dut_sosi.channel = exp_sosi.channel report "Wrong dut_sosi.channel" severity ERROR; + end if; + if exp_sosi.eop = '1' then + assert dut_sosi.empty = exp_sosi.empty report "Wrong dut_sosi.empty" severity ERROR; + assert dut_sosi.err = exp_sosi.err report "Wrong dut_sosi.err" severity ERROR; + end if; + if exp_sosi.valid = '1' then + if c_use_complex then + assert dut_sosi.re = exp_sosi.re report "Wrong dut_sosi.re" severity ERROR; + assert dut_sosi.im = exp_sosi.im report "Wrong dut_sosi.im" severity ERROR; + else + assert dut_sosi.data = exp_sosi.data report "Wrong dut_sosi.data" severity ERROR; + end if; + end if; + end proc_dp_verify_sosi_equal; + ------------------------------------------------------------------------------ -- PROCEDURE: Verify the DUT output valid ------------------------------------------------------------------------------ diff --git a/libraries/base/reorder/hdllib.cfg b/libraries/base/reorder/hdllib.cfg index 2f5353878ee6356ca89876905375690e860d7c0e..d7fa2674a8ec6283693d91a54b40528c8abddaf9 100644 --- a/libraries/base/reorder/hdllib.cfg +++ b/libraries/base/reorder/hdllib.cfg @@ -1,8 +1,8 @@ hdl_lib_name = reorder hdl_library_clause_name = reorder_lib -hdl_lib_uses_synth = common dp +hdl_lib_uses_synth = common dp hdl_lib_uses_sim = io_ddr tech_ddr -hdl_lib_technology = +hdl_lib_technology = # Description: see doc/ss_parallel.pdf # @@ -32,15 +32,15 @@ hdl_lib_technology = # synth_files = - src/vhdl/reorder_pkg.vhd + src/vhdl/reorder_pkg.vhd src/vhdl/reorder_retreive.vhd src/vhdl/reorder_store.vhd src/vhdl/reorder_col.vhd src/vhdl/reorder_col_select.vhd src/vhdl/reorder_col_wide.vhd src/vhdl/reorder_col_wide_select.vhd - src/vhdl/reorder_row.vhd - src/vhdl/reorder_row_select.vhd + src/vhdl/reorder_row.vhd + src/vhdl/reorder_row_select.vhd src/vhdl/reorder_matrix.vhd src/vhdl/reorder_sequencer.vhd src/vhdl/reorder_transpose.vhd @@ -48,20 +48,23 @@ synth_files = src/vhdl/reorder_rewire_reg.vhd src/vhdl/mms_reorder_rewire.vhd -test_bench_files = +test_bench_files = tb/vhdl/tb_reorder_transpose.vhd tb/vhdl/tb_reorder_col.vhd - tb/vhdl/tb_tb_reorder_col.vhd - tb/vhdl/tb_reorder_col_wide.vhd - tb/vhdl/tb_reorder_col_wide_row_select.vhd - tb/vhdl/tb_tb_reorder_col_wide_row_select.vhd - tb/vhdl/tb_mmf_reorder_matrix.vhd - tb/vhdl/tb_mmf_reorder_row.vhd + tb/vhdl/tb_tb_reorder_col.vhd + tb/vhdl/tb_reorder_col_wide.vhd + tb/vhdl/tb_reorder_col_wide_row_select.vhd + tb/vhdl/tb_tb_reorder_col_wide_row_select.vhd + tb/vhdl/tb_mmf_reorder_matrix.vhd + tb/vhdl/tb_mmf_reorder_row.vhd tb/vhdl/tb_mms_reorder_rewire.vhd + tb/vhdl/tb_reorder_col_select_all.vhd + tb/vhdl/tb_tb_reorder_col_select_all.vhd -regression_test_vhdl = - tb/vhdl/tb_tb_reorder_col_wide_row_select.vhd - tb/vhdl/tb_tb_reorder_col.vhd +regression_test_vhdl = + tb/vhdl/tb_tb_reorder_col_wide_row_select.vhd + tb/vhdl/tb_tb_reorder_col.vhd + tb/vhdl/tb_tb_reorder_col_select_all.vhd [modelsim_project_file] diff --git a/libraries/base/reorder/src/vhdl/reorder_col.vhd b/libraries/base/reorder/src/vhdl/reorder_col.vhd index 1c7d65153afef4e1f2914b7668155f9e678f48cb..79db37a81aaa790655ad3901b2f5fe2e61eddeb4 100644 --- a/libraries/base/reorder/src/vhdl/reorder_col.vhd +++ b/libraries/base/reorder/src/vhdl/reorder_col.vhd @@ -50,19 +50,19 @@ -- is assumed that the reorder_col source is always fast enough. The reorder_col sink could -- support the input_siso signal, e.g. based on store_done and retrieve_done. -library IEEE, common_lib, technology_lib, dp_lib; +library IEEE, common_lib, dp_lib; use IEEE.std_logic_1164.all; use IEEE.numeric_std.all; use common_lib.common_pkg.all; use common_lib.common_mem_pkg.all; use dp_lib.dp_stream_pkg.all; -use technology_lib.technology_select_pkg.all; entity reorder_col is generic ( - g_technology : natural := c_tech_select_default; - g_use_output_rl_adapter : boolean := false; -- when true adapt output RL to 1 else the output RL is equal to c_retrieve_lat=2 which is fine if no flow control is needed. - g_dsp_data_w : natural := 18; + -- when true adapt output RL to 1 else the output RL is equal to c_retrieve_lat=2 which + -- is fine if no flow control is needed. + g_use_output_rl_adapter : boolean := false; + g_dsp_data_w : natural := 18; -- complex data width, = c_data_w / 2 g_nof_ch_in : natural := 512; g_nof_ch_sel : natural := 252; -- g_nof_ch_sel < g_nof_ch_in g_select_file_name : string := "UNUSED"; @@ -87,12 +87,12 @@ entity reorder_col is ); end reorder_col; - architecture str of reorder_col is + constant c_data_w : natural := c_nof_complex * g_dsp_data_w; constant c_store_buf : t_c_mem := (latency => 1, adr_w => ceil_log2(g_nof_ch_in), - dat_w => c_nof_complex * g_dsp_data_w, + dat_w => c_data_w, nof_dat => g_nof_ch_in, init_sl => '0'); -- ST side : stat_mosi @@ -106,10 +106,12 @@ architecture str of reorder_col is constant c_info_nof_pages : natural := 2; -- fixed, fits the dual page block latency and logic latency of the SS constant c_retrieve_lat : natural := c_select_buf.latency + c_store_buf.latency; -- = 2 - constant c_output_rl : natural := sel_a_b(g_use_output_rl_adapter, 1, c_retrieve_lat); -- force SS RL from 2 -> 1 or leave it at 2 + -- force output ready latency (RL) from 2 -> 1 or leave it at 2 + constant c_output_rl : natural := sel_a_b(g_use_output_rl_adapter, 1, c_retrieve_lat); signal info_sop_wr_en : std_logic_vector(c_info_nof_pages - 1 downto 0); signal info_eop_wr_en : std_logic_vector(c_info_nof_pages - 1 downto 0); + signal info_sosi_paged : t_dp_sosi; signal info_sosi : t_dp_sosi; signal store_mosi : t_mem_mosi; @@ -122,11 +124,9 @@ architecture str of reorder_col is signal select_mosi : t_mem_mosi := c_mem_mosi_rst; signal select_miso : t_mem_miso := c_mem_miso_rst; - signal retrieve_sosi : t_dp_sosi; - signal retrieve_siso : t_dp_siso; - - signal ss_sosi : t_dp_sosi; - signal ss_siso : t_dp_siso; + signal retrieve_info_sosi : t_dp_sosi; + signal retrieve_sosi : t_dp_sosi; + signal retrieve_siso : t_dp_siso; begin @@ -157,17 +157,14 @@ begin -- Streaming input_sosi => input_sosi, - -- Timing store_done => store_done, - -- Write store buffer control store_mosi => store_mosi ); u_store_buf : entity common_lib.common_paged_ram_r_w generic map ( - g_technology => g_technology, g_str => "use_adr", g_data_w => c_store_buf.dat_w, g_nof_pages => c_data_nof_pages, @@ -192,7 +189,6 @@ begin u_select_buf : entity common_lib.common_ram_crw_crw generic map ( - g_technology => g_technology, g_ram => c_select_buf, g_init_file => g_select_file_name ) @@ -244,23 +240,8 @@ begin output_siso => retrieve_siso ); - u_rl : entity dp_lib.dp_latency_adapter -- defaults to wires when c_output_rl = c_retrieve_lat - generic map ( - g_in_latency => c_retrieve_lat, - g_out_latency => c_output_rl - ) - port map ( - rst => dp_rst, - clk => dp_clk, - -- ST sink - snk_out => retrieve_siso, - snk_in => retrieve_sosi, - -- ST source - src_in => ss_siso, - src_out => ss_sosi - ); - - -- Page delay the input_sosi info (sync, BSN, channel at sop and err, empty at eop) and combine it with the retrieved SS data to get the output_sosi + -- Page delay the input_sosi info (sync, BSN, channel at sop and err, empty at eop) and combine + -- it with the retrieved SS data to get the output_sosi. info_sop_wr_en <= input_sosi.sop & store_done; info_eop_wr_en <= input_sosi.eop & store_done; @@ -277,11 +258,30 @@ begin -- ST sink snk_in => input_sosi, -- ST source - src_out => info_sosi + src_out => info_sosi_paged ); - output_sosi <= func_dp_stream_combine_info_and_data(info_sosi, ss_sosi); - ss_siso <= output_siso; + -- Account for retrieve rd latency is 1, for sop related info it is not + -- critical that it arrives early, but for eop related info it is. + info_sosi <= info_sosi_paged when rising_edge(dp_clk); + retrieve_info_sosi <= func_dp_stream_combine_info_and_data(info_sosi, retrieve_sosi); + + -- Adapt output ready latency (RL), defaults to wires when c_output_rl = c_retrieve_lat + u_rl : entity dp_lib.dp_latency_adapter + generic map ( + g_in_latency => c_retrieve_lat, + g_out_latency => c_output_rl + ) + port map ( + rst => dp_rst, + clk => dp_clk, + -- ST sink + snk_out => retrieve_siso, + snk_in => retrieve_info_sosi, + -- ST source + src_in => output_siso, + src_out => output_sosi + ); end str; diff --git a/libraries/base/reorder/src/vhdl/reorder_col_select.vhd b/libraries/base/reorder/src/vhdl/reorder_col_select.vhd index 5e69d2e04f881e43a0e42e5902ce24bbb6043c64..2fd6d8d3694f35d66d7c5f4b18ae8274355830da 100644 --- a/libraries/base/reorder/src/vhdl/reorder_col_select.vhd +++ b/libraries/base/reorder/src/vhdl/reorder_col_select.vhd @@ -22,85 +22,126 @@ -- Author : R vd Walle -- Purpose: Reorder block of data in time -- Description: --- Select g_nof_ch_sel complex samples from an input block of g_nof_ch_in --- complex samples. The subband select map is arbitrary (any order and also --- duplicates) and can be set via the MM interface. --- The timing of sync and BSN is passed on in parallel. +-- . Select nof_ch_sel samples from an input block of nof_ch_in samples using +-- a dual page buffer. The input select map is arbitrary (any order and also +-- duplicates) and can be set via the col_select_mosi/miso MM interface. +-- . Maximum size for the dual page buffer is g_nof_ch_in. Default nof_ch_in +-- = g_nof_ch_in, but it can used with smaller reorder block sizes. +-- . New nof_ch_in and nof_ch_sel are accepted when reorder_busy = '0'. The +-- output_nof_ch_in and output_nof_ch_sel show the counts that are used. +-- . The reorder_busy goes high at input_sosi.sop, remains high while either +-- store_busy and retrieve_busy are active, and goes low after retrieve_busy +-- goes inactive. In practise this means that reorder_busy goes low after the +-- last output_sosi.eop, when the input_sosi has created a sufficiently long +-- interpacket gap. +-- . The timing of sync and BSN is passed on in parallel. -- Remarks: --- . The g_nof_ch_sel can be <= g_nof_ch_in <= period size, where g_nof_ch_in --- is the number of valid samples from sop to eop. If g_nof_ch_in is equal to --- the period size then there are no data invalid cycles during a period. --- Note that if g_nof_ch_in is less than the period size, then g_nof_ch_sel --- can be larger than g_nof_ch_in to select channels multiple times. --- . The g_nof_ch_in defines the number of complex input data words in a data --- period, so 1 complex sample via sosi.im and sosi.re. +-- . The nof_ch_sel <= period size and nof_ch_in <= period size, where period +-- size is the time between input_sosi.sop, so 1/block rate. +-- . The nof_ch_in is the number of valid samples from input_sosi.sop to +-- input_sosi.eop. If nof_ch_in is equal to the period size, then there are +-- no data invalid input_sosi.valid cycles during a period. +-- . The nof_ch_sel is the number of valid samples from output_sosi.sop to +-- output_sosi.eop. If nof_ch_sel is equal to the period size then there are +-- no data invalid output_sosi.valid cycles during a period. +-- Note that if nof_ch_in is less than the period size, then nof_ch_sel +-- can be larger than nof_ch_in to select some channels multiple times. +-- . The nof_ch_in defines the number of (complex) input data words in a +-- data period, so 1 sample via sosi.data or via sosi.im and sosi.re, +-- dependent on g_use_complex. -- . Verified in tb_reorder_col_wide_row_select.vhd via reorder_col_wide_select -- that has g_nof_inputs instances of reorder_col_select. -library IEEE, common_lib, technology_lib, dp_lib; +library IEEE, common_lib, dp_lib; use IEEE.std_logic_1164.all; use IEEE.numeric_std.all; use common_lib.common_pkg.all; use common_lib.common_mem_pkg.all; use dp_lib.dp_stream_pkg.all; -use technology_lib.technology_select_pkg.all; entity reorder_col_select is generic ( - g_technology : natural := c_tech_select_default; - g_dsp_data_w : natural := 18; + g_dsp_data_w : natural := 18; -- complex data width, = c_data_w / 2 g_nof_ch_in : natural := 1024; - g_nof_ch_sel : natural := 12; -- g_nof_ch_sel < g_nof_ch_in + g_nof_ch_sel : natural := 12; g_use_complex : boolean := true ); port ( dp_rst : in std_logic; dp_clk : in std_logic; + reorder_busy : out std_logic; + + -- Dynamic reorder block size control input + nof_ch_in : in natural range 0 to g_nof_ch_in := g_nof_ch_in; + nof_ch_sel : in natural range 0 to g_nof_ch_sel := g_nof_ch_sel; + + -- Captured reorder block size control used for output_sosi + output_nof_ch_in : out natural; + output_nof_ch_sel : out natural; + -- Memory Mapped - col_select_mosi : in t_mem_mosi; -- channel select control on DP clk - col_select_miso : out t_mem_miso := c_mem_miso_rst; -- only waitrequest is used + col_select_mosi : in t_mem_mosi; -- channel select control + col_select_miso : out t_mem_miso := c_mem_miso_rst; -- only used for waitrequest -- Streaming - input_sosi : in t_dp_sosi; -- complex input - - output_sosi : out t_dp_sosi -- selected complex output with flow control + input_sosi : in t_dp_sosi; + output_sosi : out t_dp_sosi ); end reorder_col_select; - architecture str of reorder_col_select is + constant c_data_w : natural := c_nof_complex * g_dsp_data_w; constant c_store_buf : t_c_mem := (latency => 1, adr_w => ceil_log2(g_nof_ch_in), - dat_w => c_nof_complex * g_dsp_data_w, + dat_w => c_data_w, nof_dat => g_nof_ch_in, init_sl => '0'); -- ST side : stat_mosi - constant c_data_nof_pages : natural := 2; -- fixed dual page SS constant c_info_nof_pages : natural := 2; -- fixed, fits the dual page block latency and logic latency of the SS constant c_retrieve_lat : natural := c_store_buf.latency + 1; -- = 2 rd_latency from waitrequest + store_buf latency - signal info_sop_wr_en : std_logic_vector(c_info_nof_pages - 1 downto 0); - signal info_eop_wr_en : std_logic_vector(c_info_nof_pages - 1 downto 0); - signal info_sosi : t_dp_sosi; + signal input_sosi_reg : t_dp_sosi := c_dp_sosi_rst; -- register input_sosi to ease timing closure for reorder_busy + + signal info_sop_wr_en : std_logic_vector(c_info_nof_pages - 1 downto 0); + signal info_eop_wr_en : std_logic_vector(c_info_nof_pages - 1 downto 0); + signal info_sosi_paged : t_dp_sosi; + signal info_sosi : t_dp_sosi := c_dp_sosi_rst; - signal store_mosi : t_mem_mosi; - signal store_done : std_logic; + signal store_mosi : t_mem_mosi; + signal store_done : std_logic; signal i_col_select_miso : t_mem_miso := c_mem_miso_rst; - signal ch_cnt : integer range 0 to g_nof_ch_sel - 1; - signal nxt_ch_cnt : integer; - signal retrieve_sosi : t_dp_sosi; - signal retrieve_en : std_logic; - signal retrieve_sop_dly : std_logic_vector(0 to c_retrieve_lat); - signal retrieve_eop_dly : std_logic_vector(0 to c_retrieve_lat); + signal ch_cnt : integer range 0 to g_nof_ch_sel - 1; + signal nxt_ch_cnt : integer; + signal retrieve_sosi : t_dp_sosi; + signal retrieve_en : std_logic; + signal retrieve_sop_dly : std_logic_vector(0 to c_retrieve_lat); + signal retrieve_eop_dly : std_logic_vector(0 to c_retrieve_lat); + + signal store_busy : std_logic; + signal retrieve_busy : std_logic; + signal retrieve_busy_reg : std_logic; + signal nxt_retrieve_busy : std_logic; + signal i_reorder_busy : std_logic; + signal reorder_busy_reg : std_logic; + signal nxt_reorder_busy : std_logic; + signal nof_ch_in_reg : natural; + signal nof_ch_sel_reg : natural; begin + reorder_busy <= i_reorder_busy; + nof_ch_in_reg <= nof_ch_in when rising_edge(dp_clk) and i_reorder_busy = '0'; + nof_ch_sel_reg <= nof_ch_sel when rising_edge(dp_clk) and i_reorder_busy = '0'; + + output_nof_ch_in <= nof_ch_in_reg; + output_nof_ch_sel <= nof_ch_sel_reg; + u_store : entity work.reorder_store generic map ( g_dsp_data_w => g_dsp_data_w, @@ -110,20 +151,19 @@ begin port map ( rst => dp_rst, clk => dp_clk, - + -- Dynamic reorder block size control + nof_ch_in => nof_ch_in_reg, -- Streaming - input_sosi => input_sosi, - + input_sosi => input_sosi_reg, -- Timing + store_busy => store_busy, store_done => store_done, - -- Write store buffer control store_mosi => store_mosi ); u_store_buf : entity common_lib.common_paged_ram_r_w generic map ( - g_technology => g_technology, g_str => "use_adr", g_data_w => c_store_buf.dat_w, g_nof_pages => c_data_nof_pages, @@ -146,7 +186,6 @@ begin rd_val => i_col_select_miso.rdval ); - -- Enable retrieve when a block has been stored, disable retrieve when the block has been output u_retrieve_en : entity common_lib.common_switch generic map ( @@ -163,6 +202,16 @@ begin out_level => retrieve_en ); + -- Determine reorder_busy + nxt_retrieve_busy <= '0' when ch_cnt = 0 and retrieve_en = '0' else '1'; + + retrieve_busy <= nxt_retrieve_busy or retrieve_busy_reg; + + nxt_reorder_busy <= store_busy or retrieve_busy; + + i_reorder_busy <= input_sosi.valid or nxt_reorder_busy or reorder_busy_reg; -- using input_sosi.valid or sop is equivalent here + + -- Registers p_reg : process (dp_clk, dp_rst) begin if dp_rst = '1' then @@ -170,47 +219,56 @@ begin ch_cnt <= 0; retrieve_sop_dly(1 to c_retrieve_lat) <= (others => '0'); retrieve_eop_dly(1 to c_retrieve_lat) <= (others => '0'); + retrieve_busy_reg <= '0'; + reorder_busy_reg <= '0'; elsif rising_edge(dp_clk) then -- Internal registers. + input_sosi_reg <= input_sosi; + info_sosi <= info_sosi_paged; ch_cnt <= nxt_ch_cnt; retrieve_sop_dly(1 to c_retrieve_lat) <= retrieve_sop_dly(0 to c_retrieve_lat - 1); retrieve_eop_dly(1 to c_retrieve_lat) <= retrieve_eop_dly(0 to c_retrieve_lat - 1); + retrieve_busy_reg <= nxt_retrieve_busy; + reorder_busy_reg <= nxt_reorder_busy; end if; end process; - p_ch_cnt : process (retrieve_en, ch_cnt) + -- Count nof_ch_sel clk cycles per output packet, to control col_select_miso.waitrequest + p_ch_cnt : process (retrieve_en, ch_cnt, nof_ch_sel_reg) begin nxt_ch_cnt <= ch_cnt; col_select_miso.waitrequest <= '1'; if retrieve_en = '1' then col_select_miso.waitrequest <= '0'; - if ch_cnt = g_nof_ch_sel - 1 then + if ch_cnt = nof_ch_sel_reg - 1 then nxt_ch_cnt <= 0; else nxt_ch_cnt <= ch_cnt + 1; end if; end if; - end process; -- Optional SS output frame control - retrieve_sop_dly(0) <= '1' when retrieve_en = '1' and ch_cnt = 0 else '0'; - retrieve_eop_dly(0) <= '1' when retrieve_en = '1' and ch_cnt = g_nof_ch_sel - 1 else '0'; + retrieve_sop_dly(0) <= '1' when retrieve_en = '1' and ch_cnt = 0 else '0'; + retrieve_eop_dly(0) <= '1' when retrieve_en = '1' and ch_cnt = nof_ch_sel_reg - 1 else '0'; - retrieve_sosi.re <= RESIZE_DP_DSP_DATA(i_col_select_miso.rddata( g_dsp_data_w - 1 downto 0)); + retrieve_sosi.re <= RESIZE_DP_DSP_DATA(i_col_select_miso.rddata( g_dsp_data_w - 1 downto 0)); retrieve_sosi.im <= RESIZE_DP_DSP_DATA(i_col_select_miso.rddata(c_nof_complex * g_dsp_data_w - 1 downto g_dsp_data_w)); - retrieve_sosi.data <= RESIZE_DP_DATA(i_col_select_miso.rddata( c_nof_complex * g_dsp_data_w - 1 downto 0)); + retrieve_sosi.data <= RESIZE_DP_DATA(i_col_select_miso.rddata(c_data_w - 1 downto 0)); retrieve_sosi.valid <= i_col_select_miso.rdval; - retrieve_sosi.sop <= retrieve_sop_dly(c_retrieve_lat) and i_col_select_miso.rdval; -- Only set sop/eop when valid. + -- Only set sop/eop when valid. + retrieve_sosi.sop <= retrieve_sop_dly(c_retrieve_lat) and i_col_select_miso.rdval; retrieve_sosi.eop <= retrieve_eop_dly(c_retrieve_lat) and i_col_select_miso.rdval; - -- Page delay the input_sosi info (sync, BSN, channel at sop and err, empty at eop) and combine it with the retrieved SS data to get the output_sosi - info_sop_wr_en <= input_sosi.sop & store_done; - info_eop_wr_en <= input_sosi.eop & store_done; + + -- Page delay the input_sosi_reg info (sync, BSN, channel at sop and err, empty at eop) and + -- combine it with the retrieved SS data to get the output_sosi + info_sop_wr_en <= input_sosi_reg.sop & store_done; + info_eop_wr_en <= input_sosi_reg.eop & store_done; u_info_sosi : entity dp_lib.dp_paged_sop_eop_reg generic map ( - g_nof_pages => c_info_nof_pages + g_nof_pages => c_info_nof_pages ) port map ( rst => dp_rst, @@ -219,11 +277,13 @@ begin sop_wr_en => info_sop_wr_en, eop_wr_en => info_eop_wr_en, -- ST sink - snk_in => input_sosi, + snk_in => input_sosi_reg, -- ST source - src_out => info_sosi + src_out => info_sosi_paged ); + -- Account for retrieve rd latency is 1, for sop related info it is not + -- critical that it arrives early, but for eop related info it is. output_sosi <= func_dp_stream_combine_info_and_data(info_sosi, retrieve_sosi); end str; diff --git a/libraries/base/reorder/src/vhdl/reorder_col_wide.vhd b/libraries/base/reorder/src/vhdl/reorder_col_wide.vhd index db5b224ade46796d32b72e7b324ddfbebec28070..4cc63def4f7208b02a4f18eada8f6a6cbc36f8cd 100644 --- a/libraries/base/reorder/src/vhdl/reorder_col_wide.vhd +++ b/libraries/base/reorder/src/vhdl/reorder_col_wide.vhd @@ -27,23 +27,20 @@ -- It assumes that the g_nof_ch_in input channels are equally -- distributed over the g_wb_factor input streams. -- --- -- Remarks: -- -library IEEE, common_lib, technology_lib, dp_lib; +library IEEE, common_lib, dp_lib; use IEEE.std_logic_1164.all; use IEEE.numeric_std.all; use common_lib.common_pkg.all; use common_lib.common_mem_pkg.all; use dp_lib.dp_stream_pkg.all; -use technology_lib.technology_select_pkg.all; entity reorder_col_wide is generic ( - g_technology : natural := c_tech_select_default; g_wb_factor : natural := 4; - g_dsp_data_w : natural := 18; + g_dsp_data_w : natural := 18; -- complex data width, = c_data_w / 2 g_nof_ch_in : natural := 256; g_nof_ch_sel : natural := 192; -- g_nof_ch_sel < g_nof_ch_in g_select_file_prefix : string := "UNUSED"; @@ -60,10 +57,10 @@ entity reorder_col_wide is ram_ss_ss_wide_miso : out t_mem_miso; -- Streaming - input_sosi_arr : in t_dp_sosi_arr(g_wb_factor - 1 downto 0); -- complex input - input_siso_arr : out t_dp_siso_arr(g_wb_factor - 1 downto 0) := (others => c_dp_siso_rdy); -- complex input + input_sosi_arr : in t_dp_sosi_arr(g_wb_factor - 1 downto 0); + input_siso_arr : out t_dp_siso_arr(g_wb_factor - 1 downto 0) := (others => c_dp_siso_rdy); - output_sosi_arr : out t_dp_sosi_arr(g_wb_factor - 1 downto 0); -- selected complex output with flow control + output_sosi_arr : out t_dp_sosi_arr(g_wb_factor - 1 downto 0); -- selected output output_siso_arr : in t_dp_siso_arr(g_wb_factor - 1 downto 0) := (others => c_dp_siso_rdy) ); end reorder_col_wide; @@ -99,10 +96,9 @@ begin --------------------------------------------------------------- -- INSTANTIATE MULTIPLE SINGLE CHANNEL SUBBAND SELECT UNITS --------------------------------------------------------------- - gen_ss_singles : for I in 0 to g_wb_factor - 1 generate - u_single_ss : entity work.reorder_col + gen_reorder_col_arr : for I in 0 to g_wb_factor - 1 generate + u_reorder_col : entity work.reorder_col generic map ( - g_technology => g_technology, g_dsp_data_w => g_dsp_data_w, g_nof_ch_in => c_nof_ch_in, g_nof_ch_sel => c_nof_ch_sel, diff --git a/libraries/base/reorder/src/vhdl/reorder_col_wide_select.vhd b/libraries/base/reorder/src/vhdl/reorder_col_wide_select.vhd index bb76367782ae5a5e24d854a65ca63363062b146e..62e6db321606e6b5e0a918bcda6533bd54bac009 100644 --- a/libraries/base/reorder/src/vhdl/reorder_col_wide_select.vhd +++ b/libraries/base/reorder/src/vhdl/reorder_col_wide_select.vhd @@ -23,24 +23,22 @@ -- Purpose: Select and/or reorder data on multiple streams. -- -- Description: --- Array of reorder_col_select instances +-- Array of reorder_col_select instances. -- -- Remarks: -- -library IEEE, common_lib, technology_lib, dp_lib; +library IEEE, common_lib, dp_lib; use IEEE.std_logic_1164.all; use IEEE.numeric_std.all; use common_lib.common_pkg.all; use common_lib.common_mem_pkg.all; use dp_lib.dp_stream_pkg.all; -use technology_lib.technology_select_pkg.all; entity reorder_col_wide_select is generic ( - g_technology : natural := c_tech_select_default; g_nof_inputs : natural := 6; - g_dsp_data_w : natural := 18; + g_dsp_data_w : natural := 18; -- complex data width, = c_data_w / 2 g_nof_ch_in : natural := 1024; g_nof_ch_sel : natural := 12; -- g_nof_ch_sel < g_nof_ch_in g_use_complex : boolean := true @@ -49,15 +47,17 @@ entity reorder_col_wide_select is dp_rst : in std_logic; dp_clk : in std_logic; + -- Dynamic reorder block size control + nof_ch_in : in natural range 0 to g_nof_ch_in := g_nof_ch_in; + nof_ch_sel : in natural range 0 to g_nof_ch_sel := g_nof_ch_sel; + -- Memory Mapped col_select_mosi : in t_mem_mosi; -- channel select control col_select_miso : out t_mem_miso; -- only used for waitrequest -- Streaming - input_sosi_arr : in t_dp_sosi_arr(g_nof_inputs - 1 downto 0); -- complex input - input_siso_arr : out t_dp_siso_arr(g_nof_inputs - 1 downto 0) := (others => c_dp_siso_rdy); -- complex input - - output_sosi_arr : out t_dp_sosi_arr(g_nof_inputs - 1 downto 0) -- selected complex output with flow control + input_sosi_arr : in t_dp_sosi_arr(g_nof_inputs - 1 downto 0); + output_sosi_arr : out t_dp_sosi_arr(g_nof_inputs - 1 downto 0) ); end reorder_col_wide_select; @@ -69,13 +69,12 @@ begin col_select_miso <= col_select_miso_arr(0); -- All inputs have the same mosi/miso - --------------------------------------------------------------- - -- INSTANTIATE MULTIPLE SINGLE CHANNEL SUBBAND SELECT UNITS - --------------------------------------------------------------- + -- Instantiate reorder_col_select for multiple streams in parallel, to + -- reorder blocks in each stream in time. The same reordering is applied + -- by col_select_mosi to each stream. gen_nof_input : for I in 0 to g_nof_inputs - 1 generate u_reorder_col_select : entity work.reorder_col_select generic map ( - g_technology => g_technology, g_dsp_data_w => g_dsp_data_w, g_nof_ch_in => g_nof_ch_in, g_nof_ch_sel => g_nof_ch_sel, @@ -85,13 +84,16 @@ begin dp_rst => dp_rst, dp_clk => dp_clk, + -- Dynamic reorder block size control, same for all streams + nof_ch_in => nof_ch_in, + nof_ch_sel => nof_ch_sel, + -- Memory Mapped col_select_mosi => col_select_mosi, col_select_miso => col_select_miso_arr(I), -- Streaming input_sosi => input_sosi_arr(I), - output_sosi => output_sosi_arr(I) ); end generate; diff --git a/libraries/base/reorder/src/vhdl/reorder_matrix.vhd b/libraries/base/reorder/src/vhdl/reorder_matrix.vhd index 73ceaf6250481515fc84655ae490a45dd28b0ada..46a30e6afa8862646c827d5602c598a7ac1f31b3 100644 --- a/libraries/base/reorder/src/vhdl/reorder_matrix.vhd +++ b/libraries/base/reorder/src/vhdl/reorder_matrix.vhd @@ -46,21 +46,19 @@ -- Remarks: -- -library IEEE, common_lib, technology_lib, dp_lib; +library IEEE, common_lib, dp_lib; use IEEE.std_logic_1164.all; use IEEE.numeric_std.all; use common_lib.common_pkg.all; use common_lib.common_mem_pkg.all; use dp_lib.dp_stream_pkg.all; -use technology_lib.technology_select_pkg.all; entity reorder_matrix is generic ( - g_technology : natural := c_tech_select_default; g_nof_inputs : natural := 24; g_nof_internals : natural := 64; g_nof_outputs : natural := 64; - g_dsp_data_w : natural := 8; + g_dsp_data_w : natural := 8; -- complex data width, = c_data_w / 2 g_frame_size_in : natural := 64; g_frame_size_out : natural := 128; g_reorder_in_file_name : string := "UNUSED"; -- path_to_file.hex @@ -118,7 +116,6 @@ begin ----------------------------------------------------------------------------- u_input_reorder : entity work.reorder_row generic map( - g_technology => g_technology, g_nof_inputs => g_nof_inputs, g_nof_outputs => g_nof_internals, g_dsp_data_w => g_dsp_data_w, @@ -148,7 +145,6 @@ begin ----------------------------------------------------------------------------- u_ss_wide : entity work.reorder_col_wide generic map ( - g_technology => g_technology, g_wb_factor => g_nof_internals, g_dsp_data_w => g_dsp_data_w, g_nof_ch_in => g_frame_size_in, @@ -176,7 +172,6 @@ begin ----------------------------------------------------------------------------- u_output_reorder : entity work.reorder_row generic map( - g_technology => g_technology, g_nof_inputs => g_nof_internals, g_nof_outputs => g_nof_outputs, g_dsp_data_w => g_dsp_data_w, diff --git a/libraries/base/reorder/src/vhdl/reorder_pkg.vhd b/libraries/base/reorder/src/vhdl/reorder_pkg.vhd index cf8136bcf3b08ef693587a6816ab1a2504edc2ef..80136add774ed7aa11555f523ede39a27e7183f6 100644 --- a/libraries/base/reorder/src/vhdl/reorder_pkg.vhd +++ b/libraries/base/reorder/src/vhdl/reorder_pkg.vhd @@ -21,8 +21,9 @@ library IEEE, common_lib; use IEEE.std_logic_1164.all; -use common_lib.common_pkg.all; use IEEE.numeric_std.all; +use common_lib.common_pkg.all; +use common_lib.common_mem_pkg.all; package reorder_pkg is @@ -76,9 +77,94 @@ package reorder_pkg is (0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0) ); + -- Block and data counters to derive select_copi.address for transpose + -- reording between nof_blocks_per_packet and nof_data_per_block. + type t_reorder_transpose is record + select_copi : t_mem_copi; + addr : natural; + blk_cnt : natural; + data_cnt : natural; + end record; + + constant c_reorder_transpose_rst : t_reorder_transpose := (c_mem_copi_rst, 0, 0, 0); + + -- Input block has nof_ch = nof_data_per_block * nof_blocks_per_packet + -- data per packet. The transpose.select_copi.address order will yield + -- transposed output, with nof_blocks_per_packet and nof_data_per_block. + function func_reorder_transpose(nof_blocks_per_packet : natural; + nof_data_per_block : natural; + transpose : t_reorder_transpose) + return t_reorder_transpose; + end reorder_pkg; package body reorder_pkg is -end reorder_pkg; + -- A transpose process and an undo transpose process can both use + -- func_reorder_transpose(), by swapping the transpose dimensions. + -- For example, to get transposed output with: + -- . g_nof_blocks_per_packet = 3 and + -- . g_nof_data_per_block = 5 + -- the p_comb_transpose selects: + -- + -- v.blk_cnt: 0 1 2 + -- v.data_cnt: 0 1 2 3 4 0 1 2 3 4 0 1 2 3 4 + -- ch: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 + -- data_in 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 -- in_sosi + -- transpose: 0 3 6 9 12 + -- 1 4 7 10 13 + -- 2 5 8 11 14 + -- v.addr 0 3 6 9 12 1 4 7 10 13 2 5 8 11 14 + -- data_out 0 3 6 9 12 1 4 7 10 13 2 5 8 11 14 -- transposed_sosi + -- + -- and then with swapped parameter values, to get untransposed + -- output back (= original input order): + -- . g_nof_blocks_per_packet = 5 and + -- . g_nof_data_per_block = 3 + -- the p_comb_undo_transpose selects: + -- + -- v.blk_cnt: 0 1 2 3 4 + -- v.data_cnt: 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 + -- ch: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 + -- data_in 0 3 6 9 12 1 4 7 10 13 2 5 8 11 14 -- transposed_sosi + -- undo_transpose: 0 1 2 + -- 3 4 5 + -- 6 7 8 + -- 9 10 11 + -- 12 13 14 + -- v.addr: 0 5 10 1 6 11 2 7 12 3 8 13 4 9 14 + -- data_out: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 -- out_sosi + -- + -- to restore the original order. + function func_reorder_transpose(nof_blocks_per_packet : natural; + nof_data_per_block : natural; + transpose : t_reorder_transpose) + return t_reorder_transpose is + variable v : t_reorder_transpose; + begin + v := transpose; + -- read at current address + v.select_copi.address := TO_MEM_ADDRESS(v.addr); + v.select_copi.rd := '1'; + -- prepare next read address + if v.blk_cnt <= nof_blocks_per_packet - 1 then + if v.data_cnt < nof_data_per_block - 1 then + v.data_cnt := v.data_cnt + 1; + v.addr := v.addr + nof_blocks_per_packet; + else + v.data_cnt := 0; + v.blk_cnt := v.blk_cnt + 1; + if v.blk_cnt = nof_blocks_per_packet then + v.blk_cnt := 0; + end if; + v.addr := v.blk_cnt; + end if; + else + v.data_cnt := 0; + v.blk_cnt := 0; + v.addr := 0; + end if; + return v; + end; +end reorder_pkg; diff --git a/libraries/base/reorder/src/vhdl/reorder_retreive.vhd b/libraries/base/reorder/src/vhdl/reorder_retreive.vhd index 4f1c3761e23ca6ce658709a624c252ec482599c2..099f85a16e4b0bec33889d98a660f8fd9ff333ce 100644 --- a/libraries/base/reorder/src/vhdl/reorder_retreive.vhd +++ b/libraries/base/reorder/src/vhdl/reorder_retreive.vhd @@ -43,10 +43,9 @@ use dp_lib.dp_stream_pkg.all; -- reorder_col can store a frame and retrieve it immediately in any order, so worst -- case the last stored data can be retrieved first. - entity reorder_retrieve is generic ( - g_dsp_data_w : natural; + g_dsp_data_w : natural; -- complex data width, = c_data_w / 2 g_nof_ch_in : natural; g_nof_ch_sel : natural ); @@ -75,6 +74,7 @@ end reorder_retrieve; architecture rtl of reorder_retrieve is + constant c_data_w : natural := c_nof_complex * g_dsp_data_w; constant c_retrieve_lat : natural := 2; -- fixed 1 for select buf read + 1 for store buf read signal ch_cnt : integer range 0 to g_nof_ch_sel - 1; @@ -116,7 +116,8 @@ begin u_retrieve_en : entity common_lib.common_switch generic map ( g_rst_level => '0', - g_priority_lo => false, -- store_done has priority over nxt_retrieve_done when they occur simultaneously + -- store_done has priority over nxt_retrieve_done when they occur simultaneously + g_priority_lo => false, g_or_high => true, g_and_low => false ) @@ -124,7 +125,9 @@ begin rst => rst, clk => clk, switch_high => store_done, - switch_low => nxt_retrieve_done, -- can not use retrieve_done with g_and_low = TRUE, because if retrieve_done occurs after next store_done then that page gets missed + -- can not use retrieve_done with g_and_low = TRUE, because if retrieve_done + -- occurs after next store_done then that page gets missed + switch_low => nxt_retrieve_done, out_level => retrieve_en ); @@ -158,10 +161,11 @@ begin retrieve_mosi.rd <= prev_retrieve_ready; retrieve_mosi.address <= RESIZE_MEM_ADDRESS(select_miso.rddata(ceil_log2(g_nof_ch_in) - 1 downto 0)); - -- The output_sosi has RL=2, because of the read accesses to the select buf followed by the read access to the store buf, both with read latency is 1, so c_retrieve_lat=2 - output_sosi.re <= RESIZE_DP_DSP_DATA(retrieve_miso.rddata( g_dsp_data_w - 1 downto 0)); + -- The output_sosi has RL=2, because of the read accesses to the select buf followed by the + -- read access to the store buf, both with read latency is 1, so c_retrieve_lat=2. + output_sosi.re <= RESIZE_DP_DSP_DATA(retrieve_miso.rddata( g_dsp_data_w - 1 downto 0)); output_sosi.im <= RESIZE_DP_DSP_DATA(retrieve_miso.rddata(c_nof_complex * g_dsp_data_w - 1 downto g_dsp_data_w)); - output_sosi.data <= RESIZE_DP_DATA(retrieve_miso.rddata( c_nof_complex * g_dsp_data_w - 1 downto 0)); + output_sosi.data <= RESIZE_DP_DATA(retrieve_miso.rddata(c_data_w - 1 downto 0)); output_sosi.valid <= retrieve_miso.rdval; output_sosi.sop <= retrieve_sop_dly(c_retrieve_lat); output_sosi.eop <= retrieve_eop_dly(c_retrieve_lat); diff --git a/libraries/base/reorder/src/vhdl/reorder_row.vhd b/libraries/base/reorder/src/vhdl/reorder_row.vhd index 7a6b8edeca6f9b8c0e9ed3eac8fdb99c4cfd5a2d..32171e203fa7e4e5af145ce636821e3555d36035 100644 --- a/libraries/base/reorder/src/vhdl/reorder_row.vhd +++ b/libraries/base/reorder/src/vhdl/reorder_row.vhd @@ -31,21 +31,20 @@ -- Remarks: -- -library IEEE, common_lib, technology_lib, dp_lib; +library IEEE, common_lib, dp_lib; use IEEE.std_logic_1164.all; use IEEE.numeric_std.all; use common_lib.common_pkg.all; use common_lib.common_mem_pkg.all; use dp_lib.dp_stream_pkg.all; -use technology_lib.technology_select_pkg.all; entity reorder_row is generic ( - g_technology : natural := c_tech_select_default; g_dsp_data_w : natural := 16; g_frame_size : natural := 256; g_nof_inputs : natural := 8; g_nof_outputs : natural := 16; + g_use_complex : boolean := true; g_ram_init_file : string := "../../../src/data/select_buf"; -- or "UNUSED" g_pipeline_in : natural := 1; -- pipeline in_data g_pipeline_in_m : natural := 1; -- pipeline in_data for M-fold fan out @@ -108,11 +107,11 @@ architecture str of reorder_row is signal r, rin : reg_type; - signal reorder_in_dat : std_logic_vector(g_nof_inputs * c_data_w - 1 downto 0); - signal reorder_out_dat : std_logic_vector(g_nof_outputs * c_data_w - 1 downto 0); - signal reorder_select : std_logic_vector(c_mem_dat_w_dp - 1 downto 0); + signal reorder_in_dat : std_logic_vector(g_nof_inputs * c_data_w - 1 downto 0); + signal reorder_out_dat : std_logic_vector(g_nof_outputs * c_data_w - 1 downto 0); + signal reorder_select : std_logic_vector(c_mem_dat_w_dp - 1 downto 0); --SIGNAL reorder_select : STD_LOGIC_VECTOR(g_nof_outputs*c_select_w-1 DOWNTO 0); - signal reorder_chan_cnt : std_logic_vector(c_select_buf_dp.adr_w - 1 downto 0); + signal reorder_chan_cnt : std_logic_vector(c_select_buf_dp.adr_w - 1 downto 0); begin --------------------------------------------------------------- @@ -123,8 +122,15 @@ begin -- selection buffer. --------------------------------------------------------------- gen_input : for I in g_nof_inputs - 1 downto 0 generate - reorder_in_dat((I + 1) * c_data_w - 1 downto I * c_data_w) <= r.pipe_sosi_2arr(0)(I).im(g_dsp_data_w - 1 downto 0) & - r.pipe_sosi_2arr(0)(I).re(g_dsp_data_w - 1 downto 0); + use_complex : if g_use_complex generate + reorder_in_dat((I + 1) * c_data_w - 1 downto I * c_data_w) <= + r.pipe_sosi_2arr(0)(I).im(g_dsp_data_w - 1 downto 0) & + r.pipe_sosi_2arr(0)(I).re(g_dsp_data_w - 1 downto 0); + end generate; + use_data : if not g_use_complex generate + reorder_in_dat((I + 1) * c_data_w - 1 downto I * c_data_w) <= + r.pipe_sosi_2arr(0)(I).data(c_data_w - 1 downto 0); + end generate; end generate; --------------------------------------------------------------- @@ -157,7 +163,6 @@ begin --------------------------------------------------------------- u_select_buf : entity common_lib.common_ram_crw_crw_ratio generic map( - g_technology => g_technology, g_ram_a => c_select_buf_mm, g_ram_b => c_select_buf_dp, g_init_file => g_ram_init_file @@ -217,16 +222,22 @@ begin --------------------------------------------------------------- comb : process(r, input_sosi_arr, reorder_out_dat) variable v : reg_type; + -- Use intermediate variables to avoid too long code lines + variable v_re : std_logic_vector(g_dsp_data_w - 1 downto 0); + variable v_im : std_logic_vector(g_dsp_data_w - 1 downto 0); begin v := r; v.pipe_sosi_2arr(0) := input_sosi_arr; v.pipe_sosi_2arr(c_tot_pipeline-1 downto 1) := r.pipe_sosi_2arr(c_tot_pipeline-2 downto 0); -- Merge data output to the outgoing SOSI record. + -- Assigning re,im is don't care when g_use_complex is false. for I in g_nof_outputs - 1 downto 0 loop + v_im := reorder_out_dat((I + 1) * c_data_w - 1 downto I * c_data_w + g_dsp_data_w); + v_re := reorder_out_dat((I + 1) * c_data_w - g_dsp_data_w - 1 downto I * c_data_w); v.output_sosi_arr(I) := r.pipe_sosi_2arr(c_tot_pipeline-1)(0); - v.output_sosi_arr(I).im := RESIZE_DP_DSP_DATA(reorder_out_dat((I + 1) * c_data_w - 1 downto I * c_data_w + g_dsp_data_w)); - v.output_sosi_arr(I).re := RESIZE_DP_DSP_DATA(reorder_out_dat((I + 1) * c_data_w - g_dsp_data_w - 1 downto I * c_data_w)); + v.output_sosi_arr(I).im := RESIZE_DP_DSP_DATA(v_im); + v.output_sosi_arr(I).re := RESIZE_DP_DSP_DATA(v_re); end loop; rin <= v; diff --git a/libraries/base/reorder/src/vhdl/reorder_row_select.vhd b/libraries/base/reorder/src/vhdl/reorder_row_select.vhd index 21722318aa14eea8ac3850f132a7859275f9b4f9..447f4a1487ceaa8d4e3e69bf8e75f9ed5811895d 100644 --- a/libraries/base/reorder/src/vhdl/reorder_row_select.vhd +++ b/libraries/base/reorder/src/vhdl/reorder_row_select.vhd @@ -31,20 +31,19 @@ -- Remarks: -- in_select always has to be defined on the same clock cycle as the in_sosi data. -library IEEE, common_lib, technology_lib, dp_lib; +library IEEE, common_lib, dp_lib; use IEEE.std_logic_1164.all; use IEEE.numeric_std.all; use common_lib.common_pkg.all; use common_lib.common_mem_pkg.all; use dp_lib.dp_stream_pkg.all; -use technology_lib.technology_select_pkg.all; entity reorder_row_select is generic ( - g_technology : natural := c_tech_select_default; - g_dsp_data_w : natural := 16; + g_dsp_data_w : natural := 16; -- complex data width, = c_data_w / 2 g_nof_inputs : natural := 8; g_nof_outputs : natural := 16; + g_use_complex : boolean := true; g_pipeline_in : natural := 1; -- pipeline in_data g_pipeline_in_m : natural := 1; -- pipeline in_data for M-fold fan out g_pipeline_out : natural := 1 -- pipeline out_data @@ -54,8 +53,8 @@ entity reorder_row_select is dp_clk : in std_logic; -- Streaming - input_sosi_arr : in t_dp_sosi_arr(g_nof_inputs - 1 downto 0); - output_sosi_arr : out t_dp_sosi_arr(g_nof_outputs - 1 downto 0); + input_sosi_arr : in t_dp_sosi_arr(g_nof_inputs - 1 downto 0); + output_sosi_arr : out t_dp_sosi_arr(g_nof_outputs - 1 downto 0); in_select : in std_logic_vector(g_nof_outputs * ceil_log2(g_nof_inputs) - 1 downto 0) ); end reorder_row_select; @@ -69,13 +68,13 @@ architecture str of reorder_row_select is type reg_type is record pipe_sosi_2arr : t_dp_sosi_2arr(c_tot_pipeline-1 downto 0); - output_sosi_arr : t_dp_sosi_arr(g_nof_outputs - 1 downto 0); + output_sosi_arr : t_dp_sosi_arr(g_nof_outputs - 1 downto 0); end record; signal r, rin : reg_type; - signal reorder_in_dat : std_logic_vector(g_nof_inputs * c_data_w - 1 downto 0); - signal reorder_out_dat : std_logic_vector(g_nof_outputs * c_data_w - 1 downto 0); + signal reorder_in_dat : std_logic_vector(g_nof_inputs * c_data_w - 1 downto 0); + signal reorder_out_dat : std_logic_vector(g_nof_outputs * c_data_w - 1 downto 0); begin @@ -87,8 +86,15 @@ begin -- selection buffer. --------------------------------------------------------------- gen_input : for I in g_nof_inputs - 1 downto 0 generate - reorder_in_dat((I + 1) * c_data_w - 1 downto I * c_data_w) <= input_sosi_arr(I).im(g_dsp_data_w - 1 downto 0) & - input_sosi_arr(I).re(g_dsp_data_w - 1 downto 0); + use_complex : if g_use_complex generate + reorder_in_dat((I + 1) * c_data_w - 1 downto I * c_data_w) <= + input_sosi_arr(I).im(g_dsp_data_w - 1 downto 0) & + input_sosi_arr(I).re(g_dsp_data_w - 1 downto 0); + end generate; + use_data : if not g_use_complex generate + reorder_in_dat((I + 1) * c_data_w - 1 downto I * c_data_w) <= + input_sosi_arr(I).data(c_data_w - 1 downto 0); + end generate; end generate; --------------------------------------------------------------- @@ -114,7 +120,6 @@ begin out_data => reorder_out_dat ); - --------------------------------------------------------------- -- REGISTERING AND PIPELINING -- @@ -125,19 +130,25 @@ begin --------------------------------------------------------------- comb : process(r, input_sosi_arr, reorder_out_dat) variable v : reg_type; + -- Use intermediate variables to avoid too long code lines + variable v_re : std_logic_vector(g_dsp_data_w - 1 downto 0); + variable v_im : std_logic_vector(g_dsp_data_w - 1 downto 0); begin v := r; v.pipe_sosi_2arr(0) := input_sosi_arr; v.pipe_sosi_2arr(c_tot_pipeline-1 downto 1) := r.pipe_sosi_2arr(c_tot_pipeline-2 downto 0); -- Merge data output to the outgoing SOSI record. + -- Assigning re,im is don't care when g_use_complex is false. for I in g_nof_outputs - 1 downto 0 loop + v_im := reorder_out_dat((I + 1) * c_data_w - 1 downto I * c_data_w + g_dsp_data_w); + v_re := reorder_out_dat((I + 1) * c_data_w - g_dsp_data_w - 1 downto I * c_data_w); v.output_sosi_arr(I) := r.pipe_sosi_2arr(c_tot_pipeline-1)(0); - v.output_sosi_arr(I).im := RESIZE_DP_DSP_DATA(reorder_out_dat((I + 1) * c_data_w - 1 downto I * c_data_w + g_dsp_data_w)); - v.output_sosi_arr(I).re := RESIZE_DP_DSP_DATA(reorder_out_dat((I + 1) * c_data_w - g_dsp_data_w - 1 downto I * c_data_w)); + v.output_sosi_arr(I).im := RESIZE_DP_DSP_DATA(v_im); + v.output_sosi_arr(I).re := RESIZE_DP_DSP_DATA(v_re); end loop; - rin <= v; + rin <= v; end process comb; regs : process(dp_clk) diff --git a/libraries/base/reorder/src/vhdl/reorder_store.vhd b/libraries/base/reorder/src/vhdl/reorder_store.vhd index 63a3f263bd610254397286f7d4a3293257abc3d4..75207311ae588a43fdfd2874d4220c8ba0be4b5c 100644 --- a/libraries/base/reorder/src/vhdl/reorder_store.vhd +++ b/libraries/base/reorder/src/vhdl/reorder_store.vhd @@ -26,57 +26,66 @@ use common_lib.common_pkg.all; use common_lib.common_mem_pkg.all; use dp_lib.dp_stream_pkg.all; --- Purpose: Controller that store blocks of g_nof_ch_in complex input data +-- Purpose: Controller that store blocks of nof_ch_in (complex) input data -- words in a dual page data buffer -- Description: --- Write databuf control for g_nof_ch_in complex input data words and pulse --- store_done for each g_nof_ch_in data words that have been written. +-- Write databuf control for nof_ch_in (complex) input data words and pulse +-- store_done for each nof_ch_in data words that have been written. +-- Maximum size for the dual page buffer is g_nof_ch_in. Default nof_ch_in +-- = g_nof_ch_in, but it can be used with smaller reorder block sizes. -- Remarks: --- . The SS stores the complex input data as concatenated data = im & re with --- data width 2 * g_dsp_data_w. --- . The reorder_col does not use input sop and eop, because it uses a ch_cnt. Hence --- the input_sosi only needs to carry im, re and valid, the sop and eop are --- ignored. The ch_cnt is needed anyway to set the store_mosi.address. The --- g_nof_ch_in defines the number of valid per input block, so from sop to --- eop. The reorder_store assumes that the first valid corresponds to a sop. The --- ch_cnt restarts at the and of a block, so when ch_cnt = g_nof_ch_in-1. --- . The store_done signal occurs when the last data of the block is being --- written, so 1 cycle after the input_sosi.eop. +-- . The reorder_store stores the complex input_sosi.re,im as concatenated +-- data = im & re with data width c_data_w, when g_use_complex = true. When +-- g_use_complex = false it stores c_data_w width of the input_sosi.data. +-- . The reorder_col does not use input_sosi.sop and eop, because it uses a +-- ch_cnt. Hence the input_sosi only needs to carry data, im, re and valid, +-- the input_sosi.sop and eop are ignored. The ch_cnt is needed anyway to +-- set the store_mosi.address. The nof_ch_in defines the number of valid +-- per input block, so from input_sosi.sop to input_sosi.eop. The +-- reorder_store assumes that the first input_sosi.valid corresponds to a +-- input_sosi.sop. The ch_cnt restarts at the and of a block, so when +-- ch_cnt = nof_ch_in-1. +-- . The store_done signal occurs when the last data of the input_sosi block +-- is being written, so 1 cycle after the input_sosi.eop. +-- . The store_busy goes high at in_sosi.sop and goes low after store_done. entity reorder_store is generic ( - g_dsp_data_w : natural; -- = width of sosi.im = width of sosi.re + g_dsp_data_w : natural; -- complex data width, = c_data_w / 2 g_nof_ch_in : natural; -- = nof valid per input block (sop to eop) - g_use_complex : boolean := true -- = TRUE --> use RE and IM field. FALSE = use DATA field + g_use_complex : boolean := true -- use input_sosi.re, im when true, else input_sosi.data ); port ( rst : in std_logic; clk : in std_logic; - + -- Dynamic reorder block size control + nof_ch_in : in natural range 0 to g_nof_ch_in := g_nof_ch_in; -- Streaming input_sosi : in t_dp_sosi; - -- Timing + store_busy : out std_logic; store_done : out std_logic; - -- Write databuf control store_mosi : out t_mem_mosi ); end reorder_store; - architecture rtl of reorder_store is + constant c_data_w : natural := c_nof_complex * g_dsp_data_w; signal ch_cnt : integer range 0 to g_nof_ch_in - 1; signal nxt_ch_cnt : integer; + signal input_im_re : std_logic_vector(c_data_w - 1 downto 0); + signal input_data : std_logic_vector(c_data_w - 1 downto 0); + signal i_store_mosi : t_mem_mosi; signal nxt_store_mosi : t_mem_mosi := c_mem_mosi_rst; + signal store_busy_reg : std_logic; + signal nxt_store_busy : std_logic; signal nxt_store_done : std_logic; - begin - store_mosi <= i_store_mosi; p_reg : process (clk, rst) @@ -86,23 +95,29 @@ begin ch_cnt <= 0; -- Output registers. i_store_mosi <= c_mem_mosi_rst; + store_busy_reg <= '0'; store_done <= '0'; elsif rising_edge(clk) then -- Internal registers. ch_cnt <= nxt_ch_cnt; -- Output registers. i_store_mosi <= nxt_store_mosi; + store_busy_reg <= nxt_store_busy; store_done <= nxt_store_done; end if; end process; - p_ch_cnt : process (ch_cnt, input_sosi) + store_busy <= nxt_store_busy or store_busy_reg; + + nxt_store_busy <= '0' when ch_cnt = 0 and input_sosi.valid = '0' else '1'; + + p_ch_cnt : process (ch_cnt, input_sosi, nof_ch_in) begin nxt_store_done <= '0'; nxt_ch_cnt <= ch_cnt; if input_sosi.valid = '1' then - if ch_cnt = g_nof_ch_in - 1 then + if ch_cnt = nof_ch_in - 1 then nxt_store_done <= '1'; nxt_ch_cnt <= 0; else @@ -115,14 +130,17 @@ begin nxt_store_mosi.wr <= input_sosi.valid; nxt_store_mosi.address <= TO_MEM_ADDRESS(ch_cnt) when input_sosi.valid = '1' else i_store_mosi.address; + -- Use intermediate signals to avoid too long code lines + input_im_re <= input_sosi.im(g_dsp_data_w - 1 downto 0) & input_sosi.re(g_dsp_data_w - 1 downto 0); + input_data <= input_sosi.data(c_data_w - 1 downto 0); + -- Use complex data fields - gen_complex : if g_use_complex generate - nxt_store_mosi.wrdata <= RESIZE_MEM_DATA(input_sosi.im(g_dsp_data_w - 1 downto 0) & input_sosi.re(g_dsp_data_w - 1 downto 0)) when input_sosi.valid = '1' else i_store_mosi.wrdata; + use_complex : if g_use_complex generate + nxt_store_mosi.wrdata <= RESIZE_MEM_DATA(input_im_re) when input_sosi.valid = '1' else i_store_mosi.wrdata; end generate; -- Use regular data field - gen_non_complex : if not(g_use_complex) generate - nxt_store_mosi.wrdata <= RESIZE_MEM_DATA(input_sosi.data(c_nof_complex * g_dsp_data_w - 1 downto 0)) when input_sosi.valid = '1' else i_store_mosi.wrdata; + use_data : if not g_use_complex generate + nxt_store_mosi.wrdata <= RESIZE_MEM_DATA(input_data) when input_sosi.valid = '1' else i_store_mosi.wrdata; end generate; - end rtl; diff --git a/libraries/base/reorder/src/vhdl/reorder_transpose.vhd b/libraries/base/reorder/src/vhdl/reorder_transpose.vhd index 5ab91eeca4739fd04a303911a50fb6e44cb5f4da..0943789673ec056aeb7900d938d8839fa28a9fbb 100644 --- a/libraries/base/reorder/src/vhdl/reorder_transpose.vhd +++ b/libraries/base/reorder/src/vhdl/reorder_transpose.vhd @@ -75,18 +75,16 @@ -- . g_use_complex = TRUE : c_data_w = g_nof_streams*g_in_dat_w*c_nof_complex -- Remarks: -library IEEE, common_lib, technology_lib, dp_lib; +library IEEE, common_lib, dp_lib; use IEEE.std_logic_1164.all; use IEEE.numeric_std.all; use common_lib.common_pkg.all; use common_lib.common_mem_pkg.all; use dp_lib.dp_stream_pkg.all; use work.reorder_pkg.all; -use technology_lib.technology_select_pkg.all; entity reorder_transpose is generic( - g_technology : natural := c_tech_select_default; g_pipeline_input : natural := 0; -- choose 0 to have orignal version -r < 19416, choose 1 does not seem to help timing closure (erko) g_pipeline_output: natural := 0; -- choose 0 to have orignal version -r < 19416, choose 1 does not seem to help timing closure (erko) g_nof_streams : natural := 4; @@ -311,7 +309,6 @@ begin u_single_ss : entity work.reorder_col generic map ( - g_technology => g_technology, g_dsp_data_w => c_data_w_pre, g_nof_ch_in => c_nof_ch_in, g_nof_ch_sel => c_nof_ch_sel, @@ -375,7 +372,6 @@ begin --------------------------------------------------------------- u_sync_bsn_fifo : entity common_lib.common_fifo_sc generic map ( - g_technology => g_technology, g_use_lut => true, -- Make this FIFO in logic, since it's only 2 words deep. g_reset => false, g_init => false, diff --git a/libraries/base/reorder/tb/vhdl/tb_mms_reorder_rewire.vhd b/libraries/base/reorder/tb/vhdl/tb_mms_reorder_rewire.vhd index 153e93ab30c4190b0dfdec711d3bf7c40337ed7a..5b3e90e50cee8bbd71a28b077276ae826a303c1d 100644 --- a/libraries/base/reorder/tb/vhdl/tb_mms_reorder_rewire.vhd +++ b/libraries/base/reorder/tb/vhdl/tb_mms_reorder_rewire.vhd @@ -31,7 +31,7 @@ -- > Stop the simulation manually in Modelsim by pressing the stop-button. -- > Evalute u_dr_mem_ctrl/u_io_driver/ctlr_mosi in the WAVE window for wr and rd activity. -library IEEE, common_lib, mm_lib, diag_lib, dp_lib, io_ddr_lib, technology_lib, tech_ddr_lib; +library IEEE, common_lib, mm_lib, diag_lib, dp_lib; use IEEE.std_logic_1164.all; use IEEE.numeric_std.all; use common_lib.common_pkg.all; @@ -43,11 +43,8 @@ use mm_lib.mm_file_unb_pkg.all; use mm_lib.mm_file_pkg.all; use dp_lib.dp_stream_pkg.all; use diag_lib.diag_pkg.all; -use technology_lib.technology_select_pkg.all; -use tech_ddr_lib.tech_ddr_pkg.all; use work.reorder_pkg.all; - entity tb_mms_reorder_rewire is generic ( g_nof_streams : positive := 8; diff --git a/libraries/base/reorder/tb/vhdl/tb_reorder_col_select_all.vhd b/libraries/base/reorder/tb/vhdl/tb_reorder_col_select_all.vhd new file mode 100644 index 0000000000000000000000000000000000000000..8b4640ebd355e1ee14ce5af3969bb1e69f9ecb90 --- /dev/null +++ b/libraries/base/reorder/tb/vhdl/tb_reorder_col_select_all.vhd @@ -0,0 +1,454 @@ +------------------------------------------------------------------------------- +-- +-- Copyright 2023 +-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/> +-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands +-- +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- +------------------------------------------------------------------------------- + +------------------------------------------------------------------------------- +-- Author : E. Kooistra +-- Purpose: +-- Verify reorder_col_select using two instances and select all input data, +-- so that second instance can restore the original input data order. +-- Description: +-- The second reorder_col_select instances undo's the reordering of the +-- first reorder_col_select instance. All data in the input block is used, +-- so that the output of the second reorder_col_select instance is equal +-- to the tb input data, except for a delay and data valid gaps. +-- The data and info fields are incrementing, so that the out_sosi can be +-- verified with dp_stream_verify. +-- +-- p_comb_transpose p_comb_undo_transpose +-- | | +-- ____v_____ ____v_____ +-- |reorder | |reorder | +-- p_st_stimuli -->|col_select|------->|col_select|--> p_verify +-- |__________| |__________| +-- in_sosi transposed_sosi out_sosi +-- nof_ch_input nof_ch_transposed nof_ch_output +-- +-- Remark: +-- * Development order from basic functionality to all verifying features: +-- . verify reorder 1 packet +-- . create func_reorder_transpose() in for both p_comb_transpose and +-- p_comb_undo_transpose. +-- . put t_reorder_transpose and func_reorder_transpose() in +-- reorder_pkg.vhd to anticipate for using the transpose reordering in +-- designs. +-- . verify reorder multiple packets with and without interpacket gaps +-- . verify g_use_complex +-- . verify all sosi fields using dp_stream_verify. Cannot use delayed +-- in_sosi and proc_dp_verify_sosi_equal(), because the out_sosi does +-- not have data valid gaps within a packet. +-- . add tb_tb_reorder_col_select_all +-- . verify dynamic change of nof_blocks_per_packet, nof_data_per_block. +-- . only support changing the nof_ch_in and nof_ch_sel when the no +-- reordering is busy. +-- +-- Usage: +-- > as 8 +-- > run -all +-- * The tb is self stopping and self checking, tb_end will stop the simulation +-- by stopping the clk and thus all toggling. + +library IEEE, common_lib, dp_lib; +use IEEE.std_logic_1164.all; +use common_lib.common_pkg.all; +use common_lib.common_mem_pkg.all; +use common_lib.tb_common_pkg.all; +use common_lib.tb_common_mem_pkg.all; +use dp_lib.dp_stream_pkg.all; +use dp_lib.tb_dp_pkg.all; +use work.reorder_pkg.all; + +entity tb_reorder_col_select_all is + generic( + g_dsp_data_w : natural := 16; -- complex data width, = c_data_w / 2 + g_nof_sync : natural := 5; + g_nof_packets_per_sync : natural := 3; + g_nof_blocks_per_packet : natural := 5; + g_nof_data_per_block : natural := 3; + g_inter_valid_gap : natural := 0; -- nof clk gap in in_sosi.valid + g_inter_packet_gap : natural := 3; -- nof clk gap betweek in_sosi.eop and next in_sosi.sop + g_use_complex : boolean := false; + g_use_dynamic_selection : boolean := false + ); +end tb_reorder_col_select_all; + + +architecture tb of tb_reorder_col_select_all is + + constant c_clk_period : time := 10 ns; + constant c_rl : natural := 1; + + constant c_use_data : boolean := not g_use_complex; + constant c_data_w : natural := c_nof_complex * g_dsp_data_w; + + -- Match c_nof_sync with p_nof_ch_stimuli + constant c_nof_sync : natural := sel_a_b(g_use_dynamic_selection, 2, g_nof_sync); + constant c_factor_blk : natural := sel_a_b(g_use_dynamic_selection, 2, 1); -- factor for more blocks per packet + constant c_factor_dat : natural := sel_a_b(g_use_dynamic_selection, 1, 1); -- factor for more data per block + constant c_factor_ch : natural := c_factor_blk * c_factor_dat; -- factor for more data per packet + constant c_nof_ch : natural := g_nof_blocks_per_packet * g_nof_data_per_block; + constant c_nof_ch_long : natural := c_nof_ch * c_factor_ch; + constant c_sel_gap : natural := c_nof_ch_long * 2; + + -- Total output latency for transpose and undo transpose + constant c_retrieve_lat : natural := 2; -- rd latency of reorder_col_select + constant c_output_lat : natural := (c_nof_ch + c_retrieve_lat) * 2; + constant c_output_lat_long : natural := (c_nof_ch_long + c_retrieve_lat) * 2; + + signal rst : std_logic; + signal clk : std_logic := '1'; + signal tb_end : std_logic := '0'; + + signal verify_en_sosi : t_dp_sosi_sl; + signal verify_en_out_sosi : t_dp_sosi_sl; + signal verify_en_out_sosi_long : t_dp_sosi_sl; + + -- Data + signal in_en : std_logic := '1'; + signal in_sosi : t_dp_sosi := c_dp_sosi_rst; + signal in_siso : t_dp_siso := c_dp_siso_rdy; -- used for proc_dp_gen_block_data + signal transposed_sosi : t_dp_sosi; + signal out_sosi : t_dp_sosi; + + -- Reorder control for transpose and undo transpose + signal sel_long : boolean := false; + signal reorder_busy_transposed : std_logic; + signal reorder_busy_output : std_logic; + signal reorder_busy : std_logic; + signal nof_ch_input : natural := c_nof_ch; + signal nof_ch_transposed : natural; + signal nof_ch_output : natural; + signal nof_blocks_per_packet_input : natural := g_nof_blocks_per_packet; + signal nof_blocks_per_packet_transposed : natural; + signal nof_blocks_per_packet_output : natural; + signal nof_data_per_block_input : natural := g_nof_data_per_block; + signal nof_data_per_block_transposed : natural; + signal nof_data_per_block_output : natural; + + signal select_cipo : t_mem_cipo; + signal undo_select_cipo : t_mem_cipo; + signal r_transpose : t_reorder_transpose; + signal d_transpose : t_reorder_transpose; + signal r_undo_transpose : t_reorder_transpose; + signal d_undo_transpose : t_reorder_transpose; + +begin + + clk <= (not clk) or tb_end after c_clk_period / 2; + rst <= '1', '0' after c_clk_period * 7; + + -- Pulse in_en to control in_sosi.valid + proc_common_gen_pulse(1, 1 + g_inter_valid_gap, '1', rst, clk, in_en); + + -- Dynamic reorder control + nof_ch_input <= sel_a_b(sel_long, c_nof_ch_long, c_nof_ch); + + -- Input data packets stimuli + p_st_stimuli : process + variable v_nof_ch : natural := c_nof_ch; + variable v_bsn : std_logic_vector(31 downto 0) := (others => '0'); + variable v_info : natural := 0; + variable v_data : natural := 0; + begin + sel_long <= false; + proc_common_wait_until_low(clk, rst); + proc_common_wait_some_cycles(clk, 5); + + -- Run some sync intervals with counter data in the packets + -- proc_dp_gen_block_data( + -- constant c_ready_latency : in natural; -- 0, 1 are supported by proc_dp_stream_ready_latency() + -- constant c_use_data : in boolean; -- when TRUE use data field, else use re, im fields, and keep unused fields at 'X' + -- constant c_data_w : in natural; -- data width for the data, re and im fields + -- constant c_symbol_w : in natural; -- c_data_w/c_symbol_w must be an integer + -- constant c_symbol_init : in natural; -- init counter for symbols in data field + -- constant c_symbol_re_init : in natural; -- init counter for symbols in re field + -- constant c_symbol_im_init : in natural; -- init counter for symbols in im field + -- constant c_nof_symbols : in natural; -- nof symbols per frame for the data, re and im fields + -- constant c_channel : in natural; -- channel field + -- constant c_error : in natural; -- error field + -- constant c_sync : in std_logic; -- when '1' issue sync pulse during this block + -- constant c_bsn : in std_logic_vector; -- bsn field + -- signal clk : in std_logic; + -- signal in_en : in std_logic; -- when '0' then no valid output even when src_in is ready + -- signal src_in : in t_dp_siso; + -- signal src_out : out t_dp_sosi); + for I in 0 to c_nof_sync - 1 loop + -- First packet in sync interval + v_nof_ch := nof_ch_input; + proc_dp_gen_block_data(c_rl, + c_use_data, + g_dsp_data_w, + g_dsp_data_w, + v_data, -- data + v_data, -- re + v_data + 1, -- im + v_nof_ch, + v_info + 2, -- channel + v_info + 3, -- error + '1', -- with sync + v_bsn, -- bsn + clk, + in_en, + in_siso, + in_sosi); + proc_common_wait_some_cycles(clk, g_inter_packet_gap); + for J in 0 to g_nof_packets_per_sync - 2 loop + -- Next packets in sync interval + v_nof_ch := nof_ch_input; + v_bsn := INCR_UVEC(v_bsn, 1); + v_info := v_info + 1; + v_data := v_data + v_nof_ch; + proc_dp_gen_block_data(c_rl, + c_use_data, + g_dsp_data_w, + g_dsp_data_w, + v_data, -- data + v_data, -- re + v_data + 1, -- im + v_nof_ch, + v_info + 2, -- channel + v_info + 3, -- error + '0', -- no sync + v_bsn, -- bsn + clk, + in_en, + in_siso, + in_sosi); + proc_common_wait_some_cycles(clk, g_inter_packet_gap); + end loop; + v_bsn := INCR_UVEC(v_bsn, 1); + v_info := v_info + 1; + v_data := v_data + v_nof_ch; + + if g_use_dynamic_selection then + -- Toggle dynamic reorder control + proc_common_wait_until_low(clk, reorder_busy); + sel_long <= not sel_long; + proc_common_wait_some_cycles(clk, 1); + end if; + end loop; + in_sosi <= c_dp_sosi_rst; + proc_common_wait_some_cycles(clk, c_nof_ch_long * 2); + proc_common_wait_some_cycles(clk, 10); + tb_end <= '1'; + wait; + end process; + + ------------------------------------------------------------------------------ + -- Verification + ------------------------------------------------------------------------------ + + p_verify_en_sosi : process + begin + verify_en_sosi <= c_dp_sosi_sl_rst; + proc_common_wait_until_low(clk, rst); + + -- Verify all sosi fields, except for some + verify_en_sosi <= c_dp_sosi_sl_ones; + if g_use_complex then + verify_en_sosi.data <= '0'; + else + verify_en_sosi.re <= '0'; + verify_en_sosi.im <= '0'; + end if; + verify_en_sosi.empty <= '0'; + wait; + end process; + + verify_en_out_sosi <= verify_en_sosi when sel_long = false else c_dp_sosi_sl_rst; + verify_en_out_sosi_long <= verify_en_sosi when sel_long = true else c_dp_sosi_sl_rst; + + u_verify_out_sosi : entity dp_lib.dp_stream_verify + generic map ( + -- initializations + g_sync_period => g_nof_packets_per_sync, -- BSN increment per sync interval + g_sync_offset => 0, -- first BSN + -- specific + g_in_dat_w => c_data_w, + g_pkt_len => c_nof_ch + ) + port map ( + rst => rst, + clk => clk, + -- Verify data + snk_in => out_sosi, + -- During stimuli + verify_snk_in_enable => verify_en_out_sosi, + + -- End of stimuli + expected_snk_in => c_dp_sosi_rst, + verify_expected_snk_in_evt => c_dp_sosi_sl_rst + ); + + -- When g_use_dynamic_selection = true then c_nof_sync = 2 and second sync interval + -- will contain the long packets. All sync intervals have g_nof_packets_per_sync. + -- The first sync interval will start with BSN = g_sync_offset = 0, so the second + -- sync interval with the long packets, will start with BSN = g_sync_offset = + -- g_nof_packets_per_sync. + u_verify_out_sosi_long : entity dp_lib.dp_stream_verify + generic map ( + -- initializations + g_sync_period => g_nof_packets_per_sync, + g_sync_offset => g_nof_packets_per_sync, + -- specific + g_in_dat_w => c_data_w, + g_pkt_len => c_nof_ch_long + ) + port map ( + rst => rst, + clk => clk, + -- Verify data + snk_in => out_sosi, + -- During stimuli + verify_snk_in_enable => verify_en_out_sosi_long, + + -- End of stimuli + expected_snk_in => c_dp_sosi_rst, + verify_expected_snk_in_evt => c_dp_sosi_sl_rst + ); + + ------------------------------------------------------------------------------ + -- DUT + ------------------------------------------------------------------------------ + + p_clk : process(rst, clk) + begin + if rst = '1' then + r_transpose <= c_reorder_transpose_rst; + r_undo_transpose <= c_reorder_transpose_rst; + elsif rising_edge(clk) then + r_transpose <= d_transpose; + r_undo_transpose <= d_undo_transpose; + end if; + end process; + + -- The p_comb_transpose and p_comb_undo_transpose can both use + -- func_reorder_transpose(), by swapping the transpose dimensions. + + nof_blocks_per_packet_input <= g_nof_blocks_per_packet when nof_ch_input = c_nof_ch else + g_nof_blocks_per_packet * c_factor_blk; + nof_data_per_block_input <= g_nof_data_per_block when nof_ch_input = c_nof_ch else + g_nof_data_per_block * c_factor_dat; + + p_comb_transpose : process(rst, r_transpose, select_cipo) + variable v : t_reorder_transpose; + begin + if select_cipo.waitrequest = '0' then + -- Read from reorder_col_select page + v := func_reorder_transpose(nof_data_per_block_input, nof_blocks_per_packet_input, r_transpose); + else + -- No read, new reorder_col_select page not available yet + v := c_reorder_transpose_rst; + end if; + -- Synchronous reset + if rst = '1' THEN + v := c_reorder_transpose_rst; + end if; + d_transpose <= v; + end process; + + nof_blocks_per_packet_transposed <= g_nof_blocks_per_packet when nof_ch_transposed = c_nof_ch else + g_nof_blocks_per_packet * c_factor_blk; + nof_data_per_block_transposed <= g_nof_data_per_block when nof_ch_transposed = c_nof_ch else + g_nof_data_per_block * c_factor_dat; + + p_comb_undo_transpose : process(rst, r_undo_transpose, undo_select_cipo) + variable v : t_reorder_transpose; + begin + if undo_select_cipo.waitrequest = '0' then + -- Read from reorder_col_select page + v := func_reorder_transpose(nof_blocks_per_packet_transposed, nof_data_per_block_transposed, r_undo_transpose); + else + -- No read, new reorder_col_select page not available yet + v := c_reorder_transpose_rst; + end if; + -- Synchronous reset + if rst = '1' THEN + v := c_reorder_transpose_rst; + end if; + d_undo_transpose <= v; + end process; + + nof_blocks_per_packet_output <= g_nof_blocks_per_packet when nof_ch_output = c_nof_ch else + g_nof_blocks_per_packet * c_factor_blk; + nof_data_per_block_output <= g_nof_data_per_block when nof_ch_output = c_nof_ch else + g_nof_data_per_block * c_factor_dat; + + u_transpose : entity work.reorder_col_select + generic map ( + g_dsp_data_w => g_dsp_data_w, + g_nof_ch_in => c_nof_ch_long, + g_nof_ch_sel => c_nof_ch_long, + g_use_complex => g_use_complex + ) + port map ( + dp_rst => rst, + dp_clk => clk, + + reorder_busy => reorder_busy_transposed, + + -- Dynamic reorder block size control + nof_ch_in => nof_ch_input, + nof_ch_sel => nof_ch_input, + + -- Captured reorder block size control used for output_sosi + output_nof_ch_in => nof_ch_transposed, + output_nof_ch_sel => open, + + -- Memory Mapped + col_select_mosi => r_transpose.select_copi, + col_select_miso => select_cipo, -- only used for waitrequest + + -- Streaming + input_sosi => in_sosi, + output_sosi => transposed_sosi + ); + + u_undo_transpose : entity work.reorder_col_select + generic map ( + g_dsp_data_w => g_dsp_data_w, + g_nof_ch_in => c_nof_ch_long, + g_nof_ch_sel => c_nof_ch_long, + g_use_complex => g_use_complex + ) + port map ( + dp_rst => rst, + dp_clk => clk, + + reorder_busy => reorder_busy_output, + + -- Dynamic reorder block size control + nof_ch_in => nof_ch_transposed, + nof_ch_sel => nof_ch_transposed, + + -- Captured reorder block size control used for output_sosi + output_nof_ch_in => nof_ch_output, + output_nof_ch_sel => open, + + -- Memory Mapped + col_select_mosi => r_undo_transpose.select_copi, + col_select_miso => undo_select_cipo, -- only used for waitrequest + + -- Streaming + input_sosi => transposed_sosi, + output_sosi => out_sosi + ); + + reorder_busy <= reorder_busy_transposed or reorder_busy_output; +end tb; diff --git a/libraries/base/reorder/tb/vhdl/tb_reorder_col_wide_row_select.vhd b/libraries/base/reorder/tb/vhdl/tb_reorder_col_wide_row_select.vhd index 181d41c4188726ecdc87ea40b7d2a211f458b1e5..294c4ed3a80e1217cef05fb0ab8a2b9ad8786f98 100644 --- a/libraries/base/reorder/tb/vhdl/tb_reorder_col_wide_row_select.vhd +++ b/libraries/base/reorder/tb/vhdl/tb_reorder_col_wide_row_select.vhd @@ -74,7 +74,7 @@ entity tb_reorder_col_wide_row_select is generic( g_nof_inputs : natural := 6; -- also nof rows g_nof_outputs : natural := 2; - g_dsp_data_w : natural := 16; + g_dsp_data_w : natural := 16; -- complex data width, = c_data_w / 2 g_nof_sync : natural := 5; g_nof_block_per_sync : natural := 4; g_nof_ch_in : natural := 1024; -- nof input words per block, identical for all input streams. @@ -91,6 +91,9 @@ end tb_reorder_col_wide_row_select; architecture tb of tb_reorder_col_wide_row_select is + constant c_use_complex : boolean := true; + constant c_data_w : natural := c_nof_complex * g_dsp_data_w; + constant c_clk_period : time := 10 ns; constant c_rl : natural := 1; @@ -117,14 +120,13 @@ architecture tb of tb_reorder_col_wide_row_select is signal bsn : natural := 10; signal in_sosi_arr : t_dp_sosi_arr(g_nof_inputs - 1 downto 0) := (others => c_dp_sosi_rst); - signal out_siso_arr : t_dp_siso_arr(g_nof_inputs - 1 downto 0) := (others => c_dp_siso_rdy); - signal col_wide_select_sosi_arr : t_dp_sosi_arr(g_nof_inputs - 1 downto 0); + signal col_wide_select_sosi_arr : t_dp_sosi_arr(g_nof_inputs - 1 downto 0); signal out_sosi_arr : t_dp_sosi_arr(g_nof_outputs - 1 downto 0); signal dly_out_sosi_arr : t_dp_sosi_arr(g_nof_outputs - 1 downto 0); - signal reorder_row_in_select : std_logic_vector(c_in_select_w - 1 downto 0); - signal in_select : std_logic_vector(c_in_select_w - 1 downto 0); + signal reorder_row_in_select : std_logic_vector(c_in_select_w - 1 downto 0) := (others => '0'); + signal in_select : std_logic_vector(c_in_select_w - 1 downto 0); begin @@ -276,13 +278,13 @@ begin end process; end generate; - u_dut_col : entity work.reorder_col_wide_select generic map ( g_nof_inputs => g_nof_inputs, g_dsp_data_w => g_dsp_data_w, g_nof_ch_in => g_nof_ch_in, - g_nof_ch_sel => c_nof_ch_sel + g_nof_ch_sel => c_nof_ch_sel, + g_use_complex => c_use_complex ) port map ( dp_rst => rst, @@ -294,7 +296,6 @@ begin -- Streaming input_sosi_arr => in_sosi_arr, - output_sosi_arr => col_wide_select_sosi_arr ); @@ -315,10 +316,7 @@ begin -- Streaming input_sosi_arr => col_wide_select_sosi_arr, - output_sosi_arr => out_sosi_arr ); - - end tb; diff --git a/libraries/base/reorder/tb/vhdl/tb_reorder_transpose.vhd b/libraries/base/reorder/tb/vhdl/tb_reorder_transpose.vhd index dbf0d1585779913207b156e3392cd746184ab81c..cf95c398d8ef80e9ff4a609d12b5e1844ab5393c 100644 --- a/libraries/base/reorder/tb/vhdl/tb_reorder_transpose.vhd +++ b/libraries/base/reorder/tb/vhdl/tb_reorder_transpose.vhd @@ -31,7 +31,7 @@ -- > Stop the simulation manually in Modelsim by pressing the stop-button. -- > Evalute u_dr_mem_ctrl/u_io_driver/ctlr_mosi in the WAVE window for wr and rd activity. -library IEEE, common_lib, mm_lib, diag_lib, dp_lib, io_ddr_lib, technology_lib, tech_ddr_lib; +library IEEE, common_lib, mm_lib, diag_lib, dp_lib, io_ddr_lib, tech_ddr_lib; use IEEE.std_logic_1164.all; use IEEE.numeric_std.all; use common_lib.common_pkg.all; @@ -43,7 +43,6 @@ use mm_lib.mm_file_unb_pkg.all; use mm_lib.mm_file_pkg.all; use dp_lib.dp_stream_pkg.all; use diag_lib.diag_pkg.all; -use technology_lib.technology_select_pkg.all; use tech_ddr_lib.tech_ddr_pkg.all; use work.reorder_pkg.all; @@ -65,7 +64,6 @@ use work.reorder_pkg.all; -- -- - entity tb_reorder_transpose is generic ( g_wr_chunksize : positive := 176; -- 256; @@ -342,7 +340,6 @@ begin u_ddr_mem_ctrl : entity io_ddr_lib.io_ddr generic map( - g_technology => c_tech_select_default, -- : NATURAL := c_tech_select_default; g_tech_ddr => c_tech_ddr, -- : t_c_tech_ddr; g_cross_domain_dvr_ctlr => false, -- TRUE, -- : BOOLEAN := TRUE; g_wr_data_w => c_data_w, -- : NATURAL := 32; diff --git a/libraries/base/reorder/tb/vhdl/tb_tb_reorder_col_select_all.vhd b/libraries/base/reorder/tb/vhdl/tb_tb_reorder_col_select_all.vhd new file mode 100644 index 0000000000000000000000000000000000000000..bd66fd81f0cd9f3021c662a50fce8ed3cb750816 --- /dev/null +++ b/libraries/base/reorder/tb/vhdl/tb_tb_reorder_col_select_all.vhd @@ -0,0 +1,60 @@ +------------------------------------------------------------------------------- +-- +-- Copyright 2021 +-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/> +-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands +-- +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- +------------------------------------------------------------------------------- + +------------------------------------------------------------------------------- +-- Author : E. Kooistra +-- Purpose: Verify multiple variations of tb_reorder_col_select_all +-- Description: +-- Usage: +-- > as 5 +-- > run -all +------------------------------------------------------------------------------- + +library IEEE; +use IEEE.std_logic_1164.all; + +entity tb_tb_reorder_col_select_all is +end tb_tb_reorder_col_select_all; + +architecture tb of tb_tb_reorder_col_select_all is + signal tb_end : std_logic := '0'; -- declare tb_end to avoid 'No objects found' error on 'when -label tb_end' +begin + +-- g_dsp_data_w : natural := 16; -- complex data width, = c_data_w / 2 +-- g_nof_sync : natural := 2; +-- g_nof_packets_per_sync : natural := 3; +-- g_nof_blocks_per_packet : natural := 5; +-- g_nof_data_per_block : natural := 3; +-- g_inter_valid_gap : natural := 5; -- nof clk gap in in_sosi.valid +-- g_inter_packet_gap : natural := 0; -- nof clk gap between in_sosi.eop and next in_sosi.sop +-- g_use_complex : boolean := false; +-- g_use_dynamic_selection : boolean := true + + u_complex_5_3_no_gaps : entity work.tb_reorder_col_select_all generic map(16, 3, 2, 5, 3, 0, 0, true, false); + u_data_5_3_no_gaps : entity work.tb_reorder_col_select_all generic map(16, 3, 3, 5, 3, 0, 0, false, false); + u_data_5_1_no_gaps : entity work.tb_reorder_col_select_all generic map(16, 3, 4, 5, 1, 0, 0, false, false); + u_data_1_3_no_gaps : entity work.tb_reorder_col_select_all generic map(16, 3, 5, 1, 3, 0, 0, false, false); + u_data_3_5_pkt_gap_1 : entity work.tb_reorder_col_select_all generic map(16, 3, 6, 3, 5, 0, 1, false, false); + u_data_3_5_valid_gap_1 : entity work.tb_reorder_col_select_all generic map(16, 3, 6, 3, 5, 1, 0, false, false); + + u_dynamic_data_5_3_no_gaps : entity work.tb_reorder_col_select_all generic map(16, 3, 3, 5, 3, 0, 0, false, true); + u_dynamic_data_5_3_gaps : entity work.tb_reorder_col_select_all generic map(16, 3, 3, 5, 3,10,100, false, true); + +end tb;