diff --git a/libraries/base/reorder/src/vhdl/reorder_pkg.vhd b/libraries/base/reorder/src/vhdl/reorder_pkg.vhd index cf8136bcf3b08ef693587a6816ab1a2504edc2ef..aa14d916ef5f23cd118a7381db057cf84b37ddd1 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,95 @@ 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 c_nof_ch = c_nof_data_per_block * c_nof_blocks_per_packet + -- data per packet. The transpose.select_copi.address order will yield + -- transposed outputout with c_nof_blocks_per_packet and + -- c_nof_data_per_block. + function func_reorder_transpose(constant c_nof_blocks_per_packet : natural; + constant c_nof_data_per_block : natural; + signal 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(constant c_nof_blocks_per_packet : natural; + constant c_nof_data_per_block : natural; + signal 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 <= c_nof_blocks_per_packet - 1 then + if v.data_cnt < c_nof_data_per_block - 1 then + v.data_cnt := v.data_cnt + 1; + v.addr := v.addr + c_nof_blocks_per_packet; + else + v.data_cnt := 0; + v.blk_cnt := v.blk_cnt + 1; + if v.blk_cnt = c_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/tb/vhdl/tb_reorder_col_select_all.vhd b/libraries/base/reorder/tb/vhdl/tb_reorder_col_select_all.vhd index b6aff9b06c85438cfb868a2586493974cf63160b..8701d6a9ca818783ae18b120d70e851ce76fdbcc 100644 --- a/libraries/base/reorder/tb/vhdl/tb_reorder_col_select_all.vhd +++ b/libraries/base/reorder/tb/vhdl/tb_reorder_col_select_all.vhd @@ -28,6 +28,19 @@ -- so that the output of the second reorder_col_select instance is equal -- to the tb input data, except for a delay, so that the output data can -- easily be verified. +-- 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 proc_dp_verify_sosi_equal() +-- . add tb_tb_reorder_col_select_all +-- . verify dynamic change of nof_blocks_per_packet, nof_data_per_block -- -- Usage: -- > as 10 @@ -43,6 +56,7 @@ 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( @@ -65,6 +79,7 @@ architecture tb of tb_reorder_col_select_all is constant c_use_data : boolean := not g_use_complex; constant c_data_w : natural := c_nof_complex * g_dsp_data_w; constant c_nof_ch : natural := g_nof_blocks_per_packet * g_nof_data_per_block; + constant c_nof_blocks_max : natural:= largest(g_nof_blocks_per_packet, g_nof_data_per_block) + 1; constant c_addr_max : natural := c_nof_ch + c_nof_blocks_max; constant c_cnt_max : natural := c_nof_blocks_max; @@ -73,102 +88,27 @@ architecture tb of tb_reorder_col_select_all is constant c_retrieve_lat : natural := 2; -- rd latency of reorder_col_select constant c_output_lat : natural := (c_nof_ch + c_retrieve_lat) * 2; - type t_transpose is record - select_copi : t_mem_copi; - addr : natural range 0 to c_addr_max; - blk_cnt : natural range 0 to c_cnt_max; - data_cnt : natural range 0 to c_cnt_max; - end record; - - constant c_transpose_rst : t_transpose := (c_mem_copi_rst, 0, 0, 0); - - -- The p_comb_transpose and p_comb_undo_transpose can both use - -- func_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_transpose(constant c_nof_blocks_per_packet : natural; - constant c_nof_data_per_block : natural; - signal transpose : t_transpose) return t_transpose is - variable v : t_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 <= c_nof_blocks_per_packet - 1 then - if v.data_cnt < c_nof_data_per_block - 1 then - v.data_cnt := v.data_cnt + 1; - v.addr := v.addr + c_nof_blocks_per_packet; - else - v.data_cnt := 0; - v.blk_cnt := v.blk_cnt + 1; - if v.blk_cnt = c_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; - signal rst : std_logic; signal clk : std_logic := '1'; signal tb_end : std_logic := '0'; -- 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; - signal in_sosi_dly : t_dp_sosi := c_dp_sosi_rst; - signal expected_sosi : t_dp_sosi := c_dp_sosi_rst; + 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; + signal in_sosi_dly : t_dp_sosi := c_dp_sosi_rst; + signal expected_sosi : t_dp_sosi := c_dp_sosi_rst; -- Reorder and undo reorder control signal nof_ch : natural range 0 to c_nof_ch := c_nof_ch; signal select_cipo : t_mem_cipo; signal undo_select_cipo : t_mem_cipo; - signal r_transpose : t_transpose; - signal d_transpose : t_transpose; - signal r_undo_transpose : t_transpose; - signal d_undo_transpose : t_transpose; + 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 @@ -271,36 +211,38 @@ begin r_transpose <= d_transpose when rising_edge(clk); r_undo_transpose <= d_undo_transpose when rising_edge(clk); + -- The p_comb_transpose and p_comb_undo_transpose can both use + -- func_reorder_transpose(), by swapping the transpose dimensions. p_comb_transpose : process(rst, r_transpose, select_cipo) - variable v : t_transpose; + variable v : t_reorder_transpose; begin if select_cipo.waitrequest = '0' then -- Read from reorder_col_select page - v := func_transpose(g_nof_data_per_block, g_nof_blocks_per_packet, r_transpose); + v := func_reorder_transpose(g_nof_data_per_block, g_nof_blocks_per_packet, r_transpose); else -- No read, new reorder_col_select page not available yet - v := c_transpose_rst; + v := c_reorder_transpose_rst; end if; -- Synchronous reset if rst = '1' THEN - v := c_transpose_rst; + v := c_reorder_transpose_rst; end if; d_transpose <= v; end process; p_comb_undo_transpose : process(rst, r_undo_transpose, undo_select_cipo) - variable v : t_transpose; + variable v : t_reorder_transpose; begin if undo_select_cipo.waitrequest = '0' then -- Read from reorder_col_select page - v := func_transpose(g_nof_blocks_per_packet, g_nof_data_per_block, r_undo_transpose); + v := func_reorder_transpose(g_nof_blocks_per_packet, g_nof_data_per_block, r_undo_transpose); else -- No read, new reorder_col_select page not available yet - v := c_transpose_rst; + v := c_reorder_transpose_rst; end if; -- Synchronous reset if rst = '1' THEN - v := c_transpose_rst; + v := c_reorder_transpose_rst; end if; d_undo_transpose <= v; end process;