diff --git a/libraries/base/dp/src/vhdl/dp_packet_unmerge.vhd b/libraries/base/dp/src/vhdl/dp_packet_unmerge.vhd index 9a8401456e7753a45023be5912ec77afb4eb0af7..26c9f6656e7eab03f42af23ad26e6ce03b71d75e 100644 --- a/libraries/base/dp/src/vhdl/dp_packet_unmerge.vhd +++ b/libraries/base/dp/src/vhdl/dp_packet_unmerge.vhd @@ -22,13 +22,21 @@ -- Author: E. Kooistra -- Purpose: Unmerge each input packet into output packets of length g_pkt_len. -- Description: --- . The merged packet length of the snk_in input packets must be an integer --- multiple of g_pkt_len. The number of output packets g_nof_pkt_max is only --- used to determine the maximum supported pkt_cnt range. The actual number --- of output packets has to be <= g_nof_pkt_max, and is determined by input --- packet length / g_pkt_len. Hence the dp_packet_unmerge can dynamically --- handle different sizes of input packets, provided that their length is an --- integer multiple of g_pkt_len. +-- . The merged packet length of the snk_in input packets is unmerged into +-- ceil(input packet length / pkt_len). The unmerged output packets have +-- length pkt_len, but if input packet length mod pkt_len /= 0, then the +-- last packet will contain the remaining data of the input packet and have +-- length < pkt_len. Corner cases: +-- - If pkt_len > input packet length, then the output = input +-- - The length of the last output packet is input packet length mod +-- pkt_len, so it can have minimal lenght 1. +-- . The dynamic pkt_len value is captured at the input eop, or between input +-- packets, to have a stable value during the unmerge. +-- . The number of output packets g_nof_pkt is only used to determine the +-- maximum supported pkt_cnt range. The actual number of output packets has +-- to be <= g_nof_pkt, and is determined by input packet length / +-- pkt_len. Hence the dp_packet_unmerge can dynamically handle different +-- sizes of input packets. -- . The pkt_cnt is passed on as src_out.channel index. -- . The g_bsn_increment sets the BSN increment for the unmerged output -- packets relative to the BSN of the snk_in input packet. When @@ -51,6 +59,9 @@ -- -- . Optional flow control dependent on g_use_ready and g_pipeline_ready, see -- description of dp_add_flow_control. +-- . g_pkt_len statically sets the length of the unmerged packets in absence of +-- dynamic pkt_len control. When the pkt_len control input is used, g_pkt_len +-- sets the maximum number length of the unmerged packets. library IEEE,common_lib; use IEEE.std_logic_1164.all; @@ -62,7 +73,7 @@ entity dp_packet_unmerge is generic ( g_use_ready : boolean := true; g_pipeline_ready : boolean := false; - g_nof_pkt_max : natural := 1; -- Maximum nof packets to unmerge each incoming packet to + g_nof_pkt : natural := 1; -- Number of packets to unmerge each incoming packet to g_pkt_len : natural := 1; -- Length of the unmerged packets g_bsn_increment : natural := 0 ); @@ -70,6 +81,9 @@ entity dp_packet_unmerge is rst : in std_logic; clk : in std_logic; + pkt_len : in std_logic_vector(ceil_log2(g_pkt_len + 1) - 1 downto 0) := to_uvec(g_pkt_len, ceil_log2(g_pkt_len + 1)); + pkt_len_out : out std_logic_vector(ceil_log2(g_pkt_len + 1) - 1 downto 0); -- Valid at src_out.sop + snk_out : out t_dp_siso; snk_in : in t_dp_sosi; @@ -79,20 +93,28 @@ entity dp_packet_unmerge is end dp_packet_unmerge; architecture rtl of dp_packet_unmerge is + constant c_nof_pkt_max : natural := g_nof_pkt + 1; + constant c_pkt_len_max : natural := g_pkt_len + 1; + constant c_pkt_len_w : natural := ceil_log2(c_pkt_len_max); + -- Internal state of logic function type t_reg is record - pkt_cnt : natural range 0 to g_nof_pkt_max + 1; - val_cnt : natural range 0 to g_pkt_len + 1; + pkt_cnt : natural range 0 to c_nof_pkt_max; + pkt_len : natural range 0 to c_pkt_len_max; + val_cnt : natural range 0 to c_pkt_len_max; + busy : std_logic; src_out : t_dp_sosi; end record; - constant c_reg_rst : t_reg := (0, 0, c_dp_sosi_rst); + constant c_reg_rst : t_reg := (0, 0, 0, '0', c_dp_sosi_rst); signal r : t_reg; signal d : t_reg; begin -- Map logic function outputs to entity outputs + pkt_len_out <= to_uvec(r.pkt_len, c_pkt_len_w); + u_dp_add_flow_control : entity work.dp_add_flow_control generic map ( g_use_ready => g_use_ready, @@ -114,19 +136,19 @@ begin r <= d when rising_edge(clk); -- Logic function - p_comb : process(rst, r, snk_in) + p_comb : process(rst, r, snk_in, pkt_len) variable v : t_reg; begin -- Default v := r; - -- Function - -- _ _ _ - -- snk_in.sop __| |_______________| |_______________| |_______________| - -- _ _ _ - -- snk_in.eop _________________| |_______________| |_______________| |_ - -- _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ - -- snk_in.valid __| + -- Function: unmerge input packet into output packets + -- _ _ _ + -- snk_in.sop __| |_______________| |_______________| |_______________| + -- _ _ _ + -- snk_in.eop _________________| |_______________| |_______________| |_ + -- _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + -- snk_in.valid __| -- v.val_cnt 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 -- v.pkt_cnt 0 1 2 0 1 2 0 1 2 -- ______________ _______________ _______________ _ @@ -154,6 +176,18 @@ begin v.pkt_cnt := r.pkt_cnt + 1; end if; + -- capture pkt_len between input packets when there is no unmerge busy + if snk_in.sop = '1' then + v.busy := '1'; + end if; + if snk_in.eop = '1' then + v.busy := '0'; + end if; + + if v.busy = '0' then + v.pkt_len := to_uint(pkt_len); + end if; + -- output packet bsn, sync, sop and eop -- . Default passes on snk_in.sync, valid, data, re, im -- . The sync, valid can be passed on from snk_in, without checking @@ -173,7 +207,12 @@ begin if v.val_cnt = 0 then v.src_out.sop := '1'; end if; - if v.val_cnt = g_pkt_len - 1 then + -- Unmerge packets of length r.pkt_len + if v.val_cnt = r.pkt_len - 1 then + v.src_out.eop := '1'; + end if; + -- Unmerge last packet with length <= r.pkt_len + if snk_in.eop = '1' then v.src_out.eop := '1'; end if; end if;