URL
https://opencores.org/ocsvn/dp_repack_data/dp_repack_data/trunk
Subversion Repositories dp_repack_data
Compare Revisions
- This comparison shows the changes necessary to convert path
/dp_repack_data/trunk
- from Rev 1 to Rev 2
- ↔ Reverse comparison
Rev 1 → Rev 2
/dp_repack_data.vhd
0,0 → 1,748
-------------------------------------------------------------------------------- |
-- |
-- 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/>. |
-- |
-------------------------------------------------------------------------------- |
|
-- Purpose: |
-- The dp_repack_data works both as packer and as unpacker. |
-- |
-- Block diagram: |
-- |
-- A) Functional |
-- The drawing shows g_in_nof_words=4 and g_out_nof_words=2 as example: |
-- |
-- dp_repack_in dp_repack_out |
-- ___ ___ |
-- | | pack_sosi | |--> src_out |
-- | 3 |--------------------->| 1 | |
-- | | | | |
-- | 2 | ^ | | ^ |
-- | | |valid | | |shift |
-- | 1 | |flush | 0 | | |
-- | | | | | | |
-- | 0 | | | |
-- snk_in -->|___| pack_siso |___| |
-- snk_out.ready <-- <--------------------- <-- src_in.ready |
-- snk_out.xon <------------------------------------- src_in.xon |
-- |
-- |
-- B) Flow control |
-- |
-- RL=1 RL=1 RL=1 |
-- . . . |
-- . /-----------------------------------------\ |
-- . | . _____ . | |
-- . | /------\ nxt_r | | r | |
-- . \-->| |---*-------*----->|p_reg|-----*---> src_out |
-- . | | | | |_____| |
-- snk_in -------->|p_comb|<--|-------|--------------*-------- src_in |
-- | | | | | |
-- | | | v | |
-- | | | /-------\ | |
-- | | | |p_flow | | |
-- \------/ | \-------/ | |
-- | | | |
-- nxt_r.hold_out.valid | | | |
-- v | | |
-- /| |r_snk_out | |
-- |0|------/ | |
-- snk_out <------------------| | | |
-- |1|---------------------/ |
-- \| |
-- |
-- Description: |
-- The dp_repack_data repacks g_in_nof_words of width g_in_dat_w into |
-- g_out_nof_words of width g_out_dat_w. |
-- |
-- . g_in_bypass, g_out_bypass |
-- The dp_repack_in and dp_repack_out can be bypassed to save logic and to |
-- avoid the pipeline stage. Default both are FALSE, but they can be set |
-- TRUE if: |
-- |
-- . g_in_bypass =TRUE if g_in_nof_words=g_out_nof_words or g_in_nof_words=1 |
-- . g_out_bypass=TRUE if g_in_nof_words=g_out_nof_words or g_out_nof_words=1 |
-- |
-- Both the dp_repack_in and dp_repack_out stage do work correctly independent |
-- of the g_*_bypass setting. When g_*_bypass=FALSE then they merely |
-- add a transparant pipeline delay. It is important that they also work for |
-- g_*_bypass=FALSE because that gives confidence that their implementation |
-- structure is ok. |
-- |
-- . g_in_nof_words and input block size |
-- The input block size in words is indicated by snk_in.sop and snk_in.eop. |
-- Each subsection of g_in_nof_words is packed into g_out_nof_words. The |
-- input block size does not have to be a multiple of g_in_nof_words. When |
-- the snk_in.eop occurs the last repack is initiated without need for input |
-- data padding. If the block length is an integer multiple of |
-- g_in_nof_words then the dp_repack_data introduces no gaps between blocks. |
-- If the block length is a fractional multiple of g_in_nof_words then there |
-- will be a gap after the block due to that the dp_repack_in needs to |
-- shift up the last subsection for the 'missing' input words. |
-- |
-- . g_in_dat_w*g_in_nof_words <, =, > g_in_dat_w*g_in_nof_words |
-- . = : no subsection zero padding |
-- . < : the subsections will be zero padded |
-- . > : then the input must have sufficient zero padded bits per |
-- subsection that can be stripped without data loss. |
-- |
-- . Resolution of the empty field |
-- The g_in_symbol_w is used to define the resolution of snk_in.empty and |
-- the g_out_symbol_w is used to define the resolution of src_out.empty. If |
-- they are 1 then the resolution is in number of bits, because the symbol |
-- size is then 1 bit. Their value has no effect on the packed data it self, |
-- only on the meaning of the empty field. Hence if the empty field is not |
-- used, then the setting of g_in_symbol_w and g_out_symbol_w is dont care. |
-- |
-- Remarks: |
-- . Originally reused from LOFAR rad_repack.vhd and rad_repack(rtl).vhd. This |
-- dp_repack_data still uses the shift in input register in and the shift out |
-- output register, but no longer the intermediate buffer register. |
-- Using shift in and shift out may ease timing closure because the routing |
-- is more local compared to using a demultiplexer to put the input data in |
-- the input register and a multiplexer to get the data directly from the |
-- output register. For the demultiplexer / multiplexer it would be possible |
-- to only use one internal register. |
-- Using shift up is sufficient, the shift down option is not needed. With |
-- shift up the data is input a [0] and output the high index. |
-- Instead of requiring an snk_in.valid duty cycle this dp_repack_data uses |
-- snk_out.ready flow control and can handle src_in.ready flow control. |
-- |
-- . To pack ETH/IP/UDP header slv of 14 + 20 + 8 = 42 octets into 32 bit words |
-- use: |
-- u_dp_repack_data : ENTITY .dp_repack_data |
-- GENERIC MAP ( |
-- g_in_bypass => TRUE, |
-- g_in_dat_w => 8 * 42, |
-- g_in_nof_words => 1, |
-- g_in_symbol_w => 8, |
-- g_out_bypass => FALSE, |
-- g_out_dat_w => 32, |
-- g_out_nof_words => 11, |
-- g_out_symbol_w => 8 |
-- ) |
-- The src_out.empty will be 2, because: |
-- (g_out_dat_w*g_out_nof_words-g_in_dat_w*g_in_nof_words)/g_out_symbol_w |
-- = (32*11 - 42*8*1)/ 8 = 2 octet symbols |
-- |
-- Design steps: |
-- * In total the development took 5 days. On day 3 I was in distress because |
-- I could not get it to work so I needed to rethink. After changing to the |
-- new flow control scheme that uses nxt_r the design was gradually improved |
-- by getting the dp_repack_data instances in tb_tb_dp_repack_data to work one |
-- by one. First only for e_active stimuli and later also for e_random and |
-- e_pulse. Initially about 80 % of the functionality was implemented but |
-- and subsequently each feature was verified starting with the basic |
-- features and then themore detailed features. This step by step approach |
-- makes that the bugs appear one by one instead of all together. Without a |
-- step by step approach the bugs are too big to solve. |
-- . First cases with g_in_nof_words=1 and g_out_nof_words were made to work |
-- for different g_pkt_len <, =, > g_in_nof_words. |
-- . Then the empty functionality for g_pkt_len MOD g_in_nof_words /= 0 was |
-- added. |
-- . Tried g_out_dat_w=1 which makes dp_repack_data a serializer/deserializer. |
-- . Then apply external flow control using c_dp_flow_control_enum_arr in |
-- the tb_tb_dp_repack_data was verified resulting in small corrections. |
-- . Then verified g_in_dat_w * g_in_nof_words > or < g_out_dat_w * |
-- g_out_nof_words which require padding in the subsection. The > case |
-- occurs for packing and the < case then occurs for unpacking. |
-- . Added g_bypass to force using wires instead of a void dp_repack_in or |
-- dp_repack_out stage. |
-- . Verified g_in_symbol_w and g_out_symbol_w /= 1. |
-- * The development used the tb_dp_repack_data testbench that does a pack and |
-- an unpack to be able to verify the data. The c_no_unpack and |
-- c_enable_repack_in and c_enable_repack_out parameters in the tb are |
-- useful to be able to isolate a component for debugging. |
|
LIBRARY IEEE, common_pkg_lib, dp_pkg_lib; |
USE IEEE.std_logic_1164.ALL; |
USE common_pkg_lib.common_pkg.ALL; |
USE dp_pkg_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 |
); |
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 |
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 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(c_in_buf_dat_w-1 DOWNTO 0); |
|
gen_bypass : IF g_bypass=TRUE GENERATE |
snk_out <= src_in; |
i_src_out <= snk_in; |
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 := 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; |
|
-------------------------------------------------------------------------- |
-- 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_pkg_lib, dp_pkg_lib; |
USE IEEE.std_logic_1164.ALL; |
USE common_pkg_lib.common_pkg.ALL; |
USE dp_pkg_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; |
|
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 snk_in_data : STD_LOGIC_VECTOR(g_in_buf_dat_w-1 DOWNTO 0); |
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 |
|
snk_in_data <= snk_in.data(g_in_buf_dat_w-1 DOWNTO 0); |
|
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(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(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_pkg_lib, dp_pkg_lib; |
USE IEEE.std_logic_1164.ALL; |
USE common_pkg_lib.common_pkg.ALL; |
USE dp_pkg_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 |
); |
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 |
); |
END dp_repack_data; |
|
|
ARCHITECTURE str OF dp_repack_data IS |
|
CONSTANT c_in_buf_dat_w : NATURAL := g_in_dat_w * g_in_nof_words; |
|
SIGNAL snk_in_data : STD_LOGIC_VECTOR(g_in_dat_w-1 DOWNTO 0); |
SIGNAL i_snk_out : t_dp_siso; |
|
SIGNAL pack_siso : t_dp_siso; |
SIGNAL pack_sosi : t_dp_sosi; |
SIGNAL pack_sosi_data : STD_LOGIC_VECTOR(c_in_buf_dat_w-1 DOWNTO 0); |
|
SIGNAL i_src_out : t_dp_sosi; |
SIGNAL src_out_data : STD_LOGIC_VECTOR(g_out_dat_w-1 DOWNTO 0); |
|
SIGNAL snk_out_ready_reg : STD_LOGIC_VECTOR(0 TO c_dp_stream_rl); |
SIGNAL pack_ready_reg : STD_LOGIC_VECTOR(0 TO c_dp_stream_rl); |
|
BEGIN |
|
snk_out <= i_snk_out; |
src_out <= i_src_out; |
|
snk_in_data <= snk_in.data(g_in_dat_w-1 DOWNTO 0); |
pack_sosi_data <= pack_sosi.data(c_in_buf_dat_w-1 DOWNTO 0); |
src_out_data <= i_src_out.data(g_out_dat_w-1 DOWNTO 0); |
|
no_dp_repack_in : IF g_enable_repack_in=FALSE GENERATE |
i_snk_out <= pack_siso; |
pack_sosi <= snk_in; |
END GENERATE; |
|
gen_dp_repack_in : IF g_enable_repack_in=TRUE GENERATE |
u_dp_repack_in : ENTITY work.dp_repack_in |
GENERIC MAP ( |
g_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 |
) |
PORT MAP ( |
rst => rst, |
clk => clk, |
|
snk_out => i_snk_out, |
snk_in => snk_in, |
|
src_in => pack_siso, |
src_out => pack_sosi |
); |
END GENERATE; |
|
no_dp_repack_out : IF g_enable_repack_out=FALSE GENERATE |
pack_siso <= src_in; |
i_src_out <= pack_sosi; |
END GENERATE; |
|
gen_dp_repack_out : IF g_enable_repack_out=TRUE GENERATE |
u_dp_repack_out : ENTITY work.dp_repack_out |
GENERIC MAP ( |
g_bypass => g_out_bypass, |
g_in_buf_dat_w => c_in_buf_dat_w, |
g_out_dat_w => g_out_dat_w, |
g_out_nof_words => g_out_nof_words, |
g_out_symbol_w => g_out_symbol_w |
) |
PORT MAP ( |
rst => rst, |
clk => clk, |
|
snk_out => pack_siso, |
snk_in => pack_sosi, |
|
src_in => src_in, |
src_out => i_src_out |
); |
END GENERATE; |
|
-- Simulation only: internal stream RL verification |
proc_dp_siso_alert(clk, snk_in, i_snk_out, snk_out_ready_reg); |
proc_dp_siso_alert(clk, pack_sosi, pack_siso, pack_ready_reg); |
|
END str; |
/hdllib.cfg
0,0 → 1,20
hdl_lib_name = dp_repack_data |
hdl_library_clause_name = dp_repack_data_lib |
hdl_lib_uses_synth = dp_pkg |
hdl_lib_uses_sim = |
hdl_lib_technology = |
|
synth_files = |
dp_repack_data.vhd |
|
test_bench_files = |
tb_dp_repack_data.vhd |
tb_tb_dp_repack_data.vhd |
|
regression_test_vhdl = |
tb_tb_dp_repack_data.vhd |
|
[modelsim_project_file] |
|
|
[quartus_project_file] |
/tb_dp_repack_data.vhd
0,0 → 1,317
------------------------------------------------------------------------------- |
-- |
-- 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/>. |
-- |
------------------------------------------------------------------------------- |
|
-- Purpose: |
-- . Test bench for dp_repack_data |
-- Description: |
-- c_no_unpack |
-- . |
-- g_in_dat_w g_pack_dat_w . g_in_dat_w |
-- g_in_nof_words g_pack_nof_words . g_in_nof_words |
-- . . . . |
-- . u_pack . u_unpack . . |
-- . ______________ . ______________ . |
-- . |dp_repack_data| . |dp_repack_data| . |
-- stimuli_src ---->| |----------->| |----> verify_snk |
-- | in out | pack_src | in out | |
-- |______________| |______________| |
-- |
-- Usage: |
-- > as 10 |
-- > run -all |
-- |
|
LIBRARY IEEE, common_pkg_lib, dp_pkg_lib; |
USE IEEE.std_logic_1164.ALL; |
USE IEEE.numeric_std.ALL; |
USE common_pkg_lib.common_pkg.ALL; |
USE common_pkg_lib.common_lfsr_sequences_pkg.ALL; |
USE common_pkg_lib.tb_common_pkg.ALL; |
USE dp_pkg_lib.dp_stream_pkg.ALL; |
USE dp_pkg_lib.tb_dp_pkg.ALL; |
|
|
ENTITY tb_dp_repack_data IS |
GENERIC ( |
-- general |
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_in_dat_w : NATURAL := 8 * 42; |
g_in_nof_words : NATURAL := 1; |
g_pack_dat_w : NATURAL := 32; |
g_pack_nof_words : NATURAL := 11; |
g_in_bypass : BOOLEAN := TRUE; -- can use TRUE when g_in_nof_words=1 or g_in_nof_words=g_out_nof_words |
g_pack_bypass : BOOLEAN := FALSE; -- can use TRUE when g_out_nof_words=1 or g_in_nof_words=g_out_nof_words |
g_in_symbol_w : NATURAL := 8; -- default 1 for snk_in.empty in nof bits, else use power of 2 |
g_pack_symbol_w : NATURAL := 8; -- default 1 for src_out.empty in nof bits, else use power of 2 |
g_nof_repeat : NATURAL := 10; |
g_pkt_len : NATURAL := 1; -- if not a multiple of g_in_nof_words then the input stage flush creates gap between blocks |
g_pkt_gap : NATURAL := 0 |
); |
END tb_dp_repack_data; |
|
|
ARCHITECTURE tb OF tb_dp_repack_data IS |
|
CONSTANT c_no_unpack : BOOLEAN := FALSE; |
CONSTANT c_enable_repack_in : BOOLEAN := TRUE; |
CONSTANT c_enable_repack_out : BOOLEAN := TRUE; |
|
-- dp_stream_stimuli |
CONSTANT c_stimuli_pulse_active : NATURAL := 3; --g_in_nof_words; |
CONSTANT c_stimuli_pulse_period : NATURAL := 7; |
|
CONSTANT c_data_init : NATURAL := 0; |
CONSTANT c_bsn_init : STD_LOGIC_VECTOR(c_dp_stream_bsn_w-1 DOWNTO 0) := X"0000000000000000"; -- X"0877665544332211" |
CONSTANT c_err_init : NATURAL := 247; |
CONSTANT c_channel_init : NATURAL := 5; -- fixed |
|
-- dp_stream_verify |
CONSTANT c_verify_pulse_active : NATURAL := 1; |
CONSTANT c_verify_pulse_period : NATURAL := 5; |
|
CONSTANT c_data_max : UNSIGNED(g_in_dat_w-1 DOWNTO 0) := (OTHERS=>'1'); |
CONSTANT c_dsp_max : UNSIGNED(g_in_dat_w-1 DOWNTO 0) := (OTHERS=>'1'); |
|
--CONSTANT c_verify_snk_in_cnt_max : t_dp_sosi_unsigned := c_dp_sosi_unsigned_rst; -- default 0 is no wrap |
CONSTANT c_verify_snk_in_cnt_max : t_dp_sosi_unsigned := TO_DP_SOSI_UNSIGNED('0', '0', '0', '0', c_data_max, c_dsp_max, c_dsp_max, c_unsigned_0, c_unsigned_0, c_unsigned_0, c_unsigned_0); |
CONSTANT c_verify_snk_in_cnt_gap : t_dp_sosi_unsigned := c_dp_sosi_unsigned_ones; -- default only accept increment +1 |
|
CONSTANT c_expected_pkt_len : NATURAL := sel_a_b(c_no_unpack, g_pkt_len * g_pack_nof_words / g_in_nof_words, g_pkt_len); |
-- both |
CONSTANT c_sync_period : NATURAL := 10; |
CONSTANT c_sync_offset : NATURAL := 7; |
|
SIGNAL clk : STD_LOGIC := '1'; |
SIGNAL rst : STD_LOGIC := '1'; |
SIGNAL tb_end : STD_LOGIC := '0'; |
|
SIGNAL stimuli_src_in : t_dp_siso := c_dp_siso_rdy; |
SIGNAL stimuli_src_out : t_dp_sosi; |
SIGNAL stimuli_src_out_data : STD_LOGIC_VECTOR(g_in_dat_w-1 DOWNTO 0); |
|
SIGNAL verify_snk_in_enable : t_dp_sosi_sl := c_dp_sosi_sl_rst; |
SIGNAL last_snk_in : t_dp_sosi; |
SIGNAL last_snk_in_evt : STD_LOGIC; |
SIGNAL verify_last_snk_in_evt : t_dp_sosi_sl := c_dp_sosi_sl_rst; |
|
SIGNAL verify_snk_out : t_dp_siso := c_dp_siso_rdy; |
SIGNAL verify_snk_in : t_dp_sosi; |
SIGNAL verify_snk_in_data : STD_LOGIC_VECTOR(g_in_dat_w-1 DOWNTO 0); |
|
-- specific |
SIGNAL pack_src_in : t_dp_siso; |
SIGNAL pack_src_out : t_dp_sosi; |
SIGNAL pack_src_out_data : STD_LOGIC_VECTOR(g_pack_dat_w-1 DOWNTO 0); |
|
SIGNAL unpack_src_in : t_dp_siso; |
SIGNAL unpack_src_out : t_dp_sosi; |
SIGNAL unpack_src_out_data : STD_LOGIC_VECTOR(g_in_dat_w-1 DOWNTO 0); |
|
BEGIN |
|
clk <= (NOT clk) OR tb_end AFTER clk_period/2; |
rst <= '1', '0' AFTER clk_period*7; |
|
------------------------------------------------------------------------------ |
-- DATA GENERATION |
------------------------------------------------------------------------------ |
|
u_dp_stream_stimuli : ENTITY dp_pkg_lib.dp_stream_stimuli |
GENERIC MAP ( |
g_instance_nr => 0, -- only one stream so choose index 0 |
-- flow control |
g_random_w => 15, -- use different random width for stimuli and for verify to have different random sequences |
g_pulse_active => c_stimuli_pulse_active, |
g_pulse_period => c_stimuli_pulse_period, |
g_flow_control => g_flow_control_stimuli, -- always active, random or pulse flow control |
-- initializations |
g_sync_period => c_sync_period, |
g_sync_offset => c_sync_offset, |
g_data_init => c_data_init, |
g_bsn_init => c_bsn_init, |
g_err_init => c_err_init, |
g_channel_init => c_channel_init, |
-- specific |
g_in_dat_w => g_in_dat_w, |
g_nof_repeat => g_nof_repeat, |
g_pkt_len => g_pkt_len, |
g_pkt_gap => g_pkt_gap |
) |
PORT MAP ( |
rst => rst, |
clk => clk, |
|
-- Generate stimuli |
src_in => stimuli_src_in, |
src_out => stimuli_src_out, |
|
-- End of stimuli |
last_snk_in => last_snk_in, -- expected verify_snk_in after end of stimuli |
last_snk_in_evt => last_snk_in_evt, -- trigger verify to verify the last_snk_in |
tb_end => tb_end -- signal end of tb as far as this dp_stream_stimuli is concerned |
); |
|
|
------------------------------------------------------------------------------ |
-- DATA VERIFICATION |
------------------------------------------------------------------------------ |
|
-- Select fields that need to be verified |
-- . during the test |
verify_snk_in_enable.sync <= '1'; |
verify_snk_in_enable.bsn <= '1'; |
verify_snk_in_enable.data <= '1' WHEN c_no_unpack=FALSE ELSE '0'; |
verify_snk_in_enable.re <= '0'; |
verify_snk_in_enable.im <= '0'; |
verify_snk_in_enable.valid <= '1'; |
verify_snk_in_enable.sop <= '1'; |
verify_snk_in_enable.eop <= '1'; |
verify_snk_in_enable.empty <= '0'; |
verify_snk_in_enable.channel <= '1'; |
verify_snk_in_enable.err <= '1'; |
|
-- . after the test |
verify_last_snk_in_evt.sync <= last_snk_in_evt; |
verify_last_snk_in_evt.bsn <= last_snk_in_evt; |
verify_last_snk_in_evt.data <= last_snk_in_evt WHEN c_no_unpack=FALSE ELSE '0'; |
verify_last_snk_in_evt.re <= '0'; |
verify_last_snk_in_evt.im <= '0'; |
verify_last_snk_in_evt.valid <= last_snk_in_evt; |
verify_last_snk_in_evt.sop <= last_snk_in_evt; |
verify_last_snk_in_evt.eop <= last_snk_in_evt; |
verify_last_snk_in_evt.empty <= '0'; |
verify_last_snk_in_evt.channel <= last_snk_in_evt; |
verify_last_snk_in_evt.err <= last_snk_in_evt; |
|
u_dp_stream_verify : ENTITY dp_pkg_lib.dp_stream_verify |
GENERIC MAP ( |
g_instance_nr => 0, -- only one stream so choose index 0 |
-- flow control |
g_random_w => 14, -- use different random width for stimuli and for verify to have different random sequences |
g_pulse_active => c_verify_pulse_active, |
g_pulse_period => c_verify_pulse_period, |
g_flow_control => g_flow_control_verify, -- always active, random or pulse flow control |
-- initializations |
g_sync_period => c_sync_period, |
g_sync_offset => c_sync_offset, |
g_snk_in_cnt_max => c_verify_snk_in_cnt_max, |
g_snk_in_cnt_gap => c_verify_snk_in_cnt_gap, |
-- specific |
g_in_dat_w => g_in_dat_w, |
g_pkt_len => c_expected_pkt_len |
) |
PORT MAP ( |
rst => rst, |
clk => clk, |
|
-- Verify data |
snk_out => verify_snk_out, |
snk_in => verify_snk_in, |
|
-- During stimuli |
verify_snk_in_enable => verify_snk_in_enable, -- enable verify to verify that the verify_snk_in fields are incrementing |
|
-- End of stimuli |
expected_snk_in => last_snk_in, -- expected verify_snk_in after end of stimuli |
verify_expected_snk_in_evt => verify_last_snk_in_evt -- trigger verify to verify the last_snk_in |
); |
|
------------------------------------------------------------------------------ |
-- DUT Pack |
------------------------------------------------------------------------------ |
|
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 |
) |
PORT MAP ( |
rst => rst, |
clk => clk, |
|
snk_out => stimuli_src_in, |
snk_in => stimuli_src_out, |
|
src_in => pack_src_in, |
src_out => pack_src_out |
); |
|
pack_src_out_data <= pack_src_out.data(g_pack_dat_w-1 DOWNTO 0); |
|
------------------------------------------------------------------------------ |
-- DUT Unpack |
------------------------------------------------------------------------------ |
|
no_unpack : IF c_no_unpack=TRUE GENERATE |
pack_src_in <= unpack_src_in; |
unpack_src_out <= pack_src_out; |
END GENERATE; |
|
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 |
) |
PORT MAP ( |
rst => rst, |
clk => clk, |
|
snk_out => pack_src_in, |
snk_in => pack_src_out, |
|
src_in => unpack_src_in, |
src_out => unpack_src_out |
); |
END GENERATE; |
|
unpack_src_out_data <= unpack_src_out.data(g_in_dat_w-1 DOWNTO 0); |
|
unpack_src_in <= verify_snk_out; |
verify_snk_in <= unpack_src_out; |
|
------------------------------------------------------------------------------ |
-- Auxiliary |
------------------------------------------------------------------------------ |
|
-- Map to slv to ease monitoring in wave window |
stimuli_src_out_data <= stimuli_src_out.data(g_in_dat_w-1 DOWNTO 0); |
verify_snk_in_data <= verify_snk_in.data(g_in_dat_w-1 DOWNTO 0); |
|
END tb; |
/tb_tb_dp_repack_data.vhd
0,0 → 1,166
------------------------------------------------------------------------------- |
-- |
-- Copyright (C) 2015 |
-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/> |
-- JIVE (Joint Institute for VLBI in Europe) <http://www.jive.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/>. |
-- |
------------------------------------------------------------------------------- |
|
LIBRARY IEEE, common_pkg_lib, dp_pkg_lib; |
USE IEEE.std_logic_1164.ALL; |
USE common_pkg_lib.common_pkg.ALL; |
USE dp_pkg_lib.tb_dp_pkg.ALL; |
|
-- Purpose: Verify multiple variations of tb_dp_repack_data |
-- Description: |
-- Usage: |
-- > as 6 |
-- > run -all |
|
ENTITY tb_tb_dp_repack_data IS |
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; |
|
SIGNAL tb_end : STD_LOGIC := '0'; -- declare tb_end to avoid 'No objects found' error on 'when -label tb_end' |
|
BEGIN |
|
-- -- general |
-- 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_in_dat_w : NATURAL := 5; |
-- g_in_nof_words : NATURAL := 2; |
-- g_pack_dat_w : NATURAL := 16; |
-- g_pack_nof_words : NATURAL := 1; |
-- g_in_bypass : BOOLEAN := FALSE; -- can use TRUE when g_in_nof_words=1 or g_in_nof_words=g_out_nof_words |
-- g_pack_bypass : BOOLEAN := FALSE; -- can use TRUE when g_out_nof_words=1 or g_in_nof_words=g_out_nof_words |
-- g_in_symbol_w : NATURAL := 1; -- default 1 for snk_in.empty in nof bits, else use power of 2 |
-- g_pack_symbol_w : NATURAL := 1; -- default 1 for src_out.empty in nof bits, else use power of 2 |
-- g_nof_repeat : NATURAL := 10; |
-- 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 |
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 |
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; |