diff --git a/libraries/base/dp/hdllib.cfg b/libraries/base/dp/hdllib.cfg index 26e882b63228ecd4ab4c86bd1150e28e84695f03..bae5699da89fd18b4563292bf9b7a144d072d572 100644 --- a/libraries/base/dp/hdllib.cfg +++ b/libraries/base/dp/hdllib.cfg @@ -121,6 +121,10 @@ synth_files = src/vhdl/dp_frame.vhd src/vhdl/dp_unframe.vhd src/vhdl/dp_repack_legacy.vhd + src/vhdl/dp_repack_data_in_shift.vhd + src/vhdl/dp_repack_data_in_load.vhd + src/vhdl/dp_repack_data_in.vhd + src/vhdl/dp_repack_data_out_shift.vhd src/vhdl/dp_repack_data.vhd src/vhdl/dp_frame_repack.vhd src/vhdl/dp_frame_scheduler.vhd diff --git a/libraries/base/dp/src/vhdl/dp_repack_data.vhd b/libraries/base/dp/src/vhdl/dp_repack_data.vhd index 4a675f0fdf3ecb7e2ffe4328cba70532e17f3e6c..9d73239a3999b059de23a5cd1ee653ca02b30d69 100644 --- a/libraries/base/dp/src/vhdl/dp_repack_data.vhd +++ b/libraries/base/dp/src/vhdl/dp_repack_data.vhd @@ -179,468 +179,20 @@ use IEEE.std_logic_1164.all; use common_lib.common_pkg.all; use dp_lib.dp_stream_pkg.all; -entity dp_repack_in is - generic ( - g_bypass : boolean := false; - g_in_dat_w : natural; - g_in_nof_words : natural; - g_in_symbol_w : natural := 1 -- default 1 for snk_in.empty in nof bits, else use power of 2 - ); - port ( - rst : in std_logic; - clk : in std_logic; - - snk_out : out t_dp_siso; - snk_in : in t_dp_sosi; - - src_in : in t_dp_siso; - src_out : out t_dp_sosi; - src_out_data : out std_logic_vector(g_in_dat_w * g_in_nof_words - 1 downto 0) - ); -end dp_repack_in; - -architecture rtl of dp_repack_in is - constant c_in_buf_dat_w : natural := g_in_dat_w * g_in_nof_words; - constant c_bit_cnt_max : natural := c_in_buf_dat_w; - constant c_in_empty_lo : natural := true_log2(g_in_symbol_w); - - type t_dat_arr is array (integer range <>) of std_logic_vector(g_in_dat_w - 1 downto 0); - - type t_reg is record - dat_arr : t_dat_arr(g_in_nof_words - 1 downto 0); -- internally use dat_arr[] to represent v.src_out.data - src_out : t_dp_sosi; -- sosi output - src_out_data : std_logic_vector(c_in_buf_dat_w - 1 downto 0); -- Use seperate STD_LOGIC_VECTOR to carry the sosi data as c_in_buf_dat_w can be larger than c_dp_stream_data_w. - hold_out : t_dp_sosi; -- hold snk_in.sync/sop/eop until end of section and then hold valid src_out until src_in.ready - flush : std_logic; -- shift when snk_in.valid or flush in case the last subsection has < g_in_nof_words - dat_bit_cnt : natural range 0 to c_bit_cnt_max; -- actual nof bits in subsection - pack_bit_cnt : natural range 0 to c_bit_cnt_max; -- count nof bits in subsection - end record; - - signal data_vec : std_logic_vector(c_in_buf_dat_w - 1 downto 0); - - signal r_snk_out : t_dp_siso := c_dp_siso_rdy; - signal r : t_reg; - signal nxt_r : t_reg; - - -- Debug signals - signal snk_in_data : std_logic_vector(g_in_dat_w - 1 downto 0); - signal i_src_out : t_dp_sosi; - signal i_src_out_data : std_logic_vector(c_in_buf_dat_w - 1 downto 0); - - signal dbg_g_in_dat_w : natural := g_in_dat_w; - signal dbg_in_nof_words : natural := g_in_nof_words; - signal dbg_in_symbol_w : natural := g_in_symbol_w; - signal dbc_in_buf_dat_w : natural := c_in_buf_dat_w; -begin - snk_in_data <= snk_in.data(g_in_dat_w - 1 downto 0); - - src_out <= i_src_out; - src_out_data <= i_src_out_data; - - gen_bypass : if g_bypass = true generate - snk_out <= src_in; - i_src_out <= snk_in; - i_src_out_data <= RESIZE_UVEC(snk_in.data, c_in_buf_dat_w); - end generate; - - no_bypass : if g_bypass = false generate - p_comb : process(rst, r, snk_in, data_vec, src_in) - variable v : t_reg; - begin - ------------------------------------------------------------------------ - -- Default - v := r; - v.src_out.sync := '0'; - v.src_out.valid := '0'; - v.src_out.sop := '0'; - v.src_out.eop := '0'; - - -------------------------------------------------------------------------- - -- Function - if r.hold_out.valid = '0' then - - -- Clear hold_out for new output valid (= new subsection) - if r.src_out.valid = '1' then - v.hold_out := c_dp_sosi_rst; - end if; - - -- Capture the snk_in block info that is valid at sop and eop - if snk_in.sop = '1' then - v.hold_out.sop := '1'; - v.hold_out.sync := snk_in.sync; - v.src_out.bsn := snk_in.bsn; - v.src_out.channel := snk_in.channel; - end if; - if snk_in.eop = '1' then - v.hold_out.eop := '1'; - v.hold_out.empty := SHIFT_UVEC(snk_in.empty, -c_in_empty_lo); -- use snk_in.empty as offset for src_out.empty in nof bits - v.src_out.err := snk_in.err; - end if; - - -- Capture the data per subsection in a block - if snk_in.valid = '1' or r.flush = '1' then - -- shift in during block - v.dat_arr(g_in_nof_words - 1 downto 1) := r.dat_arr(g_in_nof_words - 2 downto 0); -- shift up from low to high and shift in at index 0 - if r.flush = '1' then - v.dat_arr(0) := (others => '0'); -- shift in data=0 for flush - else - v.dat_arr(0) := snk_in.data(g_in_dat_w - 1 downto 0); -- shift in valid data - end if; - - -- pack subsection - if r.pack_bit_cnt < c_in_buf_dat_w - g_in_dat_w then - v.pack_bit_cnt := r.pack_bit_cnt + g_in_dat_w; - - -- early end of pack subsection - if snk_in.eop = '1' then - v.flush := '1'; -- enable flush in case eop occurs before end of pack subsection - v.dat_bit_cnt := v.pack_bit_cnt; -- capture the current subsection pack_bit_cnt - end if; - else -- r.pack_bit_cnt=c_in_buf_dat_w-g_in_dat_w - -- default end of pack subsection - v.pack_bit_cnt := 0; - v.flush := '0'; - if r.flush = '0' then - v.dat_bit_cnt := c_in_buf_dat_w; -- set default subsection pack_bit_cnt - end if; - - v.hold_out.valid := '1'; -- the function has new data to output - end if; - end if; - - -- pass on the v.dat_arr as data vector - v.src_out_data := data_vec; - v.src_out.data := RESIZE_DP_DATA(data_vec); - - -- pass on dat_bit_cnt via DP empty field - v.src_out.empty := INCR_UVEC(v.hold_out.empty, c_in_buf_dat_w - v.dat_bit_cnt); - - -- output input stage into output stage when ready, else hold_out.valid to signal pending output - if v.hold_out.valid = '1' then - if src_in.ready = '1' then - v.src_out.valid := '1'; - v.src_out.sync := v.hold_out.sync; - v.src_out.sop := v.hold_out.sop; - v.src_out.eop := v.hold_out.eop; - v.hold_out.valid := '0'; - end if; - end if; - else - -- pending output - if src_in.ready = '1' then - v.src_out.valid := '1'; - v.src_out.sync := r.hold_out.sync; - v.src_out.sop := r.hold_out.sop; - v.src_out.eop := r.hold_out.eop; - v.hold_out.valid := '0'; - end if; - end if; - - ------------------------------------------------------------------------ - -- Reset and nxt_r - if rst = '1' then - v.src_out := c_dp_sosi_rst; - v.hold_out := c_dp_sosi_rst; - v.flush := '0'; - v.dat_bit_cnt := 0; - v.pack_bit_cnt := 0; - end if; - - nxt_r <= v; - end process; - - -------------------------------------------------------------------------- - -- p_reg - r <= nxt_r when rising_edge(clk); - - -------------------------------------------------------------------------- - -- Wires - p_data_vec : process(nxt_r) - begin - for I in 0 to g_in_nof_words - 1 loop - data_vec((I + 1) * g_in_dat_w - 1 downto I * g_in_dat_w) <= nxt_r.dat_arr(I); - end loop; - end process; - - -------------------------------------------------------------------------- - -- Wired output - i_src_out <= r.src_out; - i_src_out_data <= r.src_out_data; - -------------------------------------------------------------------------- - -- Flow control - - -- local function flow control - p_flow : process(nxt_r) - begin - r_snk_out <= c_dp_siso_rdy; - if nxt_r.flush = '1' then - r_snk_out.ready <= '0'; -- input shift in stage function is always ready except when flushing - end if; - end process; - - -- combined local and remote src_in flow control - snk_out.ready <= r_snk_out.ready when nxt_r.hold_out.valid = '0' else src_in.ready; -- if there is pending output then the src_in ready determines the flow control - snk_out.xon <= src_in.xon; -- just pass on the xon/off frame flow control - end generate; -end rtl; - -library IEEE, common_lib, dp_lib; -use IEEE.std_logic_1164.all; -use common_lib.common_pkg.all; -use dp_lib.dp_stream_pkg.all; - -entity dp_repack_out is - generic ( - g_bypass : boolean := false; - g_in_buf_dat_w : natural; - g_out_dat_w : natural; - g_out_nof_words : natural; - g_out_symbol_w : natural := 1 -- default 1 for snk_in.empty in nof bits, else use power of 2 - ); - port ( - rst : in std_logic; - clk : in std_logic; - - snk_out : out t_dp_siso; - snk_in : in t_dp_sosi; - snk_in_data : in std_logic_vector(g_in_buf_dat_w - 1 downto 0); - - src_in : in t_dp_siso; - src_out : out t_dp_sosi - ); -end dp_repack_out; - -architecture rtl of dp_repack_out is - constant c_out_buf_dat_w : natural := g_out_dat_w * g_out_nof_words; - constant c_out_buf_dat_lo : natural := sel_a_b(c_out_buf_dat_w > g_in_buf_dat_w, c_out_buf_dat_w - g_in_buf_dat_w, 0); -- pack into subsection with 0 or more padding bits - constant c_snk_in_dat_lo : natural := sel_a_b(c_out_buf_dat_w < g_in_buf_dat_w, g_in_buf_dat_w - c_out_buf_dat_w, 0); -- unpack from subsection that has 0 or more padding bits - constant c_bit_cnt_max : natural := c_out_buf_dat_w; - constant c_out_empty_lo : natural := true_log2(g_out_symbol_w); - - type t_dat_arr is array (integer range <>) of std_logic_vector(g_out_dat_w - 1 downto 0); - - type t_reg is record - dat_arr : t_dat_arr(g_out_nof_words - 1 downto 0); - src_out : t_dp_sosi; - hold_out : t_dp_sosi; -- hold src_out valid and sync/sop/eop until src_in.ready - shift : std_logic; -- shift out the dat_arr - dat_bit_cnt : natural range 0 to c_bit_cnt_max; -- actual nof bits in subsection - pack_bit_cnt : natural range 0 to c_bit_cnt_max; -- count nof bits in subsection - empty_bit_cnt : natural range 0 to c_bit_cnt_max; -- empty nof bits in subsection - eos : std_logic; -- end of subsection - end record; - - signal data_vec : std_logic_vector(c_out_buf_dat_w - 1 downto 0) := (others => '0'); - - signal r_snk_out : t_dp_siso := c_dp_siso_rdy; - signal r : t_reg; - signal nxt_r : t_reg; - - -- Debug signals - signal i_src_out : t_dp_sosi; - signal src_out_data : std_logic_vector(g_out_dat_w - 1 downto 0); - - signal dbg_g_in_buf_dat_w : natural := g_in_buf_dat_w; - signal dbg_g_out_dat_w : natural := g_out_dat_w; - signal dbg_out_nof_words : natural := g_out_nof_words; - signal dbg_out_symbol_w : natural := g_out_symbol_w; - signal dbc_out_buf_dat_w : natural := c_out_buf_dat_w; - signal dbc_out_buf_dat_lo : natural := c_out_buf_dat_lo; - signal dbc_snk_in_dat_lo : natural := c_snk_in_dat_lo; -begin - src_out <= i_src_out; - src_out_data <= i_src_out.data(g_out_dat_w - 1 downto 0); - - gen_bypass : if g_bypass = true generate - snk_out <= src_in; - - p_src_out : process(snk_in) - begin - i_src_out <= snk_in; - if c_snk_in_dat_lo > 0 then - i_src_out.data <= SHIFT_UVEC(RESIZE_DP_DATA(snk_in_data), c_snk_in_dat_lo); - i_src_out.empty <= INCR_UVEC( snk_in.empty, -c_snk_in_dat_lo); - end if; - if c_out_buf_dat_lo > 0 then - i_src_out.data <= SHIFT_UVEC(RESIZE_DP_DATA(snk_in_data), -c_out_buf_dat_lo); - i_src_out.empty <= INCR_UVEC( snk_in.empty, c_out_buf_dat_lo); - end if; - end process; - end generate; - - no_bypass : if g_bypass = false generate - p_comb : process(rst, snk_in, r, data_vec, src_in) - variable v : t_reg; - begin - ------------------------------------------------------------------------ - -- Default - v := r; - v.src_out.sync := '0'; - v.src_out.valid := '0'; - v.src_out.sop := '0'; - v.src_out.eop := '0'; - - ------------------------------------------------------------------------ - -- Function - if r.hold_out.valid = '0' then - - -- Clear hold_out for new output valid - if r.src_out.sop = '1' then - v.hold_out.sync := '0'; - v.hold_out.sop := '0'; - end if; - if r.src_out.eop = '1' then - v.hold_out.eop := '0'; - end if; - - -- Capture the snk_in block info that is valid at sop and eop - if snk_in.sop = '1' then - v.hold_out.sop := '1'; - v.hold_out.sync := snk_in.sync; - v.src_out.bsn := snk_in.bsn; - v.src_out.channel := snk_in.channel; - end if; - if snk_in.eop = '1' then - v.hold_out.eop := '1'; -- local function will calculate src_out.empty based on snk_in.empty - v.src_out.err := snk_in.err; - end if; - - if r.shift = '1' then - -- shift out rest of subsection - v.hold_out.valid := '1'; - - v.dat_arr(g_out_nof_words - 1 downto 1) := r.dat_arr(g_out_nof_words - 2 downto 0); -- shift up from low to high and shift out at high index - v.dat_arr(0) := (others => '0'); -- shift in data=0 - - v.pack_bit_cnt := r.pack_bit_cnt - g_out_dat_w; - - -- end of pack subsection - if v.pack_bit_cnt <= r.empty_bit_cnt then - v.eos := '1'; -- end of subsection, so ready for new snk_in - v.shift := '0'; -- stop shifting - end if; - - elsif snk_in.valid = '1' then - -- start of pack subsection - v.hold_out.valid := '1'; - - for I in 0 to g_out_nof_words - 1 loop - v.dat_arr(I) := data_vec((I + 1) * g_out_dat_w - 1 downto I * g_out_dat_w); - end loop; - - v.dat_bit_cnt := g_in_buf_dat_w - c_snk_in_dat_lo; -- default dat_bit_cnt per subsection - if snk_in.eop = '1' then - v.dat_bit_cnt := g_in_buf_dat_w - TO_UINT(snk_in.empty); -- pass on last subsection dat_bit_cnt info via DP empty field - end if; - - v.pack_bit_cnt := c_out_buf_dat_w - g_out_dat_w; - v.empty_bit_cnt := c_out_buf_dat_w - v.dat_bit_cnt; - v.eos := '0'; - v.shift := '1'; - - -- end of pack subsection - if v.pack_bit_cnt <= v.empty_bit_cnt then - v.eos := '1'; -- end of subsection, so ready for new snk_in - v.shift := '0'; - end if; - end if; - - -- fill in local empty if this is the last subsection of a block - if v.eos = '1' then - if v.hold_out.eop = '1' then - v.src_out.empty := TO_DP_EMPTY(v.empty_bit_cnt - v.pack_bit_cnt); -- in nof bits - v.src_out.empty := SHIFT_UVEC(v.src_out.empty, c_out_empty_lo); -- in nof symbols - end if; - end if; - - -- pass on the v.dat_arr as data vector - v.src_out.data := RESIZE_DP_DATA(v.dat_arr(g_out_nof_words - 1)); - - -- output valid data when ready, else hold_out.valid to signal pending output - if v.hold_out.valid = '1' then - if src_in.ready = '1' then - v.src_out.valid := '1'; - v.src_out.sync := v.hold_out.sync; - v.src_out.sop := v.hold_out.sop; - v.src_out.eop := v.hold_out.eop and v.eos; -- output eop at end of subsection - v.hold_out.valid := '0'; - end if; - end if; - - else - -- pending output - if src_in.ready = '1' then - v.src_out.valid := '1'; - v.src_out.sync := r.hold_out.sync; - v.src_out.sop := r.hold_out.sop; - v.src_out.eop := r.hold_out.eop and r.eos; -- output eop at end of subsection - v.hold_out.valid := '0'; - end if; - end if; - - ------------------------------------------------------------------------ - -- Reset and nxt_r - if rst = '1' then - v.src_out := c_dp_sosi_rst; - v.hold_out := c_dp_sosi_rst; - v.shift := '0'; - v.dat_bit_cnt := 0; - v.pack_bit_cnt := 0; - v.empty_bit_cnt := 0; - v.eos := '0'; - end if; - - nxt_r <= v; - end process; - - -------------------------------------------------------------------------- - -- p_reg - r <= nxt_r when rising_edge(clk); - - -------------------------------------------------------------------------- - -- Wires - data_vec(c_out_buf_dat_w - 1 downto c_out_buf_dat_lo) <= snk_in_data(g_in_buf_dat_w - 1 downto c_snk_in_dat_lo); - - -------------------------------------------------------------------------- - -- Wired output - i_src_out <= r.src_out; - - -------------------------------------------------------------------------- - -- Flow control - - -- local function flow control - p_flow : process(nxt_r) - begin - r_snk_out <= c_dp_siso_rdy; - if nxt_r.shift = '1' and nxt_r.eos = '0' then - r_snk_out.ready <= '0'; -- output shift out stage function is only ready when it is not shifting or at the end of the subsection - end if; - end process; - - -- combined local and remote src_in flow control - snk_out.ready <= r_snk_out.ready when nxt_r.hold_out.valid = '0' else src_in.ready; -- if there is pending output then the src_in ready determines the flow control - snk_out.xon <= src_in.xon; -- just pass on the xon/off frame flow control - end generate; -end rtl; - -library IEEE, common_lib, dp_lib; -use IEEE.std_logic_1164.all; -use common_lib.common_pkg.all; -use dp_lib.dp_stream_pkg.all; - entity dp_repack_data is generic ( - g_enable_repack_in : boolean := true; - g_enable_repack_out : boolean := true; - g_in_bypass : boolean := false; - g_in_dat_w : natural; - g_in_nof_words : natural; - g_in_symbol_w : natural := 1; -- default 1 for snk_in.empty in nof bits, else use power of 2 - g_out_bypass : boolean := false; - g_out_dat_w : natural; - g_out_nof_words : natural; - g_out_symbol_w : natural := 1; -- default 1 for src_out.empty in nof bits, else use power of 2 - g_pipeline_ready : boolean := false -- TRUE to pipeline ready from src_in to snk_out. + g_use_repack_in_load : boolean := false; + g_enable_repack_in : boolean := true; + g_enable_repack_out : boolean := true; + g_in_bypass : boolean := false; + g_in_dat_w : natural; + g_in_nof_words : natural; + g_in_symbol_w : natural := 1; -- default 1 for snk_in.empty in nof bits, else use power of 2 + g_out_bypass : boolean := false; + g_out_dat_w : natural; + g_out_nof_words : natural; + g_out_symbol_w : natural := 1; -- default 1 for src_out.empty in nof bits, else use power of 2 + g_pipeline_ready : boolean := false -- TRUE to pipeline ready from src_in to snk_out. ); port ( rst : in std_logic; @@ -702,8 +254,9 @@ begin end generate; gen_dp_repack_in : if g_enable_repack_in = true generate - u_dp_repack_in : entity work.dp_repack_in + u_dp_repack_in : entity work.dp_repack_data_in generic map ( + g_use_in_load => g_use_repack_in_load, g_bypass => g_in_bypass, g_in_dat_w => g_in_dat_w, g_in_nof_words => g_in_nof_words, @@ -728,7 +281,7 @@ begin end generate; gen_dp_repack_out : if g_enable_repack_out = true generate - u_dp_repack_out : entity work.dp_repack_out + u_dp_repack_out : entity work.dp_repack_data_out_shift generic map ( g_bypass => g_out_bypass, g_in_buf_dat_w => c_in_buf_dat_w, diff --git a/libraries/base/dp/src/vhdl/dp_repack_data_in.vhd b/libraries/base/dp/src/vhdl/dp_repack_data_in.vhd new file mode 100644 index 0000000000000000000000000000000000000000..69d590dd2666cd5b0a064b523a9507b822d6f39f --- /dev/null +++ b/libraries/base/dp/src/vhdl/dp_repack_data_in.vhd @@ -0,0 +1,92 @@ +-------------------------------------------------------------------------------- +-- +-- Copyright (C) 2015 +-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/> +-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands +-- +-- This program is free software: you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as published by +-- the Free Software Foundation, either version 3 of the License, or +-- (at your option) any later version. +-- +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with this program. If not, see <http://www.gnu.org/licenses/>. +-- +-------------------------------------------------------------------------------- +-- Author: Eric Kooistra +-- Purpose: +-- Select shift in or load in version of dp_repack_data_in. +-- Description: +-- Use g_use_in_load = true when snk_in.data valid has no gaps. +-- +library IEEE, common_lib, dp_lib; +use IEEE.std_logic_1164.all; +use common_lib.common_pkg.all; +use dp_lib.dp_stream_pkg.all; + +entity dp_repack_data_in is + generic ( + g_use_in_load : boolean := false; + g_bypass : boolean := false; + g_in_dat_w : natural; + g_in_nof_words : natural; + g_in_symbol_w : natural := 1 -- default 1 for snk_in.empty in nof bits, else use power of 2 + ); + port ( + rst : in std_logic; + clk : in std_logic; + + snk_out : out t_dp_siso; + snk_in : in t_dp_sosi; + + src_in : in t_dp_siso; + src_out : out t_dp_sosi; + src_out_data : out std_logic_vector(g_in_dat_w * g_in_nof_words - 1 downto 0) + ); +end dp_repack_data_in; + +architecture str of dp_repack_data_in is +begin + gen_shift : if not g_use_in_load generate + u_shift : entity work.dp_repack_data_in_shift + generic map ( + g_bypass => g_bypass, + g_in_dat_w => g_in_dat_w, + g_in_nof_words => g_in_nof_words, + g_in_symbol_w => g_in_symbol_w + ) + port map ( + rst => rst, + clk => clk, + snk_out => snk_out, + snk_in => snk_in, + src_in => src_in, + src_out => src_out, + src_out_data => src_out_data + ); + end generate; + + gen_load : if g_use_in_load generate + u_load : entity work.dp_repack_data_in_load + generic map ( + g_bypass => g_bypass, + g_in_dat_w => g_in_dat_w, + g_in_nof_words => g_in_nof_words, + g_in_symbol_w => g_in_symbol_w + ) + port map ( + rst => rst, + clk => clk, + snk_out => snk_out, + snk_in => snk_in, + src_in => src_in, + src_out => src_out, + src_out_data => src_out_data + ); + end generate; +end str; diff --git a/libraries/base/dp/src/vhdl/dp_repack_data_in_load.vhd b/libraries/base/dp/src/vhdl/dp_repack_data_in_load.vhd new file mode 100644 index 0000000000000000000000000000000000000000..1e297540ed71c6e57c3bae230020c1169d93c0b6 --- /dev/null +++ b/libraries/base/dp/src/vhdl/dp_repack_data_in_load.vhd @@ -0,0 +1,232 @@ +-------------------------------------------------------------------------------- +-- +-- Copyright (C) 2025 +-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/> +-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands +-- +-- This program is free software: you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as published by +-- the Free Software Foundation, either version 3 of the License, or +-- (at your option) any later version. +-- +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with this program. If not, see <http://www.gnu.org/licenses/>. +-- +-------------------------------------------------------------------------------- +-- Author: Eric Kooistra +-- Purpose: +-- The dp_repack_data_in_load stage for dp_repack_data, using data load in. +-- Description: +-- Load in snk_in.data from high to low index in dat_arr. The dp_repack_data_in_load can handle empty words without +-- having to apply backpressure and is therefore suitable for snk_in.data without gaps in the valid. +library IEEE, common_lib, dp_lib; +use IEEE.std_logic_1164.all; +use common_lib.common_pkg.all; +use dp_lib.dp_stream_pkg.all; + +entity dp_repack_data_in_load is + generic ( + g_bypass : boolean := false; + g_in_dat_w : natural; + g_in_nof_words : natural; + g_in_symbol_w : natural := 1 -- default 1 for snk_in.empty in nof bits, else use power of 2 + ); + port ( + rst : in std_logic; + clk : in std_logic; + + snk_out : out t_dp_siso; + snk_in : in t_dp_sosi; + + src_in : in t_dp_siso; + src_out : out t_dp_sosi; + src_out_data : out std_logic_vector(g_in_dat_w * g_in_nof_words - 1 downto 0) + ); +end dp_repack_data_in_load; + +architecture rtl of dp_repack_data_in_load is + constant c_in_buf_dat_w : natural := g_in_dat_w * g_in_nof_words; + constant c_bit_cnt_max : natural := c_in_buf_dat_w; + constant c_in_empty_lo : natural := true_log2(g_in_symbol_w); + + type t_dat_arr is array (integer range <>) of std_logic_vector(g_in_dat_w - 1 downto 0); + + type t_reg is record + dat_arr : t_dat_arr(g_in_nof_words - 1 downto 0); -- internally use dat_arr[] to represent v.src_out.data + src_out : t_dp_sosi; -- sosi output + src_out_data : std_logic_vector(c_in_buf_dat_w - 1 downto 0); -- Use seperate slv to carry the sosi data as + -- c_in_buf_dat_w can be larger than c_dp_stream_data_w. + hold_out : t_dp_sosi; -- hold snk_in.sync/sop/eop until end of section and then hold valid src_out until + -- src_in.ready + load_index : natural range 0 to g_in_nof_words; -- count nof in_dat shifted in subsection + dat_bit_cnt : natural range 0 to c_bit_cnt_max; -- actual nof bits in subsection + pack_bit_cnt : natural range 0 to c_bit_cnt_max; -- count nof bits in subsection + end record; + + signal data_vec : std_logic_vector(c_in_buf_dat_w - 1 downto 0); + + signal r_snk_out : t_dp_siso := c_dp_siso_rdy; + signal r : t_reg; + signal nxt_r : t_reg; + + -- Debug signals + signal snk_in_data : std_logic_vector(g_in_dat_w - 1 downto 0); + signal i_src_out : t_dp_sosi; + signal i_src_out_data : std_logic_vector(c_in_buf_dat_w - 1 downto 0); + + signal dbg_g_in_dat_w : natural := g_in_dat_w; + signal dbg_in_nof_words : natural := g_in_nof_words; + signal dbg_in_symbol_w : natural := g_in_symbol_w; + signal dbc_in_buf_dat_w : natural := c_in_buf_dat_w; +begin + snk_in_data <= snk_in.data(g_in_dat_w - 1 downto 0); + + src_out <= i_src_out; + src_out_data <= i_src_out_data; + + gen_bypass : if g_bypass = true generate + snk_out <= src_in; + i_src_out <= snk_in; + i_src_out_data <= RESIZE_UVEC(snk_in.data, c_in_buf_dat_w); + end generate; + + no_bypass : if g_bypass = false generate + p_comb : process(rst, r, snk_in, data_vec, src_in) + variable v : t_reg; + begin + ------------------------------------------------------------------------ + -- Default + v := r; + v.src_out.sync := '0'; + v.src_out.valid := '0'; + v.src_out.sop := '0'; + v.src_out.eop := '0'; + + -------------------------------------------------------------------------- + -- Function + if r.hold_out.valid = '0' then + + -- Clear hold_out for new output valid (= new subsection) + if r.src_out.valid = '1' then + v.hold_out := c_dp_sosi_rst; + end if; + + -- Capture the snk_in block info that is valid at sop and eop + if snk_in.sop = '1' then + v.hold_out.sop := '1'; + v.hold_out.sync := snk_in.sync; + v.src_out.bsn := snk_in.bsn; + v.src_out.channel := snk_in.channel; + end if; + if snk_in.eop = '1' then + v.hold_out.eop := '1'; + v.hold_out.empty := SHIFT_UVEC(snk_in.empty, -c_in_empty_lo); -- use snk_in.empty as offset for + -- src_out.empty in nof bits + v.src_out.err := snk_in.err; + end if; + + -- Capture the data per subsection in a block + if snk_in.valid = '1' then + -- load snk_in.data into v.dat_arr from high index g_in_nof_words - 1 to low index per subsection + v.dat_arr(r.load_index) := snk_in.data(g_in_dat_w - 1 downto 0); + + -- Pack subsection control + if r.load_index > 0 then + -- Prepare next load_index + v.load_index := r.load_index - 1; + + -- Count number of bits loaded in subsection + v.pack_bit_cnt := r.pack_bit_cnt + g_in_dat_w; + + if snk_in.eop = '1' then + -- Early end of pack subsection, with v.load_index number of empty words. Occurs when snk_in block does + -- not have an integer multiple of g_in_nof_words + v.dat_bit_cnt := v.pack_bit_cnt; -- capture the current subsection pack_bit_cnt + v.load_index := g_in_nof_words - 1; + v.pack_bit_cnt := 0; + v.hold_out.valid := '1'; -- the function has new data to output + end if; + else + -- Default end of pack subsection, last word loaded in of complete subsection. Occurs during block + -- or in the last subsection of a snk_in block with an integer multiple of g_in_nof_words. + v.dat_bit_cnt := c_in_buf_dat_w; -- set default pack_bit_cnt for complete subsection + v.load_index := g_in_nof_words - 1; + v.pack_bit_cnt := 0; + v.hold_out.valid := '1'; -- the function has new data to output + end if; + end if; + + -- pass on the v.dat_arr as data vector + v.src_out_data := data_vec; + v.src_out.data := RESIZE_DP_DATA(data_vec); + + -- pass on dat_bit_cnt via DP empty field + v.src_out.empty := INCR_UVEC(v.hold_out.empty, c_in_buf_dat_w - v.dat_bit_cnt); + + -- output input stage into output stage when ready, else hold_out.valid to signal pending output + if v.hold_out.valid = '1' then + if src_in.ready = '1' then + v.src_out.valid := '1'; + v.src_out.sync := v.hold_out.sync; + v.src_out.sop := v.hold_out.sop; + v.src_out.eop := v.hold_out.eop; + v.hold_out.valid := '0'; + end if; + end if; + else + -- pending output + if src_in.ready = '1' then + v.src_out.valid := '1'; + v.src_out.sync := r.hold_out.sync; + v.src_out.sop := r.hold_out.sop; + v.src_out.eop := r.hold_out.eop; + v.hold_out.valid := '0'; + end if; + end if; + + ------------------------------------------------------------------------ + -- Reset and nxt_r + if rst = '1' then + v.src_out := c_dp_sosi_rst; + v.hold_out := c_dp_sosi_rst; + v.load_index := g_in_nof_words - 1; + v.dat_bit_cnt := 0; + v.pack_bit_cnt := 0; + end if; + + nxt_r <= v; + end process; + + -------------------------------------------------------------------------- + -- p_reg + r <= nxt_r when rising_edge(clk); + + -------------------------------------------------------------------------- + -- Wires + p_data_vec : process(nxt_r) + begin + for I in 0 to g_in_nof_words - 1 loop + data_vec((I + 1) * g_in_dat_w - 1 downto I * g_in_dat_w) <= nxt_r.dat_arr(I); + end loop; + end process; + + -------------------------------------------------------------------------- + -- Wired output + i_src_out <= r.src_out; + i_src_out_data <= r.src_out_data; + -------------------------------------------------------------------------- + -- Flow control + + -- local function flow control + r_snk_out <= c_dp_siso_rdy; -- input shift in stage function is always ready + + -- combined local and remote src_in flow control + snk_out.ready <= r_snk_out.ready when nxt_r.hold_out.valid = '0' else src_in.ready; -- if there is pending output then the src_in ready determines the flow control + snk_out.xon <= src_in.xon; -- just pass on the xon/off frame flow control + end generate; +end rtl; diff --git a/libraries/base/dp/src/vhdl/dp_repack_data_in_shift.vhd b/libraries/base/dp/src/vhdl/dp_repack_data_in_shift.vhd new file mode 100644 index 0000000000000000000000000000000000000000..1da8640d88bec022f85d726cb3198259cab2c69a --- /dev/null +++ b/libraries/base/dp/src/vhdl/dp_repack_data_in_shift.vhd @@ -0,0 +1,241 @@ +-------------------------------------------------------------------------------- +-- +-- Copyright (C) 2015 +-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/> +-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands +-- +-- This program is free software: you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as published by +-- the Free Software Foundation, either version 3 of the License, or +-- (at your option) any later version. +-- +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with this program. If not, see <http://www.gnu.org/licenses/>. +-- +-------------------------------------------------------------------------------- +-- Author: Eric Kooistra +-- Purpose: +-- The dp_repack_data_in_shift stage for dp_repack_data, using data shift in. +-- Description: +-- Shift in snk_in.data from low to high index in dat_arr. If snk_in block size is not an integer multiple of +-- g_in_nof_words, then the last packed word will have empty words. These empty words are shifted in as zero +-- values. During the shift in of empty words the dp_repack_data_in_shift applies backpressure to temporarily stop +-- new snk_in.data. Therefore the snk_in.data has to have sufficient gaps in the valid. +-- +library IEEE, common_lib, dp_lib; +use IEEE.std_logic_1164.all; +use common_lib.common_pkg.all; +use dp_lib.dp_stream_pkg.all; + +entity dp_repack_data_in_shift is + generic ( + g_bypass : boolean := false; + g_in_dat_w : natural; + g_in_nof_words : natural; + g_in_symbol_w : natural := 1 -- default 1 for snk_in.empty in nof bits, else use power of 2 + ); + port ( + rst : in std_logic; + clk : in std_logic; + + snk_out : out t_dp_siso; + snk_in : in t_dp_sosi; + + src_in : in t_dp_siso; + src_out : out t_dp_sosi; + src_out_data : out std_logic_vector(g_in_dat_w * g_in_nof_words - 1 downto 0) + ); +end dp_repack_data_in_shift; + +architecture rtl of dp_repack_data_in_shift is + constant c_in_buf_dat_w : natural := g_in_dat_w * g_in_nof_words; + constant c_bit_cnt_max : natural := c_in_buf_dat_w; + constant c_in_empty_lo : natural := true_log2(g_in_symbol_w); + + type t_dat_arr is array (integer range <>) of std_logic_vector(g_in_dat_w - 1 downto 0); + + type t_reg is record + dat_arr : t_dat_arr(g_in_nof_words - 1 downto 0); -- internally use dat_arr[] to represent v.src_out.data + src_out : t_dp_sosi; -- sosi output + src_out_data : std_logic_vector(c_in_buf_dat_w - 1 downto 0); -- Use seperate slv to carry the sosi data as + -- c_in_buf_dat_w can be larger than c_dp_stream_data_w. + hold_out : t_dp_sosi; -- hold snk_in.sync/sop/eop until end of section and then hold valid src_out until + -- src_in.ready + flush : std_logic; -- shift when snk_in.valid or flush in case the last subsection has < g_in_nof_words + dat_bit_cnt : natural range 0 to c_bit_cnt_max; -- actual nof bits in subsection + pack_bit_cnt : natural range 0 to c_bit_cnt_max; -- count nof bits in subsection + end record; + + signal data_vec : std_logic_vector(c_in_buf_dat_w - 1 downto 0); + + signal r_snk_out : t_dp_siso := c_dp_siso_rdy; + signal r : t_reg; + signal nxt_r : t_reg; + + -- Debug signals + signal snk_in_data : std_logic_vector(g_in_dat_w - 1 downto 0); + signal i_src_out : t_dp_sosi; + signal i_src_out_data : std_logic_vector(c_in_buf_dat_w - 1 downto 0); + + signal dbg_g_in_dat_w : natural := g_in_dat_w; + signal dbg_in_nof_words : natural := g_in_nof_words; + signal dbg_in_symbol_w : natural := g_in_symbol_w; + signal dbc_in_buf_dat_w : natural := c_in_buf_dat_w; +begin + snk_in_data <= snk_in.data(g_in_dat_w - 1 downto 0); + + src_out <= i_src_out; + src_out_data <= i_src_out_data; + + gen_bypass : if g_bypass = true generate + snk_out <= src_in; + i_src_out <= snk_in; + i_src_out_data <= RESIZE_UVEC(snk_in.data, c_in_buf_dat_w); + end generate; + + no_bypass : if g_bypass = false generate + p_comb : process(rst, r, snk_in, data_vec, src_in) + variable v : t_reg; + begin + ------------------------------------------------------------------------ + -- Default + v := r; + v.src_out.sync := '0'; + v.src_out.valid := '0'; + v.src_out.sop := '0'; + v.src_out.eop := '0'; + + -------------------------------------------------------------------------- + -- Function + if r.hold_out.valid = '0' then + + -- Clear hold_out for new output valid (= new subsection) + if r.src_out.valid = '1' then + v.hold_out := c_dp_sosi_rst; + end if; + + -- Capture the snk_in block info that is valid at sop and eop + if snk_in.sop = '1' then + v.hold_out.sop := '1'; + v.hold_out.sync := snk_in.sync; + v.src_out.bsn := snk_in.bsn; + v.src_out.channel := snk_in.channel; + end if; + if snk_in.eop = '1' then + v.hold_out.eop := '1'; + v.hold_out.empty := SHIFT_UVEC(snk_in.empty, -c_in_empty_lo); -- use snk_in.empty as offset for + -- src_out.empty in nof bits + v.src_out.err := snk_in.err; + end if; + + -- Capture the data per subsection in a block + if snk_in.valid = '1' or r.flush = '1' then + -- shift in during block, shift up from low to high and shift in at index 0 + v.dat_arr(g_in_nof_words - 1 downto 1) := r.dat_arr(g_in_nof_words - 2 downto 0); + if r.flush = '1' then + v.dat_arr(0) := (others => '0'); -- shift in data=0 for flush + else + v.dat_arr(0) := snk_in.data(g_in_dat_w - 1 downto 0); -- shift in valid data + end if; + + -- pack subsection + if r.pack_bit_cnt < c_in_buf_dat_w - g_in_dat_w then + v.pack_bit_cnt := r.pack_bit_cnt + g_in_dat_w; + + -- early end of pack subsection + if snk_in.eop = '1' then + v.flush := '1'; -- enable flush in case eop occurs before end of pack subsection + v.dat_bit_cnt := v.pack_bit_cnt; -- capture the current subsection pack_bit_cnt + end if; + else -- r.pack_bit_cnt=c_in_buf_dat_w-g_in_dat_w + -- default end of pack subsection + v.pack_bit_cnt := 0; + v.flush := '0'; + if r.flush = '0' then + v.dat_bit_cnt := c_in_buf_dat_w; -- set default subsection pack_bit_cnt + end if; + + v.hold_out.valid := '1'; -- the function has new data to output + end if; + end if; + + -- pass on the v.dat_arr as data vector + v.src_out_data := data_vec; + v.src_out.data := RESIZE_DP_DATA(data_vec); + + -- pass on dat_bit_cnt via DP empty field + v.src_out.empty := INCR_UVEC(v.hold_out.empty, c_in_buf_dat_w - v.dat_bit_cnt); + + -- output input stage into output stage when ready, else hold_out.valid to signal pending output + if v.hold_out.valid = '1' then + if src_in.ready = '1' then + v.src_out.valid := '1'; + v.src_out.sync := v.hold_out.sync; + v.src_out.sop := v.hold_out.sop; + v.src_out.eop := v.hold_out.eop; + v.hold_out.valid := '0'; + end if; + end if; + else + -- pending output + if src_in.ready = '1' then + v.src_out.valid := '1'; + v.src_out.sync := r.hold_out.sync; + v.src_out.sop := r.hold_out.sop; + v.src_out.eop := r.hold_out.eop; + v.hold_out.valid := '0'; + end if; + end if; + + ------------------------------------------------------------------------ + -- Reset and nxt_r + if rst = '1' then + v.src_out := c_dp_sosi_rst; + v.hold_out := c_dp_sosi_rst; + v.flush := '0'; + v.dat_bit_cnt := 0; + v.pack_bit_cnt := 0; + end if; + + nxt_r <= v; + end process; + + -------------------------------------------------------------------------- + -- p_reg + r <= nxt_r when rising_edge(clk); + + -------------------------------------------------------------------------- + -- Wires + p_data_vec : process(nxt_r) + begin + for I in 0 to g_in_nof_words - 1 loop + data_vec((I + 1) * g_in_dat_w - 1 downto I * g_in_dat_w) <= nxt_r.dat_arr(I); + end loop; + end process; + + -------------------------------------------------------------------------- + -- Wired output + i_src_out <= r.src_out; + i_src_out_data <= r.src_out_data; + -------------------------------------------------------------------------- + -- Flow control + + -- local function flow control + p_flow : process(nxt_r) + begin + r_snk_out <= c_dp_siso_rdy; + if nxt_r.flush = '1' then + r_snk_out.ready <= '0'; -- input shift in stage function is always ready except when flushing + end if; + end process; + + -- combined local and remote src_in flow control + snk_out.ready <= r_snk_out.ready when nxt_r.hold_out.valid = '0' else src_in.ready; -- if there is pending output then the src_in ready determines the flow control + snk_out.xon <= src_in.xon; -- just pass on the xon/off frame flow control + end generate; +end rtl; diff --git a/libraries/base/dp/src/vhdl/dp_repack_data_out_shift.vhd b/libraries/base/dp/src/vhdl/dp_repack_data_out_shift.vhd new file mode 100644 index 0000000000000000000000000000000000000000..99667a5f11e8409a871ed9f07d938dea567dc15c --- /dev/null +++ b/libraries/base/dp/src/vhdl/dp_repack_data_out_shift.vhd @@ -0,0 +1,270 @@ +-------------------------------------------------------------------------------- +-- +-- Copyright (C) 2015 +-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/> +-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands +-- +-- This program is free software: you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as published by +-- the Free Software Foundation, either version 3 of the License, or +-- (at your option) any later version. +-- +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with this program. If not, see <http://www.gnu.org/licenses/>. +-- +-------------------------------------------------------------------------------- +-- Author: Eric Kooistra +-- Purpose: +-- The dp_repack_data_out_shift stage for dp_repack_data, using data shift in. +-- Description: +-- See dp_repack_data. +-- +library IEEE, common_lib, dp_lib; +use IEEE.std_logic_1164.all; +use common_lib.common_pkg.all; +use dp_lib.dp_stream_pkg.all; + +entity dp_repack_data_out_shift is + generic ( + g_bypass : boolean := false; + g_in_buf_dat_w : natural; + g_out_dat_w : natural; + g_out_nof_words : natural; + g_out_symbol_w : natural := 1 -- default 1 for snk_in.empty in nof bits, else use power of 2 + ); + port ( + rst : in std_logic; + clk : in std_logic; + + snk_out : out t_dp_siso; + snk_in : in t_dp_sosi; + snk_in_data : in std_logic_vector(g_in_buf_dat_w - 1 downto 0); + + src_in : in t_dp_siso; + src_out : out t_dp_sosi + ); +end dp_repack_data_out_shift; + +architecture rtl of dp_repack_data_out_shift is + constant c_out_buf_dat_w : natural := g_out_dat_w * g_out_nof_words; + constant c_out_buf_dat_lo : natural := sel_a_b(c_out_buf_dat_w > g_in_buf_dat_w, + c_out_buf_dat_w - g_in_buf_dat_w, 0); -- pack into subsection with 0 or more padding bits + constant c_snk_in_dat_lo : natural := sel_a_b(c_out_buf_dat_w < g_in_buf_dat_w, + g_in_buf_dat_w - c_out_buf_dat_w, 0); -- unpack from subsection that has 0 or more padding bits + constant c_bit_cnt_max : natural := c_out_buf_dat_w; + constant c_out_empty_lo : natural := true_log2(g_out_symbol_w); + + type t_dat_arr is array (integer range <>) of std_logic_vector(g_out_dat_w - 1 downto 0); + + type t_reg is record + dat_arr : t_dat_arr(g_out_nof_words - 1 downto 0); + src_out : t_dp_sosi; + hold_out : t_dp_sosi; -- hold src_out valid and sync/sop/eop until src_in.ready + shift : std_logic; -- shift out the dat_arr + dat_bit_cnt : natural range 0 to c_bit_cnt_max; -- actual nof bits in subsection + pack_bit_cnt : natural range 0 to c_bit_cnt_max; -- count nof bits in subsection + empty_bit_cnt : natural range 0 to c_bit_cnt_max; -- empty nof bits in subsection + eos : std_logic; -- end of subsection + end record; + + signal data_vec : std_logic_vector(c_out_buf_dat_w - 1 downto 0) := (others => '0'); + + signal r_snk_out : t_dp_siso := c_dp_siso_rdy; + signal r : t_reg; + signal nxt_r : t_reg; + + -- Debug signals + signal i_src_out : t_dp_sosi; + signal src_out_data : std_logic_vector(g_out_dat_w - 1 downto 0); + + signal dbg_g_in_buf_dat_w : natural := g_in_buf_dat_w; + signal dbg_g_out_dat_w : natural := g_out_dat_w; + signal dbg_out_nof_words : natural := g_out_nof_words; + signal dbg_out_symbol_w : natural := g_out_symbol_w; + signal dbc_out_buf_dat_w : natural := c_out_buf_dat_w; + signal dbc_out_buf_dat_lo : natural := c_out_buf_dat_lo; + signal dbc_snk_in_dat_lo : natural := c_snk_in_dat_lo; +begin + src_out <= i_src_out; + src_out_data <= i_src_out.data(g_out_dat_w - 1 downto 0); + + gen_bypass : if g_bypass = true generate + snk_out <= src_in; + + p_src_out : process(snk_in) + begin + i_src_out <= snk_in; + if c_snk_in_dat_lo > 0 then + i_src_out.data <= SHIFT_UVEC(RESIZE_DP_DATA(snk_in_data), c_snk_in_dat_lo); + i_src_out.empty <= INCR_UVEC( snk_in.empty, -c_snk_in_dat_lo); + end if; + if c_out_buf_dat_lo > 0 then + i_src_out.data <= SHIFT_UVEC(RESIZE_DP_DATA(snk_in_data), -c_out_buf_dat_lo); + i_src_out.empty <= INCR_UVEC( snk_in.empty, c_out_buf_dat_lo); + end if; + end process; + end generate; + + no_bypass : if g_bypass = false generate + p_comb : process(rst, snk_in, r, data_vec, src_in) + variable v : t_reg; + begin + ------------------------------------------------------------------------ + -- Default + v := r; + v.src_out.sync := '0'; + v.src_out.valid := '0'; + v.src_out.sop := '0'; + v.src_out.eop := '0'; + + ------------------------------------------------------------------------ + -- Function + if r.hold_out.valid = '0' then + + -- Clear hold_out for new output valid + if r.src_out.sop = '1' then + v.hold_out.sync := '0'; + v.hold_out.sop := '0'; + end if; + if r.src_out.eop = '1' then + v.hold_out.eop := '0'; + end if; + + -- Capture the snk_in block info that is valid at sop and eop + if snk_in.sop = '1' then + v.hold_out.sop := '1'; + v.hold_out.sync := snk_in.sync; + v.src_out.bsn := snk_in.bsn; + v.src_out.channel := snk_in.channel; + end if; + if snk_in.eop = '1' then + v.hold_out.eop := '1'; -- local function will calculate src_out.empty based on snk_in.empty + v.src_out.err := snk_in.err; + end if; + + if r.shift = '1' then + -- shift out rest of subsection + v.hold_out.valid := '1'; + + -- shift up from low to high and shift out at high index + v.dat_arr(g_out_nof_words - 1 downto 1) := r.dat_arr(g_out_nof_words - 2 downto 0); + v.dat_arr(0) := (others => '0'); -- shift in data=0 + + v.pack_bit_cnt := r.pack_bit_cnt - g_out_dat_w; + + -- end of pack subsection + if v.pack_bit_cnt <= r.empty_bit_cnt then + v.eos := '1'; -- end of subsection, so ready for new snk_in + v.shift := '0'; -- stop shifting + end if; + + elsif snk_in.valid = '1' then + -- start of pack subsection + v.hold_out.valid := '1'; + + for I in 0 to g_out_nof_words - 1 loop + v.dat_arr(I) := data_vec((I + 1) * g_out_dat_w - 1 downto I * g_out_dat_w); + end loop; + + v.dat_bit_cnt := g_in_buf_dat_w - c_snk_in_dat_lo; -- default dat_bit_cnt per subsection + if snk_in.eop = '1' then + -- pass on last subsection dat_bit_cnt info via DP empty field + v.dat_bit_cnt := g_in_buf_dat_w - TO_UINT(snk_in.empty); + end if; + + v.pack_bit_cnt := c_out_buf_dat_w - g_out_dat_w; + v.empty_bit_cnt := c_out_buf_dat_w - v.dat_bit_cnt; + v.eos := '0'; + v.shift := '1'; + + -- end of pack subsection + if v.pack_bit_cnt <= v.empty_bit_cnt then + v.eos := '1'; -- end of subsection, so ready for new snk_in + v.shift := '0'; + end if; + end if; + + -- fill in local empty if this is the last subsection of a block + if v.eos = '1' then + if v.hold_out.eop = '1' then + v.src_out.empty := TO_DP_EMPTY(v.empty_bit_cnt - v.pack_bit_cnt); -- in nof bits + v.src_out.empty := SHIFT_UVEC(v.src_out.empty, c_out_empty_lo); -- in nof symbols + end if; + end if; + + -- pass on the v.dat_arr as data vector + v.src_out.data := RESIZE_DP_DATA(v.dat_arr(g_out_nof_words - 1)); + + -- output valid data when ready, else hold_out.valid to signal pending output + if v.hold_out.valid = '1' then + if src_in.ready = '1' then + v.src_out.valid := '1'; + v.src_out.sync := v.hold_out.sync; + v.src_out.sop := v.hold_out.sop; + v.src_out.eop := v.hold_out.eop and v.eos; -- output eop at end of subsection + v.hold_out.valid := '0'; + end if; + end if; + + else + -- pending output + if src_in.ready = '1' then + v.src_out.valid := '1'; + v.src_out.sync := r.hold_out.sync; + v.src_out.sop := r.hold_out.sop; + v.src_out.eop := r.hold_out.eop and r.eos; -- output eop at end of subsection + v.hold_out.valid := '0'; + end if; + end if; + + ------------------------------------------------------------------------ + -- Reset and nxt_r + if rst = '1' then + v.src_out := c_dp_sosi_rst; + v.hold_out := c_dp_sosi_rst; + v.shift := '0'; + v.dat_bit_cnt := 0; + v.pack_bit_cnt := 0; + v.empty_bit_cnt := 0; + v.eos := '0'; + end if; + + nxt_r <= v; + end process; + + -------------------------------------------------------------------------- + -- p_reg + r <= nxt_r when rising_edge(clk); + + -------------------------------------------------------------------------- + -- Wires + data_vec(c_out_buf_dat_w - 1 downto c_out_buf_dat_lo) <= snk_in_data(g_in_buf_dat_w - 1 downto c_snk_in_dat_lo); + + -------------------------------------------------------------------------- + -- Wired output + i_src_out <= r.src_out; + + -------------------------------------------------------------------------- + -- Flow control + + -- local function flow control + p_flow : process(nxt_r) + begin + r_snk_out <= c_dp_siso_rdy; + if nxt_r.shift = '1' and nxt_r.eos = '0' then + r_snk_out.ready <= '0'; -- output shift out stage function is only ready when it is not shifting or at the + -- end of the subsection + end if; + end process; + + -- combined local and remote src_in flow control + snk_out.ready <= r_snk_out.ready when nxt_r.hold_out.valid = '0' else src_in.ready; -- if there is pending output + -- then the src_in ready determines the flow control + snk_out.xon <= src_in.xon; -- just pass on the xon/off frame flow control + end generate; +end rtl; diff --git a/libraries/base/dp/tb/vhdl/tb_dp_bsn_sync_scheduler.vhd b/libraries/base/dp/tb/vhdl/tb_dp_bsn_sync_scheduler.vhd index b5692167dc1787214811e11fa3e65579442cfd49..def13ed15ee3012f8bc6a5fe0fb484c8377bbad3 100644 --- a/libraries/base/dp/tb/vhdl/tb_dp_bsn_sync_scheduler.vhd +++ b/libraries/base/dp/tb/vhdl/tb_dp_bsn_sync_scheduler.vhd @@ -367,7 +367,7 @@ begin -- cycles, but for timing closure it is preferred to use r.enable. -- Verify out_enable - p_expected_out_enable : process(ctrl_enable, in_sosi, ctrl_start_bsn, ctrl_enable_evt, out_enable_cnt, ctrl_enable, in_sosi, ctrl_start_bsn) + p_expected_out_enable : process(ctrl_enable, in_sosi, ctrl_start_bsn, ctrl_enable_evt, out_enable_cnt) begin -- Default expected_out_enable_comb <= '0'; diff --git a/libraries/base/dp/tb/vhdl/tb_dp_repack_data.vhd b/libraries/base/dp/tb/vhdl/tb_dp_repack_data.vhd index 4a09164eaf1339f29b58c733de09d3c67e1da91b..a52baeda2752bd8cc15da0cc48c98907ad4ff495 100644 --- a/libraries/base/dp/tb/vhdl/tb_dp_repack_data.vhd +++ b/libraries/base/dp/tb/vhdl/tb_dp_repack_data.vhd @@ -54,6 +54,7 @@ entity tb_dp_repack_data is g_flow_control_stimuli : t_dp_flow_control_enum := e_active; -- always e_active, e_random or e_pulse flow control g_flow_control_verify : t_dp_flow_control_enum := e_active; -- always e_active, e_random or e_pulse flow control -- specific + g_use_repack_in_load : boolean := false; g_in_dat_w : natural := 36; g_in_nof_words : natural := 16; g_pack_dat_w : natural := 64; @@ -236,16 +237,17 @@ begin u_pack : entity work.dp_repack_data generic map ( - g_enable_repack_in => c_enable_repack_in, - g_enable_repack_out => c_enable_repack_out, - g_in_bypass => g_in_bypass, - g_in_dat_w => g_in_dat_w, - g_in_nof_words => g_in_nof_words, - g_in_symbol_w => g_in_symbol_w, - g_out_bypass => g_pack_bypass, - g_out_dat_w => g_pack_dat_w, - g_out_nof_words => g_pack_nof_words, - g_out_symbol_w => g_pack_symbol_w + g_use_repack_in_load => g_use_repack_in_load, + g_enable_repack_in => c_enable_repack_in, + g_enable_repack_out => c_enable_repack_out, + g_in_bypass => g_in_bypass, + g_in_dat_w => g_in_dat_w, + g_in_nof_words => g_in_nof_words, + g_in_symbol_w => g_in_symbol_w, + g_out_bypass => g_pack_bypass, + g_out_dat_w => g_pack_dat_w, + g_out_nof_words => g_pack_nof_words, + g_out_symbol_w => g_pack_symbol_w ) port map ( rst => rst, @@ -272,16 +274,17 @@ begin gen_unpack : if c_no_unpack = false generate u_unpack : entity work.dp_repack_data generic map ( - g_enable_repack_in => c_enable_repack_out, - g_enable_repack_out => c_enable_repack_in, - g_in_bypass => g_pack_bypass, - g_in_dat_w => g_pack_dat_w, - g_in_nof_words => g_pack_nof_words, - g_in_symbol_w => g_pack_symbol_w, - g_out_bypass => g_in_bypass, - g_out_dat_w => g_in_dat_w, - g_out_nof_words => g_in_nof_words, - g_out_symbol_w => g_in_symbol_w + g_use_repack_in_load => g_use_repack_in_load, + g_enable_repack_in => c_enable_repack_out, + g_enable_repack_out => c_enable_repack_in, + g_in_bypass => g_pack_bypass, + g_in_dat_w => g_pack_dat_w, + g_in_nof_words => g_pack_nof_words, + g_in_symbol_w => g_pack_symbol_w, + g_out_bypass => g_in_bypass, + g_out_dat_w => g_in_dat_w, + g_out_nof_words => g_in_nof_words, + g_out_symbol_w => g_in_symbol_w ) port map ( rst => rst, diff --git a/libraries/base/dp/tb/vhdl/tb_tb_dp_repack_data.vhd b/libraries/base/dp/tb/vhdl/tb_tb_dp_repack_data.vhd index f61ac825829346b955479db5f27696346389f5df..98625fafd4062feb6e0a305197679dd84ab0036c 100644 --- a/libraries/base/dp/tb/vhdl/tb_tb_dp_repack_data.vhd +++ b/libraries/base/dp/tb/vhdl/tb_tb_dp_repack_data.vhd @@ -37,8 +37,10 @@ end tb_tb_dp_repack_data; architecture tb of tb_tb_dp_repack_data is constant c_nof_repeat : natural := 5; - constant c_flow : t_dp_flow_control_enum_arr := c_dp_flow_control_enum_arr; - constant c_bool : t_nat_boolean_arr := c_nat_boolean_arr; + constant c_flow : t_dp_flow_control_enum_arr := c_dp_flow_control_enum_arr; -- for stimuli and verify flow + -- control options + constant c_bypass : t_nat_boolean_arr := c_nat_boolean_arr; -- for g_in_bypass and g_pack_bypass variants + constant c_in : t_nat_boolean_arr := c_nat_boolean_arr; -- for g_use_repack_in_load variants signal tb_end : std_logic := '0'; -- declare tb_end to avoid 'No objects found' error on 'when -label tb_end' begin @@ -46,6 +48,7 @@ begin -- g_flow_control_stimuli : t_dp_flow_control_enum := e_active; -- always e_active, e_random or e_pulse flow control -- g_flow_control_verify : t_dp_flow_control_enum := e_active; -- always e_active, e_random or e_pulse flow control -- -- specific + -- g_use_repack_in_load : boolean := false; -- g_in_dat_w : NATURAL := 5; -- g_in_nof_words : NATURAL := 2; -- g_pack_dat_w : NATURAL := 16; @@ -58,103 +61,105 @@ begin -- g_pkt_len : NATURAL := 11; -- if not a multiple of g_in_nof_words then the input stage flush creates gap between blocks -- g_pkt_gap : NATURAL := 0 - g_flow_control_stimuli : for I in 0 to 2 generate -- 0 = e_active, 1 = e_random, 2 = e_pulse - g_flow_control_verify : for J in 0 to 2 generate -- 0 = e_active, 1 = e_random, 2 = e_pulse - - ------------------------------------------------------------------------- - -- Tests that can use bypass - -- . g_in_nof_words = 1 - -- . g_out_nof_words = 1 - -- . g_in_nof_words = g_in_nof_words >= 1 - ------------------------------------------------------------------------- - - gen_bool_bypass : for K in 0 to 1 generate - gen_bool_bypass : for L in 0 to 1 generate - -- no repack, g_in_nof_words = g_out_nof_words = 1 - u_16_1_16_1_len_10_gap_0 : entity work.tb_dp_repack_data generic map (c_flow(I), c_flow(J), 16, 1, 16, 1, c_bool(K), c_bool(L), 1, 1, c_nof_repeat, 10, 0); -- g_pkt_len > g_in_nof_words - u_16_1_16_1_len_3_gap_0 : entity work.tb_dp_repack_data generic map (c_flow(I), c_flow(J), 16, 1, 16, 1, c_bool(K), c_bool(L), 1, 1, c_nof_repeat, 3, 0); -- g_pkt_len > g_in_nof_words, odd - u_16_1_16_1_len_2_gap_0 : entity work.tb_dp_repack_data generic map (c_flow(I), c_flow(J), 16, 1, 16, 1, c_bool(K), c_bool(L), 1, 1, c_nof_repeat, 2, 0); -- g_pkt_len > g_in_nof_words, even - u_16_1_16_1_len_1_gap_0 : entity work.tb_dp_repack_data generic map (c_flow(I), c_flow(J), 16, 1, 16, 1, c_bool(K), c_bool(L), 1, 1, c_nof_repeat, 1, 0); -- g_pkt_len = g_in_nof_words - - u_16_1_16_1_len_1_gap_1 : entity work.tb_dp_repack_data generic map (c_flow(I), c_flow(J), 16, 1, 16, 1, c_bool(K), c_bool(L), 1, 1, c_nof_repeat, 1, 1); -- g_pkt_gap > 0 + g_in : for V in 0 to 1 generate -- 0 = false, 1 = true + g_flow_control_stimuli : for I in 0 to 2 generate -- 0 = e_active, 1 = e_random, 2 = e_pulse + g_flow_control_verify : for J in 0 to 2 generate -- 0 = e_active, 1 = e_random, 2 = e_pulse + + ------------------------------------------------------------------------- + -- Tests that can use bypass + -- . g_in_nof_words = 1 + -- . g_out_nof_words = 1 + -- . g_in_nof_words = g_in_nof_words >= 1 + ------------------------------------------------------------------------- + + gen_bool_bypass : for K in 0 to 1 generate -- 0 = false, 1 = true + gen_bool_bypass : for L in 0 to 1 generate -- 0 = false, 1 = true + -- no repack, g_in_nof_words = g_out_nof_words = 1 + u_16_1_16_1_len_10_gap_0 : entity work.tb_dp_repack_data generic map (c_flow(I), c_flow(J), c_in(V), 16, 1, 16, 1, c_bypass(K), c_bypass(L), 1, 1, c_nof_repeat, 10, 0); -- g_pkt_len > g_in_nof_words + u_16_1_16_1_len_3_gap_0 : entity work.tb_dp_repack_data generic map (c_flow(I), c_flow(J), c_in(V), 16, 1, 16, 1, c_bypass(K), c_bypass(L), 1, 1, c_nof_repeat, 3, 0); -- g_pkt_len > g_in_nof_words, odd + u_16_1_16_1_len_2_gap_0 : entity work.tb_dp_repack_data generic map (c_flow(I), c_flow(J), c_in(V), 16, 1, 16, 1, c_bypass(K), c_bypass(L), 1, 1, c_nof_repeat, 2, 0); -- g_pkt_len > g_in_nof_words, even + u_16_1_16_1_len_1_gap_0 : entity work.tb_dp_repack_data generic map (c_flow(I), c_flow(J), c_in(V), 16, 1, 16, 1, c_bypass(K), c_bypass(L), 1, 1, c_nof_repeat, 1, 0); -- g_pkt_len = g_in_nof_words + + u_16_1_16_1_len_1_gap_1 : entity work.tb_dp_repack_data generic map (c_flow(I), c_flow(J), c_in(V), 16, 1, 16, 1, c_bypass(K), c_bypass(L), 1, 1, c_nof_repeat, 1, 1); -- g_pkt_gap > 0 + end generate; + + -- no repack, g_in_nof_words = g_out_nof_words > 1 + u_16_3_16_3_len_10_gap_0 : entity work.tb_dp_repack_data generic map (c_flow(I), c_flow(J), c_in(V), 16, 3, 16, 3, c_bypass(K), c_bypass(K), 1, 1, c_nof_repeat, 10, 0); + + -- g_in_nof_words > g_pack_nof_words can use always active stimuli except when g_pkt_len MOD g_in_nof_words /= 0, because then the input stage needs to flush + u_8_4_32_1_len_1_gap_0 : entity work.tb_dp_repack_data generic map (c_flow(I), c_flow(J), c_in(V), 8, 4, 32, 1, false, c_bypass(K), 1, 1, c_nof_repeat, 1, 0); -- g_pkt_len < g_in_nof_words + u_8_4_32_1_len_2_gap_0 : entity work.tb_dp_repack_data generic map (c_flow(I), c_flow(J), c_in(V), 8, 4, 32, 1, false, c_bypass(K), 1, 1, c_nof_repeat, 2, 0); -- g_pkt_len = g_in_nof_words + u_8_4_32_1_len_3_gap_0 : entity work.tb_dp_repack_data generic map (c_flow(I), c_flow(J), c_in(V), 8, 4, 32, 1, false, c_bypass(K), 1, 1, c_nof_repeat, 3, 0); -- g_pkt_len > g_in_nof_words, MOD /= 0 + u_8_4_32_1_len_10_gap_0 : entity work.tb_dp_repack_data generic map (c_flow(I), c_flow(J), c_in(V), 8, 4, 32, 1, false, c_bypass(K), 1, 1, c_nof_repeat, 10, 0); -- g_pkt_len > g_in_nof_words, MOD /= 0 + u_8_4_32_1_len_11_gap_0 : entity work.tb_dp_repack_data generic map (c_flow(I), c_flow(J), c_in(V), 8, 4, 32, 1, false, c_bypass(K), 1, 1, c_nof_repeat, 11, 0); -- g_pkt_len > g_in_nof_words, MOD /= 0 + u_8_4_32_1_len_12_gap_0 : entity work.tb_dp_repack_data generic map (c_flow(I), c_flow(J), c_in(V), 8, 4, 32, 1, false, c_bypass(K), 1, 1, c_nof_repeat, 12, 0); -- g_pkt_len > g_in_nof_words, MOD = 0 + + u_8_4_32_1_len_12_gap_2 : entity work.tb_dp_repack_data generic map (c_flow(I), c_flow(J), c_in(V), 8, 4, 32, 1, false, c_bypass(K), 1, 1, c_nof_repeat, 12, 2); -- g_pkt_gap > 0 + + -- g_in_nof_words < g_pack_nof_words will apply backpressure, because the output stage needs to output more + u_32_1_8_4_len_1_gap_0 : entity work.tb_dp_repack_data generic map (c_flow(I), c_flow(J), c_in(V), 32, 1, 8, 4, c_bypass(K), false, 1, 1, c_nof_repeat, 1, 0); -- g_pkt_len = g_in_nof_words + u_32_1_8_4_len_2_gap_0 : entity work.tb_dp_repack_data generic map (c_flow(I), c_flow(J), c_in(V), 32, 1, 8, 4, c_bypass(K), false, 1, 1, c_nof_repeat, 2, 0); -- g_pkt_len > g_in_nof_words + u_32_1_8_4_len_3_gap_0 : entity work.tb_dp_repack_data generic map (c_flow(I), c_flow(J), c_in(V), 32, 1, 8, 4, c_bypass(K), false, 1, 1, c_nof_repeat, 3, 0); -- g_pkt_len > g_in_nof_words + u_32_1_8_4_len_10_gap_0 : entity work.tb_dp_repack_data generic map (c_flow(I), c_flow(J), c_in(V), 32, 1, 8, 4, c_bypass(K), false, 1, 1, c_nof_repeat, 10, 0); -- g_pkt_len > g_in_nof_words + + u_32_1_8_4_len_11_gap_1 : entity work.tb_dp_repack_data generic map (c_flow(I), c_flow(J), c_in(V), 32, 1, 8, 4, c_bypass(K), false, 1, 1, c_nof_repeat, 11, 1); -- g_pkt_gap > 0 + + -- g_in_dat_w MOD 8 /= 0, g_in_nof_words=1 + u_14_1_8_2_len_10_gap_0 : entity work.tb_dp_repack_data generic map (c_flow(I), c_flow(J), c_in(V), 14, 1, 8, 2, c_bypass(K), false, 1, 1, c_nof_repeat, 10, 0); -- repack with subsection padding, even multiple of g_in_nof_words + u_14_1_8_2_len_11_gap_0 : entity work.tb_dp_repack_data generic map (c_flow(I), c_flow(J), c_in(V), 14, 1, 8, 2, c_bypass(K), false, 1, 1, c_nof_repeat, 11, 0); -- repack with subsection padding, odd multiple of g_in_nof_words + + -- g_in_dat_w MOD 8 /= 0, g_out_nof_words=1 + u_5_2_16_1_len_10_gap_0 : entity work.tb_dp_repack_data generic map (c_flow(I), c_flow(J), c_in(V), 5, 2, 16, 1, false, c_bypass(K), 1, 1, c_nof_repeat, 10, 0); -- repack with subsection padding, integer multiple of g_in_nof_words + u_5_2_16_1_len_11_gap_0 : entity work.tb_dp_repack_data generic map (c_flow(I), c_flow(J), c_in(V), 5, 2, 16, 1, false, c_bypass(K), 1, 1, c_nof_repeat, 11, 0); -- repack with subsection padding, fractional multiple of g_in_nof_words + + -- g_in_nof_words=1, g_pack_nof_words>1 + u_8_1_4_2_len_10_gap_0 : entity work.tb_dp_repack_data generic map (c_flow(I), c_flow(J), c_in(V), 8, 1, 4, 2, c_bypass(K), false, 1, 1, c_nof_repeat, 10, 0); + u_512_1_32_16_len_1_gap_20 : entity work.tb_dp_repack_data generic map (c_flow(I), c_flow(J), c_in(V), 512, 1, 32, 16, c_bypass(K), false, 1, 1, c_nof_repeat, 1, 20); -- pack a larger header slv into g_pack_dat_w words + + -- serialize to and deserialize from g_pack_dat_w=1 bit + u_8_1_1_8_len_10_gap_0 : entity work.tb_dp_repack_data generic map (c_flow(I), c_flow(J), c_in(V), 8, 1, 1, 8, c_bypass(K), false, 1, 1, c_nof_repeat, 10, 0); -- g_pack_dat_w=1 + u_32_1_1_32_len_10_gap_7 : entity work.tb_dp_repack_data generic map (c_flow(I), c_flow(J), c_in(V), 32, 1, 1, 32, c_bypass(K), false, 1, 1, c_nof_repeat, 10, 7); -- g_pack_dat_w=1 + + -- g_in_symbol_w /= 1, g_out_symbol_w /= 1 + u_20_1_8_3_symbol_1_4_len_10_gap_0 : entity work.tb_dp_repack_data generic map (c_flow(I), c_flow(J), c_in(V), 20, 1, 8, 3, c_bypass(K), false, 1, 4, c_nof_repeat, 10, 0); -- no repack + u_20_1_8_3_symbol_4_1_len_10_gap_0 : entity work.tb_dp_repack_data generic map (c_flow(I), c_flow(J), c_in(V), 20, 1, 8, 3, c_bypass(K), false, 4, 1, c_nof_repeat, 10, 0); -- no repack + u_20_1_8_3_symbol_4_4_len_10_gap_0 : entity work.tb_dp_repack_data generic map (c_flow(I), c_flow(J), c_in(V), 20, 1, 8, 3, c_bypass(K), false, 4, 4, c_nof_repeat, 10, 0); -- no repack + + -- pack ETH/IP/UDP header, g_in_symbol_w = 8, g_out_symbol_w = 8 + u_336_1_32_11_symbol_8_8_len_1_gap_0 : entity work.tb_dp_repack_data generic map (c_flow(I), c_flow(J), c_in(V), 336, 1, 32, 11, c_bypass(K), false, 8, 8, c_nof_repeat, 1, 0); -- pack to 32 bit --> empty = 2 + u_336_1_64_6_symbol_8_8_len_1_gap_0 : entity work.tb_dp_repack_data generic map (c_flow(I), c_flow(J), c_in(V), 336, 1, 64, 6, c_bypass(K), false, 8, 8, c_nof_repeat, 1, 0); -- pack to 64 bit --> empty = 6 end generate; - -- no repack, g_in_nof_words = g_out_nof_words > 1 - u_16_3_16_3_len_10_gap_0 : entity work.tb_dp_repack_data generic map (c_flow(I), c_flow(J), 16, 3, 16, 3, c_bool(K), c_bool(K), 1, 1, c_nof_repeat, 10, 0); - - -- g_in_nof_words > g_pack_nof_words can use always active stimuli except when g_pkt_len MOD g_in_nof_words /= 0, because then the input stage needs to flush - u_8_4_32_1_len_1_gap_0 : entity work.tb_dp_repack_data generic map (c_flow(I), c_flow(J), 8, 4, 32, 1, false, c_bool(K), 1, 1, c_nof_repeat, 1, 0); -- g_pkt_len < g_in_nof_words - u_8_4_32_1_len_2_gap_0 : entity work.tb_dp_repack_data generic map (c_flow(I), c_flow(J), 8, 4, 32, 1, false, c_bool(K), 1, 1, c_nof_repeat, 2, 0); -- g_pkt_len = g_in_nof_words - u_8_4_32_1_len_3_gap_0 : entity work.tb_dp_repack_data generic map (c_flow(I), c_flow(J), 8, 4, 32, 1, false, c_bool(K), 1, 1, c_nof_repeat, 3, 0); -- g_pkt_len > g_in_nof_words, MOD /= 0 - u_8_4_32_1_len_10_gap_0 : entity work.tb_dp_repack_data generic map (c_flow(I), c_flow(J), 8, 4, 32, 1, false, c_bool(K), 1, 1, c_nof_repeat, 10, 0); -- g_pkt_len > g_in_nof_words, MOD /= 0 - u_8_4_32_1_len_11_gap_0 : entity work.tb_dp_repack_data generic map (c_flow(I), c_flow(J), 8, 4, 32, 1, false, c_bool(K), 1, 1, c_nof_repeat, 11, 0); -- g_pkt_len > g_in_nof_words, MOD /= 0 - u_8_4_32_1_len_12_gap_0 : entity work.tb_dp_repack_data generic map (c_flow(I), c_flow(J), 8, 4, 32, 1, false, c_bool(K), 1, 1, c_nof_repeat, 12, 0); -- g_pkt_len > g_in_nof_words, MOD = 0 - - u_8_4_32_1_len_12_gap_2 : entity work.tb_dp_repack_data generic map (c_flow(I), c_flow(J), 8, 4, 32, 1, false, c_bool(K), 1, 1, c_nof_repeat, 12, 2); -- g_pkt_gap > 0 - - -- g_in_nof_words < g_pack_nof_words will apply backpressure, because the output stage needs to output more - u_32_1_8_4_len_1_gap_0 : entity work.tb_dp_repack_data generic map (c_flow(I), c_flow(J), 32, 1, 8, 4, c_bool(K), false, 1, 1, c_nof_repeat, 1, 0); -- g_pkt_len = g_in_nof_words - u_32_1_8_4_len_2_gap_0 : entity work.tb_dp_repack_data generic map (c_flow(I), c_flow(J), 32, 1, 8, 4, c_bool(K), false, 1, 1, c_nof_repeat, 2, 0); -- g_pkt_len > g_in_nof_words - u_32_1_8_4_len_3_gap_0 : entity work.tb_dp_repack_data generic map (c_flow(I), c_flow(J), 32, 1, 8, 4, c_bool(K), false, 1, 1, c_nof_repeat, 3, 0); -- g_pkt_len > g_in_nof_words - u_32_1_8_4_len_10_gap_0 : entity work.tb_dp_repack_data generic map (c_flow(I), c_flow(J), 32, 1, 8, 4, c_bool(K), false, 1, 1, c_nof_repeat, 10, 0); -- g_pkt_len > g_in_nof_words - - u_32_1_8_4_len_11_gap_1 : entity work.tb_dp_repack_data generic map (c_flow(I), c_flow(J), 32, 1, 8, 4, c_bool(K), false, 1, 1, c_nof_repeat, 11, 1); -- g_pkt_gap > 0 - - -- g_in_dat_w MOD 8 /= 0, g_in_nof_words=1 - u_14_1_8_2_len_10_gap_0 : entity work.tb_dp_repack_data generic map (c_flow(I), c_flow(J), 14, 1, 8, 2, c_bool(K), false, 1, 1, c_nof_repeat, 10, 0); -- repack with subsection padding, even multiple of g_in_nof_words - u_14_1_8_2_len_11_gap_0 : entity work.tb_dp_repack_data generic map (c_flow(I), c_flow(J), 14, 1, 8, 2, c_bool(K), false, 1, 1, c_nof_repeat, 11, 0); -- repack with subsection padding, odd multiple of g_in_nof_words - - -- g_in_dat_w MOD 8 /= 0, g_out_nof_words=1 - u_5_2_16_1_len_10_gap_0 : entity work.tb_dp_repack_data generic map (c_flow(I), c_flow(J), 5, 2, 16, 1, false, c_bool(K), 1, 1, c_nof_repeat, 10, 0); -- repack with subsection padding, integer multiple of g_in_nof_words - u_5_2_16_1_len_11_gap_0 : entity work.tb_dp_repack_data generic map (c_flow(I), c_flow(J), 5, 2, 16, 1, false, c_bool(K), 1, 1, c_nof_repeat, 11, 0); -- repack with subsection padding, fractional multiple of g_in_nof_words - - -- g_in_nof_words=1, g_pack_nof_words>1 - u_8_1_4_2_len_10_gap_0 : entity work.tb_dp_repack_data generic map (c_flow(I), c_flow(J), 8, 1, 4, 2, c_bool(K), false, 1, 1, c_nof_repeat, 10, 0); - u_512_1_32_16_len_1_gap_20 : entity work.tb_dp_repack_data generic map (c_flow(I), c_flow(J), 512, 1, 32, 16, c_bool(K), false, 1, 1, c_nof_repeat, 1, 20); -- pack a larger header slv into g_pack_dat_w words - - -- serialize to and deserialize from g_pack_dat_w=1 bit - u_8_1_1_8_len_10_gap_0 : entity work.tb_dp_repack_data generic map (c_flow(I), c_flow(J), 8, 1, 1, 8, c_bool(K), false, 1, 1, c_nof_repeat, 10, 0); -- g_pack_dat_w=1 - u_32_1_1_32_len_10_gap_7 : entity work.tb_dp_repack_data generic map (c_flow(I), c_flow(J), 32, 1, 1, 32, c_bool(K), false, 1, 1, c_nof_repeat, 10, 7); -- g_pack_dat_w=1 - - -- g_in_symbol_w /= 1, g_out_symbol_w /= 1 - u_20_1_8_3_symbol_1_4_len_10_gap_0 : entity work.tb_dp_repack_data generic map (c_flow(I), c_flow(J), 20, 1, 8, 3, c_bool(K), false, 1, 4, c_nof_repeat, 10, 0); -- no repack - u_20_1_8_3_symbol_4_1_len_10_gap_0 : entity work.tb_dp_repack_data generic map (c_flow(I), c_flow(J), 20, 1, 8, 3, c_bool(K), false, 4, 1, c_nof_repeat, 10, 0); -- no repack - u_20_1_8_3_symbol_4_4_len_10_gap_0 : entity work.tb_dp_repack_data generic map (c_flow(I), c_flow(J), 20, 1, 8, 3, c_bool(K), false, 4, 4, c_nof_repeat, 10, 0); -- no repack - - -- pack ETH/IP/UDP header, g_in_symbol_w = 8, g_out_symbol_w = 8 - u_336_1_32_11_symbol_8_8_len_1_gap_0 : entity work.tb_dp_repack_data generic map (c_flow(I), c_flow(J), 336, 1, 32, 11, c_bool(K), false, 8, 8, c_nof_repeat, 1, 0); -- pack to 32 bit --> empty = 2 - u_336_1_64_6_symbol_8_8_len_1_gap_0 : entity work.tb_dp_repack_data generic map (c_flow(I), c_flow(J), 336, 1, 64, 6, c_bool(K), false, 8, 8, c_nof_repeat, 1, 0); -- pack to 64 bit --> empty = 6 + ------------------------------------------------------------------------- + -- Tests that cannot use bypass + ------------------------------------------------------------------------- + + -- g_in_nof_words > 1 and g_pack_nof_words > 1 + u_24_2_16_3_len_1_gap_0 : entity work.tb_dp_repack_data generic map (c_flow(I), c_flow(J), c_in(V), 24, 2, 16, 3, false, false, 1, 1, c_nof_repeat, 1, 0); -- g_pkt_len < g_in_nof_words + u_24_2_16_3_len_2_gap_0 : entity work.tb_dp_repack_data generic map (c_flow(I), c_flow(J), c_in(V), 24, 2, 16, 3, false, false, 1, 1, c_nof_repeat, 2, 0); -- g_pkt_len = g_in_nof_words + u_24_2_16_3_len_3_gap_0 : entity work.tb_dp_repack_data generic map (c_flow(I), c_flow(J), c_in(V), 24, 2, 16, 3, false, false, 1, 1, c_nof_repeat, 3, 0); -- g_pkt_len = fractional multiple of g_in_nof_words + u_24_2_16_3_len_10_gap_0 : entity work.tb_dp_repack_data generic map (c_flow(I), c_flow(J), c_in(V), 24, 2, 16, 3, false, false, 1, 1, c_nof_repeat, 10, 0); -- g_pkt_len = integer multiple of g_in_nof_words + u_24_2_16_3_len_11_gap_0 : entity work.tb_dp_repack_data generic map (c_flow(I), c_flow(J), c_in(V), 24, 2, 16, 3, false, false, 1, 1, c_nof_repeat, 11, 0); -- g_pkt_len = fractional multiple of g_in_nof_words + + u_24_2_16_3_len_11_gap_3 : entity work.tb_dp_repack_data generic map (c_flow(I), c_flow(J), c_in(V), 24, 2, 16, 3, false, false, 1, 1, c_nof_repeat, 11, 3); -- g_pkt_gap > 0 + + -- g_in_dat_w MOD 8 /= 0 + u_6_5_10_3_len_1_gap_0 : entity work.tb_dp_repack_data generic map (c_flow(I), c_flow(J), c_in(V), 6, 5, 10, 3, false, false, 1, 1, c_nof_repeat, 1, 0); -- g_pkt_len < g_in_nof_words + u_6_5_10_3_len_2_gap_0 : entity work.tb_dp_repack_data generic map (c_flow(I), c_flow(J), c_in(V), 6, 5, 10, 3, false, false, 1, 1, c_nof_repeat, 2, 0); -- g_pkt_len < g_in_nof_words + u_6_5_10_3_len_3_gap_0 : entity work.tb_dp_repack_data generic map (c_flow(I), c_flow(J), c_in(V), 6, 5, 10, 3, false, false, 1, 1, c_nof_repeat, 3, 0); -- g_pkt_len < g_in_nof_words + u_6_5_10_3_len_4_gap_0 : entity work.tb_dp_repack_data generic map (c_flow(I), c_flow(J), c_in(V), 6, 5, 10, 3, false, false, 1, 1, c_nof_repeat, 4, 0); -- g_pkt_len < g_in_nof_words + u_6_5_10_3_len_5_gap_0 : entity work.tb_dp_repack_data generic map (c_flow(I), c_flow(J), c_in(V), 6, 5, 10, 3, false, false, 1, 1, c_nof_repeat, 5, 0); -- g_pkt_len = g_in_nof_words + u_6_5_10_3_len_10_gap_0 : entity work.tb_dp_repack_data generic map (c_flow(I), c_flow(J), c_in(V), 6, 5, 10, 3, false, false, 1, 1, c_nof_repeat, 10, 0); -- g_pkt_len = integer multiple of g_in_nof_words + u_6_5_10_3_len_11_gap_0 : entity work.tb_dp_repack_data generic map (c_flow(I), c_flow(J), c_in(V), 6, 5, 10, 3, false, false, 1, 1, c_nof_repeat, 11, 0); -- g_pkt_len = fractional multiple of g_in_nof_words + + u_6_5_10_3_len_21_gap_3 : entity work.tb_dp_repack_data generic map (c_flow(I), c_flow(J), c_in(V), 6, 5, 10, 3, false, false, 1, 1, c_nof_repeat, 21, 3); -- g_pkt_gap > 0 + + -- subsection padding, g_in_dat_w * g_in_nof_words < g_pack_dat_w * g_pack_nof_words + u_18_2_8_5_len_1_gap_0 : entity work.tb_dp_repack_data generic map (c_flow(I), c_flow(J), c_in(V), 18, 2, 8, 5, false, false, 1, 1, c_nof_repeat, 1, 0); -- g_pkt_len < g_in_nof_words + u_18_2_8_5_len_2_gap_0 : entity work.tb_dp_repack_data generic map (c_flow(I), c_flow(J), c_in(V), 18, 2, 8, 5, false, false, 1, 1, c_nof_repeat, 2, 0); -- g_pkt_len = g_in_nof_words + u_18_2_8_5_len_3_gap_0 : entity work.tb_dp_repack_data generic map (c_flow(I), c_flow(J), c_in(V), 18, 2, 8, 5, false, false, 1, 1, c_nof_repeat, 3, 0); -- g_pkt_len = fractional multiple of g_in_nof_words + u_18_2_8_5_len_10_gap_0 : entity work.tb_dp_repack_data generic map (c_flow(I), c_flow(J), c_in(V), 18, 2, 8, 5, false, false, 1, 1, c_nof_repeat, 10, 0); -- g_pkt_len = integer multiple of g_in_nof_words end generate; - - ------------------------------------------------------------------------- - -- Tests that cannot use bypass - ------------------------------------------------------------------------- - - -- g_in_nof_words > 1 and g_pack_nof_words > 1 - u_24_2_16_3_len_1_gap_0 : entity work.tb_dp_repack_data generic map (c_flow(I), c_flow(J), 24, 2, 16, 3, false, false, 1, 1, c_nof_repeat, 1, 0); -- g_pkt_len < g_in_nof_words - u_24_2_16_3_len_2_gap_0 : entity work.tb_dp_repack_data generic map (c_flow(I), c_flow(J), 24, 2, 16, 3, false, false, 1, 1, c_nof_repeat, 2, 0); -- g_pkt_len = g_in_nof_words - u_24_2_16_3_len_3_gap_0 : entity work.tb_dp_repack_data generic map (c_flow(I), c_flow(J), 24, 2, 16, 3, false, false, 1, 1, c_nof_repeat, 3, 0); -- g_pkt_len = fractional multiple of g_in_nof_words - u_24_2_16_3_len_10_gap_0 : entity work.tb_dp_repack_data generic map (c_flow(I), c_flow(J), 24, 2, 16, 3, false, false, 1, 1, c_nof_repeat, 10, 0); -- g_pkt_len = integer multiple of g_in_nof_words - u_24_2_16_3_len_11_gap_0 : entity work.tb_dp_repack_data generic map (c_flow(I), c_flow(J), 24, 2, 16, 3, false, false, 1, 1, c_nof_repeat, 11, 0); -- g_pkt_len = fractional multiple of g_in_nof_words - - u_24_2_16_3_len_11_gap_3 : entity work.tb_dp_repack_data generic map (c_flow(I), c_flow(J), 24, 2, 16, 3, false, false, 1, 1, c_nof_repeat, 11, 3); -- g_pkt_gap > 0 - - -- g_in_dat_w MOD 8 /= 0 - u_6_5_10_3_len_1_gap_0 : entity work.tb_dp_repack_data generic map (c_flow(I), c_flow(J), 6, 5, 10, 3, false, false, 1, 1, c_nof_repeat, 1, 0); -- g_pkt_len < g_in_nof_words - u_6_5_10_3_len_2_gap_0 : entity work.tb_dp_repack_data generic map (c_flow(I), c_flow(J), 6, 5, 10, 3, false, false, 1, 1, c_nof_repeat, 2, 0); -- g_pkt_len < g_in_nof_words - u_6_5_10_3_len_3_gap_0 : entity work.tb_dp_repack_data generic map (c_flow(I), c_flow(J), 6, 5, 10, 3, false, false, 1, 1, c_nof_repeat, 3, 0); -- g_pkt_len < g_in_nof_words - u_6_5_10_3_len_4_gap_0 : entity work.tb_dp_repack_data generic map (c_flow(I), c_flow(J), 6, 5, 10, 3, false, false, 1, 1, c_nof_repeat, 4, 0); -- g_pkt_len < g_in_nof_words - u_6_5_10_3_len_5_gap_0 : entity work.tb_dp_repack_data generic map (c_flow(I), c_flow(J), 6, 5, 10, 3, false, false, 1, 1, c_nof_repeat, 5, 0); -- g_pkt_len = g_in_nof_words - u_6_5_10_3_len_10_gap_0 : entity work.tb_dp_repack_data generic map (c_flow(I), c_flow(J), 6, 5, 10, 3, false, false, 1, 1, c_nof_repeat, 10, 0); -- g_pkt_len = integer multiple of g_in_nof_words - u_6_5_10_3_len_11_gap_0 : entity work.tb_dp_repack_data generic map (c_flow(I), c_flow(J), 6, 5, 10, 3, false, false, 1, 1, c_nof_repeat, 11, 0); -- g_pkt_len = fractional multiple of g_in_nof_words - - u_6_5_10_3_len_21_gap_3 : entity work.tb_dp_repack_data generic map (c_flow(I), c_flow(J), 6, 5, 10, 3, false, false, 1, 1, c_nof_repeat, 21, 3); -- g_pkt_gap > 0 - - -- subsection padding, g_in_dat_w * g_in_nof_words < g_pack_dat_w * g_pack_nof_words - u_18_2_8_5_len_1_gap_0 : entity work.tb_dp_repack_data generic map (c_flow(I), c_flow(J), 18, 2, 8, 5, false, false, 1, 1, c_nof_repeat, 1, 0); -- g_pkt_len < g_in_nof_words - u_18_2_8_5_len_2_gap_0 : entity work.tb_dp_repack_data generic map (c_flow(I), c_flow(J), 18, 2, 8, 5, false, false, 1, 1, c_nof_repeat, 2, 0); -- g_pkt_len = g_in_nof_words - u_18_2_8_5_len_3_gap_0 : entity work.tb_dp_repack_data generic map (c_flow(I), c_flow(J), 18, 2, 8, 5, false, false, 1, 1, c_nof_repeat, 3, 0); -- g_pkt_len = fractional multiple of g_in_nof_words - u_18_2_8_5_len_10_gap_0 : entity work.tb_dp_repack_data generic map (c_flow(I), c_flow(J), 18, 2, 8, 5, false, false, 1, 1, c_nof_repeat, 10, 0); -- g_pkt_len = integer multiple of g_in_nof_words end generate; end generate; end tb;