Skip to content
Snippets Groups Projects
Commit 0320d618 authored by Eric Kooistra's avatar Eric Kooistra
Browse files

Added dp_example_dut.vhd and used it in renamed tb_dp_example_dut and tb_tb_example_dut.vhd.

parent 9c2f72fa
No related branches found
No related tags found
No related merge requests found
......@@ -10,6 +10,7 @@ build_dir_synth = $HDL_BUILD_DIR
synth_files =
src/vhdl/dp_stream_pkg.vhd
src/vhdl/dp_example_dut.vhd
$UNB/Firmware/modules/dp/src/vhdl/dp_packetizing_pkg.vhd
$UNB/Firmware/modules/dp/src/vhdl/dp_packet_pkg.vhd
......@@ -142,7 +143,7 @@ test_bench_files =
$UNB/Firmware/modules/dp/tb/vhdl/tb_dp_concat.vhd
tb/vhdl/tb_dp_deinterleave.vhd
$UNB/Firmware/modules/dp/tb/vhdl/tb_dp_distribute.vhd
tb/vhdl/tb_dp_example_no_dut.vhd
tb/vhdl/tb_dp_example_dut.vhd
$UNB/Firmware/modules/dp/tb/vhdl/tb_dp_fifo_fill.vhd
tb/vhdl/tb_dp_fifo_fill_sc.vhd
$UNB/Firmware/modules/dp/tb/vhdl/tb_dp_fifo_info.vhd
......@@ -184,7 +185,7 @@ test_bench_files =
$UNB/Firmware/modules/dp/tb/vhdl/tb_tb2_dp_demux.vhd
$UNB/Firmware/modules/dp/tb/vhdl/tb_tb3_dp_demux.vhd
$UNB/Firmware/modules/dp/tb/vhdl/tb_tb_dp_distribute.vhd
tb/vhdl/tb_tb_dp_example_no_dut.vhd
tb/vhdl/tb_tb_dp_example_dut.vhd
$UNB/Firmware/modules/dp/tb/vhdl/tb_tb_dp_flush.vhd
$UNB/Firmware/modules/dp/tb/vhdl/tb_tb_dp_fifo_info.vhd
tb/vhdl/tb_tb_dp_fifo_sc.vhd
......
--------------------------------------------------------------------------------
--
-- 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_example_dut serves as a template for a streaming component with
-- flow control.
--
--
-- Block diagram:
--
-- A) Streaming interface
-- ____________________
-- | dp_example_dut |
-- | |
-- <---|snk_out src_in |<---
-- --->|snk_in src_out |--->
-- |____________________|
-- 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:
-- . p_comb = functionality:
-- The functionality of the DP component is defined in the p_comb process.
-- The rest of the block diagram is needed to fit support input valid and
-- output ready flow control and to pipeline the processing such that
-- the function can be implementend within 1 clock cycle.
--
-- . p_reg = local storage and pipelining:
-- The storage is done in a register r and this r contains local storage
-- and the src_out. The r.src_out can directly be wired to src_out. The
-- latency from snk_in to src_out must be 1 clock cycle. If more pipelining
-- is needed then the functionality should be split over separate components
-- that can each again have a latency of 1.
--
-- . p_flow = local flow control:
-- If the functionality does not add or remove valid data from the snk_in
-- input stream, then the src_in can be passed on directly to snk_out.
-- However if the functionality needs to apply backpressure itself or if it
-- can accept input data when the src_in is not ready then it can implement
-- p_flow to apply backpressure via r_snk_out.
--
-- . nxt_r:
-- Note that the function yields nxt_r that gets pipeline stored in r. The
-- nxt_r is combinatorially related to snk_in so it does not change the RL.
-- The p_flow also works combinatorially because it uses nxt_r and via
-- p_comb also src_in. Hence in total the flow control logic does not change
-- the RL because snk_out relaies combinatorially on snk_in.valid, nxt_r
-- and src_in.ready.
--
-- . nxt_r.hold_out.valid = combine local and remote flow control:
-- When the functionality in p_comb is about to yield new valid output then
-- nxt_r.hold_out.valid='1' and then the remote src-in is passed on to
-- snk_out. If p_comb is not yet about to yield new valid output then
-- nxt_r.hold_out.valid='0' and then the local r_snk_out is passed on to
-- snk_out.
--
-- . src_out sosi control fields
-- The src_out sosi control fields (sync, sop, eop, valid) can only become
-- active when the src_in.ready='1'. If the function has new valid output
-- and src_in.ready is '0' then the function has to hold the src_out sosi
-- control in r.hold_out.
--
-- . src_out sosi data fields
-- The src_out sosi data fields (, data, re, im, bsn, channel, empty, err)
-- can immediately be registered into r.src_out, because they are only
-- accepted when the corresponding sosi control field (valid, sop, eop) has
-- become active. Therefore the sosi dat fields are not kept in r.hold_out.
-- Typically a function that does not use all sosi fields should still pass
-- them on if that is not inappropriate.
--
-- Design steps:
-- . First determine how to implement the function it self and setup the basic
-- structure in VHDL, eg dtermine what fields in r will be needed.
-- . The initial structure for the function should already be more or less
-- correct such that the default behaviour or simplest behaviour of the
-- function can already be verified with the test bench. Hence the testbench
-- and the component are developed simultaneously.
-- . Next the more detailed functionality, special cases or extra features of
-- the function can be tested one at a time, again starting with the easiest
-- items, until the whole functinality has been covered. 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.
-- . The development steps can becovered in a single testbench or they may also
-- be covered by representing them as tb instances in a multi tb testbench.
-- During the development the multi tb ensures that bug fixes do not
-- compromise functionality that did already verify ok. When the component
-- is finished, then the multi tb forms the regression test for the component
-- and should be added to the regression tb of the library.
-- . Typically the external flow control by src_in and snk_in is verified as
-- after the component has verified ok for e_active. Often it is sufficient
-- to only verify e_random for both snk_in and src_in, but sometimes it can
-- also be useful to try e_pulse and combinations of eg e_active for snk_in
-- and e_random for snk_out.
--
-- Remarks:
-- . dp_repack_dev provides two usage examples of this dp_example_dut and of
-- the dp_stream_stimuli and dp_stream_verify components that are used in
-- the test bench.
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_example_dut IS
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_example_dut;
ARCHITECTURE rtl OF dp_example_dut IS
TYPE t_reg IS RECORD
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
END RECORD;
SIGNAL r_snk_out : t_dp_siso := c_dp_siso_rdy;
SIGNAL r : t_reg;
SIGNAL nxt_r : t_reg;
BEGIN
p_comb : PROCESS(rst, r, snk_in, 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.src_out.empty := snk_in.empty;
v.src_out.err := snk_in.err;
END IF;
IF snk_in.valid='1' THEN
-- < main section of component function >
v.src_out.data := snk_in.data; -- pipeline function as example
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;
ELSE
v.hold_out.valid := '1';
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;
END IF;
nxt_r <= v;
END PROCESS;
--------------------------------------------------------------------------
-- p_reg
r <= nxt_r WHEN rising_edge(clk);
--------------------------------------------------------------------------
-- Wired output
src_out <= r.src_out;
--------------------------------------------------------------------------
-- Flow control
-- local function flow control
p_flow : PROCESS(nxt_r)
BEGIN
r_snk_out <= c_dp_siso_rdy;
-- < force r_snk_out.ready='0' based on nxt_r if function needs to apply backpressure >
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 rtl;
......@@ -95,9 +95,9 @@
-- verification does not start too soon.
--
-- . Multi testbench
-- This tb_dp_example_no_dut can be instantiated multiple times is a multi
-- tb_tb_dp_example_no_dut test bench to verify the DUT for different
-- parameter configurations. When the tb_tb_dp_example_no_dut runs ok then it
-- This tb_dp_example_dut can be instantiated multiple times is a multi
-- tb_tb_dp_example_dut test bench to verify the DUT for different
-- parameter configurations. When the tb_tb_dp_example_dut runs ok then it
-- can be added to the overall DP library regression testbench in
-- tb_tb_tb_dp_backpressure.vhd.
--
......@@ -120,27 +120,26 @@ USE work.dp_stream_pkg.ALL;
USE work.tb_dp_pkg.ALL;
ENTITY tb_dp_example_no_dut IS
ENTITY tb_dp_example_dut IS
GENERIC (
-- general
g_flow_control_stimuli : t_dp_flow_control_enum := e_active; -- always active, random or pulse flow control
g_flow_control_verify : t_dp_flow_control_enum := e_active; -- always active, random or pulse flow control
g_flow_control_verify : t_dp_flow_control_enum := e_random; -- always active, random or pulse flow control
-- specific
g_in_dat_w : NATURAL := 64;
g_no_dut : BOOLEAN:= FALSE;
g_dat_w : NATURAL := 16;
g_nof_repeat : NATURAL := 5;
g_pkt_len : NATURAL := 5;
g_pkt_gap : NATURAL := 4
);
END tb_dp_example_no_dut;
END tb_dp_example_dut;
ARCHITECTURE tb OF tb_dp_example_no_dut IS
CONSTANT c_no_dut : BOOLEAN:= TRUE;
ARCHITECTURE tb OF tb_dp_example_dut IS
-- dp_stream_stimuli
CONSTANT c_stimuli_pulse_active : NATURAL := 1;
CONSTANT c_stimuli_pulse_period : NATURAL := 2;
CONSTANT c_stimuli_pulse_active : NATURAL := 3;
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"
......@@ -149,10 +148,10 @@ ARCHITECTURE tb OF tb_dp_example_no_dut IS
-- dp_stream_verify
CONSTANT c_verify_pulse_active : NATURAL := 1;
CONSTANT c_verify_pulse_period : NATURAL := 2;
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_data_max : UNSIGNED(g_dat_w-1 DOWNTO 0) := (OTHERS=>'1');
CONSTANT c_dsp_max : UNSIGNED(g_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);
......@@ -168,7 +167,7 @@ ARCHITECTURE tb OF tb_dp_example_no_dut IS
SIGNAL stimuli_src_in : t_dp_siso;
SIGNAL stimuli_src_out : t_dp_sosi;
SIGNAL stimuli_src_out_data : STD_LOGIC_VECTOR(g_in_dat_w-1 DOWNTO 0);
SIGNAL stimuli_src_out_data : STD_LOGIC_VECTOR(g_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;
......@@ -183,7 +182,7 @@ ARCHITECTURE tb OF tb_dp_example_no_dut IS
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);
SIGNAL verify_snk_in_data : STD_LOGIC_VECTOR(g_dat_w-1 DOWNTO 0);
BEGIN
......@@ -210,7 +209,7 @@ BEGIN
g_err_init => c_err_init,
g_channel_init => c_channel_init,
-- specific
g_in_dat_w => g_in_dat_w,
g_in_dat_w => g_dat_w,
g_nof_repeat => g_nof_repeat,
g_pkt_len => g_pkt_len,
g_pkt_gap => g_pkt_gap
......@@ -236,7 +235,7 @@ BEGIN
-- Select fields that need to be verified
-- . during the test
verify_snk_in_enable.sync <= '1';
verify_snk_in_enable.sync <= '1'; -- or '0'
verify_snk_in_enable.bsn <= '1';
verify_snk_in_enable.data <= '1';
verify_snk_in_enable.re <= '0';
......@@ -249,8 +248,8 @@ BEGIN
verify_snk_in_enable.err <= '1';
-- . after the test
verify_last_snk_in_evt.sync <= '0';
verify_last_snk_in_evt.bsn <= '0';
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;
verify_last_snk_in_evt.re <= '0';
verify_last_snk_in_evt.im <= '0';
......@@ -275,7 +274,7 @@ BEGIN
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_in_dat_w => g_dat_w,
g_pkt_len => g_pkt_len
)
PORT MAP (
......@@ -302,14 +301,24 @@ BEGIN
stimuli_src_in <= dut_snk_out;
dut_snk_in <= stimuli_src_out;
no_dut : IF c_no_dut=TRUE GENERATE
no_dut : IF g_no_dut=TRUE GENERATE
dut_snk_out <= dut_src_in;
dut_src_out <= dut_snk_in;
END GENERATE;
-- DUT function
gen_dut : IF c_no_dut=FALSE GENERATE
gen_dut : IF g_no_dut=FALSE GENERATE
u_dut : ENTITY work.dp_example_dut
PORT MAP (
rst => rst,
clk => clk,
snk_out => dut_snk_out,
snk_in => dut_snk_in,
src_in => dut_src_in,
src_out => dut_src_out
);
END GENERATE;
-- Connect DUT source output stream to verification
......@@ -322,7 +331,7 @@ BEGIN
------------------------------------------------------------------------------
-- 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);
stimuli_src_out_data <= stimuli_src_out.data(g_dat_w-1 DOWNTO 0);
verify_snk_in_data <= verify_snk_in.data(g_dat_w-1 DOWNTO 0);
END tb;
......@@ -20,38 +20,46 @@
--
-------------------------------------------------------------------------------
LIBRARY IEEE, dp_lib;
LIBRARY IEEE, common_lib;
USE IEEE.std_logic_1164.ALL;
USE dp_lib.tb_dp_pkg.ALL;
USE common_lib.common_pkg.ALL;
USE work.tb_dp_pkg.ALL;
-- Purpose: Verify multiple variations of tb_dp_example_no_dut
-- Purpose: Verify multiple variations of tb_dp_example_dut
-- Description:
-- Usage:
-- > as 3
-- > as 6
-- > run -all
ENTITY tb_tb_dp_example_no_dut IS
END tb_tb_dp_example_no_dut;
ENTITY tb_tb_dp_example_dut IS
END tb_tb_dp_example_dut;
ARCHITECTURE tb OF tb_tb_dp_example_no_dut IS
ARCHITECTURE tb OF tb_tb_dp_example_dut IS
CONSTANT c_nof_repeat : NATURAL := 10;
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;
BEGIN
-- -- general
-- g_flow_control_stimuli : t_dp_flow_control_enum := e_pulse; -- always active, random or pulse flow control
-- g_flow_control_verify : t_dp_flow_control_enum := e_active; -- always active, random or pulse flow control
-- -- specific
-- g_no_dut : BOOLEAN:= TRUE;
-- g_in_dat_w : NATURAL := 32;
-- g_nof_repeat : NATURAL := 5;
-- g_pkt_len : NATURAL := 16;
-- g_pkt_gap : NATURAL := 4
u_act_act : ENTITY work.tb_dp_example_no_dut GENERIC MAP ( e_active, e_active, 32, c_nof_repeat, 139, 4);
u_rnd_act : ENTITY work.tb_dp_example_no_dut GENERIC MAP ( e_random, e_active, 24, c_nof_repeat, 139, 5);
u_rnd_rnd : ENTITY work.tb_dp_example_no_dut GENERIC MAP ( e_random, e_random, 16, c_nof_repeat, 139, 6);
u_pls_pls : ENTITY work.tb_dp_example_no_dut GENERIC MAP ( e_pulse, e_pulse, 8, c_nof_repeat, 139, 7);
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
gen_bool_dut : FOR K IN 0 TO 1 GENERATE -- 0 = TRUE, 1= FALSE
u_dut : ENTITY work.tb_dp_example_dut GENERIC MAP (c_flow(I), c_flow(J), c_bool(K), 16, c_nof_repeat, 17, 4);
END GENERATE;
END GENERATE;
END GENERATE;
END tb;
......@@ -53,7 +53,7 @@ BEGIN
u_tb_tb_dp_concat : ENTITY work.tb_tb_dp_concat;
u_tb_tb_dp_demux : ENTITY work.tb_tb_dp_demux;
u_tb_tb_dp_distribute : ENTITY work.tb_tb_dp_distribute;
u_tb_tb_dp_example_no_dut : ENTITY work.tb_tb_dp_example_no_dut;
u_tb_tb_dp_example_dut : ENTITY work.tb_tb_dp_example_dut;
u_tb_tb_dp_fifo_dc : ENTITY work.tb_tb_dp_fifo_dc;
u_tb_tb_dp_fifo_dc_mixed_widths : ENTITY work.tb_tb_dp_fifo_dc_mixed_widths;
u_tb_tb_dp_fifo_fill : ENTITY work.tb_tb_dp_fifo_fill;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment