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

Prepared dp_bsn_align_v2.vhd (still empty) and mmp_, tb_ and tb_mmp_ files,...

Prepared dp_bsn_align_v2.vhd (still empty) and mmp_, tb_ and tb_mmp_ files, that compile but have no functionality yet.
parent 9b129582
No related branches found
No related tags found
2 merge requests!148L2SDP-495,!146Prepared dp_bsn_align_v2.vhd (still empty) and mmp_, tb_ and tb_mmp_ files,...
......@@ -82,6 +82,12 @@ synth_files =
src/vhdl/dp_block_from_mm.vhd
src/vhdl/dp_block_from_mm_dc.vhd
src/vhdl/dp_block_to_mm.vhd
src/vhdl/dp_bsn_monitor.vhd
src/vhdl/dp_bsn_monitor_reg.vhd
src/vhdl/mms_dp_bsn_monitor.vhd
src/vhdl/dp_bsn_monitor_v2.vhd
src/vhdl/dp_bsn_monitor_reg_v2.vhd
src/vhdl/mms_dp_bsn_monitor_v2.vhd
src/vhdl/dp_bsn_source.vhd
src/vhdl/dp_bsn_source_v2.vhd
src/vhdl/dp_bsn_source_reg.vhd
......@@ -97,6 +103,8 @@ synth_files =
src/vhdl/dp_bsn_align.vhd
src/vhdl/dp_bsn_align_reg.vhd
src/vhdl/mms_dp_bsn_align.vhd
src/vhdl/dp_bsn_align_v2.vhd
src/vhdl/mmp_dp_bsn_align_v2.vhd
src/vhdl/dp_frame_rd.vhd
src/vhdl/dp_frame_fsn.vhd
src/vhdl/dp_frame_tx.vhd
......@@ -114,12 +122,6 @@ synth_files =
src/vhdl/dp_packet_dec_channel_lo.vhd
src/vhdl/dp_gap.vhd
src/vhdl/dp_mon.vhd
src/vhdl/dp_bsn_monitor.vhd
src/vhdl/dp_bsn_monitor_reg.vhd
src/vhdl/mms_dp_bsn_monitor.vhd
src/vhdl/dp_bsn_monitor_v2.vhd
src/vhdl/dp_bsn_monitor_reg_v2.vhd
src/vhdl/mms_dp_bsn_monitor_v2.vhd
src/vhdl/dp_distribute.vhd
src/vhdl/dp_ram_from_mm.vhd
src/vhdl/dp_ram_from_mm_reg.vhd
......@@ -210,6 +212,8 @@ test_bench_files =
tb/vhdl/tb_dp_block_validate_channel.vhd
tb/vhdl/tb_dp_bsn_align.vhd
tb/vhdl/tb_mms_dp_bsn_align.vhd
tb/vhdl/tb_dp_bsn_align_v2.vhd
tb/vhdl/tb_mmp_dp_bsn_align_v2.vhd
tb/vhdl/tb_dp_bsn_monitor.vhd
tb/vhdl/tb_dp_bsn_monitor_v2.vhd
tb/vhdl/tb_dp_bsn_source.vhd
......@@ -294,6 +298,7 @@ test_bench_files =
tb/vhdl/tb_tb_dp_block_from_mm.vhd
tb/vhdl/tb_tb_dp_block_validate_channel.vhd
tb/vhdl/tb_tb_dp_bsn_align.vhd
#src/vhdl/tb_tb_dp_bsn_align_v2.vhd
tb/vhdl/tb_tb_dp_bsn_source_v2.vhd
tb/vhdl/tb_tb_dp_bsn_sync_scheduler.vhd
tb/vhdl/tb_tb_dp_concat.vhd
......@@ -364,6 +369,8 @@ regression_test_vhdl =
tb/vhdl/tb_tb_dp_block_from_mm.vhd
tb/vhdl/tb_tb_dp_block_validate_channel.vhd
tb/vhdl/tb_tb_dp_bsn_align.vhd
#tb/vhdl/tb_tb_dp_bsn_align_v2.vhd
tb/vhdl/tb_mmp_dp_bsn_align_v2.vhd
tb/vhdl/tb_tb_dp_bsn_source_v2.vhd
tb/vhdl/tb_tb_dp_bsn_sync_scheduler.vhd
tb/vhdl/tb_tb_dp_concat.vhd
......
-- --------------------------------------------------------------------------
-- Copyright 2021
-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/>
-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
--
-- Licensed under the Apache License, Version 2.0 (the "License");
-- you may not use this file except in compliance with the License.
-- You may obtain a copy of the License at
--
-- http://www.apache.org/licenses/LICENSE-2.0
--
-- Unless required by applicable law or agreed to in writing, software
-- distributed under the License is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-- See the License for the specific language governing permissions and
-- limitations under the License.
-- --------------------------------------------------------------------------
--
-- Author: Eric Kooistra, 3 Sept 2021
-- Purpose :
-- Align frames from multiple input streams
-- Description:
-- The aligner uses a circular buffer to capture the blocks that arrive at
-- the input streams. The blocks have a block sequence number (BSN) that
-- is used to align the inputs. The input stream 0 is treated as local
-- input stream that is ahead of the other remote input streams. After a
-- certain number of blocks on input 0, the same block on all remote
-- inputs should also have arrived. If not then they are replaced by
-- filler data. The output streams are paced by the block rate of input 0.
--
-- For more detailed description see:
-- https://support.astron.nl/confluence/display/L2M/L6+FWLIB+Design+Document%3A+BSN+aligner+v2
--
-- Remarks:
-- . This dp_bsn_align_v2.vhd replaces the dp_bsn_align.vhd that was used in
-- APERTIF. Mian differences are that the old component uses FIFO buffers,
-- timeouts and states, and v2 does not, which makes v2 simpler and more
-- robust.
LIBRARY IEEE,common_lib;
USE IEEE.std_logic_1164.ALL;
USE IEEE.numeric_std.ALL;
USE common_lib.common_pkg.ALL;
USE common_lib.common_mem_pkg.ALL;
USE work.dp_stream_pkg.ALL;
ENTITY dp_bsn_align_v2 IS
GENERIC (
g_nof_streams : NATURAL; -- number of input and output streams
g_bsn_latency_max : NATURAL; -- Maximum travel latency of a remote block in number of block periods T_blk
g_bsn_latency_use_node_index : BOOLEAN := FALSE; -- FALSE for align at end node, TRUE for align at every intermediate node
g_block_size : NATURAL := 32; -- > 1, g_block_size=1 is not supported
g_buffer_nof_blocks : NATURAL; -- circular buffer size per input, choose ceil_pow2(1 + g_bsn_latency_max)
g_bsn_w : NATURAL := c_dp_stream_bsn_w; -- number of bits in sosi BSN
g_data_w : NATURAL; -- number of bits in sosi data
g_filler_value : INTEGER := 0 -- output sosi data value for missing input blocks
);
PORT (
dp_rst : IN STD_LOGIC;
dp_clk : IN STD_LOGIC;
node_index : IN NATURAL := 0; -- only used when g_bsn_latency_use_node_index is TRUE
-- MM control
in_en_arr : IN STD_LOGIC_VECTOR(g_nof_streams-1 DOWNTO 0);
-- Streaming input
in_sosi_arr : IN t_dp_sosi_arr(g_nof_streams-1 DOWNTO 0);
-- Output via local MM interface in dp_clk domain
mm_copi : IN t_mem_copi; -- read access to output block, all output streams share same mm_copi
mm_cipo_arr : OUT t_mem_copi_arr(g_nof_streams-1 DOWNTO 0);
mm_sosi : OUT t_dp_sosi -- streaming information that signals that an output block can be read
);
END dp_bsn_align_v2;
ARCHITECTURE rtl OF dp_bsn_align_v2 IS
TYPE t_reg IS RECORD
a : STD_LOGIC;
b : NATURAL;
END RECORD;
CONSTANT c_reg_rst : t_reg := ('0', 0);
-- Local registers
SIGNAL r : t_reg;
SIGNAL nxt_r : t_reg;
BEGIN
p_clk: PROCESS(dp_clk, dp_rst)
BEGIN
IF dp_rst='1' THEN
r <= c_reg_rst;
ELSIF rising_edge(dp_clk) THEN
r <= nxt_r;
END IF;
END PROCESS;
END rtl;
-- --------------------------------------------------------------------------
-- Copyright 2021
-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/>
-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
--
-- Licensed under the Apache License, Version 2.0 (the "License");
-- you may not use this file except in compliance with the License.
-- You may obtain a copy of the License at
--
-- http://www.apache.org/licenses/LICENSE-2.0
--
-- Unless required by applicable law or agreed to in writing, software
-- distributed under the License is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-- See the License for the specific language governing permissions and
-- limitations under the License.
-- --------------------------------------------------------------------------
--
-- Author: Eric Kooistra, 6 Sept 2021
-- Purpose: MMP for dp_bsn_align_v2
-- Description:
-- Add MM interfaces to dp_bsn_align_v2:
--
-- * Instantiates input BSN monitors when g_nof_input_bsn_monitors > 0
-- * Instantiates output BSN monitor g_use_bsn_output_monitor = TRUE
-- * Define MM reg for input enable/disable control for input i:
--
-- wi Bits Access Type Name
-- i [0] RW boolean input_enable
--
-- where i = 0:g_nof_streams-1 and input_enable '1' is on, '0' is off
--
-- For more description see dp_bsn_align_v2 and
-- https://support.astron.nl/confluence/display/L2M/L6+FWLIB+Design+Document%3A+BSN+aligner+v2
LIBRARY IEEE, common_lib;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.NUMERIC_STD.ALL;
USE common_lib.common_pkg.ALL;
USE common_lib.common_mem_pkg.ALL;
USE work.dp_stream_pkg.ALL;
ENTITY mmp_dp_bsn_align_v2 IS
GENERIC (
g_nof_streams : NATURAL; -- number of input and output streams
g_bsn_latency_max : NATURAL; -- Maximum travel latency of a remote block in number of block periods T_blk
g_bsn_latency_use_node_index : BOOLEAN := FALSE; -- FALSE for align at end node, TRUE for align at every intermediate node
g_block_size : NATURAL := 32; -- > 1, g_block_size=1 is not supported
g_buffer_nof_blocks : NATURAL; -- circular buffer size per input, choose ceil_pow2(1 + g_bsn_latency_max)
g_bsn_w : NATURAL := c_dp_stream_bsn_w; -- number of bits in sosi BSN
g_data_w : NATURAL; -- number of bits in sosi data
g_filler_value : INTEGER := 0; -- output sosi data value for missing input blocks
g_nof_clk_per_sync : NATURAL := 200*10**6;
g_nof_input_bsn_monitors : NATURAL := 0;
g_use_bsn_output_monitor : BOOLEAN := FALSE
);
PORT (
-- Memory-mapped clock domain
mm_rst : IN STD_LOGIC;
mm_clk : IN STD_LOGIC;
reg_copi : IN t_mem_copi;
reg_cipo : OUT t_mem_cipo;
reg_input_monitor_copi : IN t_mem_copi;
reg_input_monitor_cipo : OUT t_mem_cipo;
reg_output_monitor_copi : IN t_mem_copi;
reg_output_monitor_cipo : OUT t_mem_cipo;
-- Streaming clock domain
dp_rst : IN STD_LOGIC;
dp_clk : IN STD_LOGIC;
node_index : IN NATURAL := 0; -- only used when g_bsn_latency_use_node_index is TRUE
-- Streaming input
in_sosi_arr : IN t_dp_sosi_arr(g_nof_streams-1 DOWNTO 0);
-- Output via local MM in dp_clk domain
mm_copi : IN t_mem_copi; -- read access to output block, all output streams share same mm_copi
mm_cipo_arr : OUT t_mem_copi_arr(g_nof_streams-1 DOWNTO 0);
mm_sosi : OUT t_dp_sosi -- streaming information that signals that an output block can be read
);
END mmp_dp_bsn_align_v2;
ARCHITECTURE str OF mmp_dp_bsn_align_v2 IS
-- Use one MM word (bit 0) per input_enable bit, similar as in dp_bsn_align_reg.vhd.
-- TYPE t_c_mem IS RECORD
-- latency : NATURAL; -- read latency
-- adr_w : NATURAL;
-- dat_w : NATURAL;
-- nof_dat : NATURAL; -- optional, nof dat words <= 2**adr_w
-- init_sl : STD_LOGIC; -- optional, init all dat words to std_logic '0', '1' or 'X'
CONSTANT c_mm_reg : t_c_mem := (1, ceil_log2(g_nof_streams), 1, g_nof_streams, '0');
SIGNAL reg_wr : STD_LOGIC_VECTOR(c_mm_reg.nof_dat*c_mm_reg.dat_w-1 DOWNTO 0);
SIGNAL in_en_arr : STD_LOGIC_VECTOR(g_nof_streams-1 DOWNTO 0);
SIGNAL mm_sosi_arr : t_dp_sosi_arr(0 DOWNTO 0);
BEGIN
u_reg : ENTITY common_lib.common_reg_r_w_dc
GENERIC MAP (
g_cross_clock_domain => TRUE,
g_readback => FALSE,
g_reg => c_mm_reg
)
PORT MAP (
-- Clocks and reset
mm_rst => mm_rst,
mm_clk => mm_clk,
st_rst => dp_rst,
st_clk => dp_clk,
-- Memory Mapped Slave in mm_clk domain
sla_in => reg_copi,
sla_out => reg_cipo,
-- MM registers in st_clk domain
reg_wr_arr => OPEN,
reg_rd_arr => OPEN,
out_reg => reg_wr, -- readback via ST clock domain
in_reg => reg_wr
);
in_en_arr <= reg_wr;
-- Use input BSN monitors for the first g_nof_input_bsn_monitors input
-- streams, e.g. to support:
-- . only one input stream (g_nof_input_bsn_monitors = 1), or
-- . all input streams (g_nof_input_bsn_monitors = g_nof_streams).
gen_bsn_mon_input : IF g_nof_input_bsn_monitors > 0 GENERATE
u_bsn_mon_input : ENTITY work.mms_dp_bsn_monitor_v2
GENERIC MAP (
g_nof_streams => g_nof_input_bsn_monitors,
g_cross_clock_domain => TRUE,
g_sync_timeout => g_nof_clk_per_sync,
g_bsn_w => g_bsn_w,
g_error_bi => 0,
g_cnt_sop_w => c_word_w,
g_cnt_valid_w => c_word_w,
g_cnt_latency_w => c_word_w
)
PORT MAP (
-- Memory-mapped clock domain
mm_rst => mm_rst,
mm_clk => mm_clk,
reg_mosi => reg_input_monitor_copi,
reg_miso => reg_input_monitor_cipo,
-- Streaming clock domain
dp_rst => dp_rst,
dp_clk => dp_clk,
ref_sync => in_sosi_arr(0).sync, -- local reference sync input
in_siso_arr => (OTHERS=>c_dp_siso_rdy),
in_sosi_arr => in_sosi_arr(g_nof_input_bsn_monitors-1 DOWNTO 0)
);
END GENERATE;
gen_bsn_mon_output : IF g_use_bsn_output_monitor GENERATE
u_bsn_mon_output : ENTITY work.mms_dp_bsn_monitor_v2
GENERIC MAP (
g_nof_streams => 1, -- all outputs have same BSN monitor information
g_cross_clock_domain => TRUE,
g_sync_timeout => g_nof_clk_per_sync,
g_bsn_w => g_bsn_w,
g_error_bi => 0,
g_cnt_sop_w => c_word_w,
g_cnt_valid_w => c_word_w,
g_cnt_latency_w => c_word_w
)
PORT MAP (
-- Memory-mapped clock domain
mm_rst => mm_rst,
mm_clk => mm_clk,
reg_mosi => reg_output_monitor_copi,
reg_miso => reg_output_monitor_cipo,
-- Streaming clock domain
dp_rst => dp_rst,
dp_clk => dp_clk,
ref_sync => in_sosi_arr(0).sync, -- local reference sync input
in_siso_arr => (OTHERS=>c_dp_siso_rdy),
in_sosi_arr => mm_sosi_arr
);
END GENERATE;
u_bsn_align : ENTITY work.dp_bsn_align_v2
GENERIC MAP (
g_nof_streams => g_nof_streams,
g_bsn_latency_max => g_bsn_latency_max,
g_bsn_latency_use_node_index => g_bsn_latency_use_node_index,
g_block_size => g_block_size,
g_buffer_nof_blocks => g_buffer_nof_blocks,
g_bsn_w => g_bsn_w,
g_data_w => g_data_w,
g_filler_value => g_filler_value
)
PORT MAP (
dp_rst => dp_rst,
dp_clk => dp_clk,
node_index => node_index,
-- MM control
in_en_arr => in_en_arr,
-- Streaming input
in_sosi_arr => in_sosi_arr,
-- Output via local MM in dp_clk domain
mm_copi => mm_copi,
mm_cipo_arr => mm_cipo_arr,
mm_sosi => mm_sosi
);
mm_sosi <= mm_sosi_arr(0);
END str;
-- --------------------------------------------------------------------------
-- Copyright 2021
-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/>
-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
--
-- Licensed under the Apache License, Version 2.0 (the "License");
-- you may not use this file except in compliance with the License.
-- You may obtain a copy of the License at
--
-- http://www.apache.org/licenses/LICENSE-2.0
--
-- Unless required by applicable law or agreed to in writing, software
-- distributed under the License is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-- See the License for the specific language governing permissions and
-- limitations under the License.
-- --------------------------------------------------------------------------
--
-- Author: Eric Kooistra, 3 Sept 2021
-- Purpose: Verify dp_bsn_align_v2
-- Description:
-- Usage:
-- > as 10
-- > run -all
LIBRARY IEEE, common_lib, dp_lib;
USE IEEE.std_logic_1164.ALL;
USE IEEE.numeric_std.ALL;
USE common_lib.common_pkg.ALL;
USE common_lib.common_mem_pkg.ALL;
USE common_lib.common_lfsr_sequences_pkg.ALL;
USE common_lib.tb_common_pkg.ALL;
USE dp_lib.dp_stream_pkg.ALL;
USE dp_lib.tb_dp_pkg.ALL;
ENTITY tb_dp_bsn_align_v2 IS
GENERIC (
-- DUT
g_nof_streams : NATURAL := 2; -- number of input and output streams
g_bsn_latency_max : NATURAL := 1; -- Maximum travel latency of a remote block in number of block periods T_blk
g_bsn_latency_use_node_index : BOOLEAN := FALSE; -- FALSE for align at end node, TRUE for align at every intermediate node
g_block_size : NATURAL := 17; -- > 1, g_block_size=1 is not supported
g_bsn_w : NATURAL := c_dp_stream_bsn_w; -- number of bits in sosi BSN
g_data_w : NATURAL; -- number of bits in sosi data
g_filler_value : INTEGER := 0; -- output sosi data value for missing input blocks
-- TB
g_diff_delay : NATURAL := 20;
g_diff_bsn : NATURAL := 3; -- g_diff_bsn = g_bsn_latency_max can just be aligned
g_nof_repeat : NATURAL := 100 -- for constant active stream control using 1 is sufficient, use > 1 to verify longer with random stimuli
);
END tb_dp_bsn_align_v2;
ARCHITECTURE tb OF tb_dp_bsn_align_v2 IS
CONSTANT c_rl : NATURAL := 1;
CONSTANT c_pulse_active : NATURAL := 1;
CONSTANT c_pulse_period : NATURAL := 7;
CONSTANT c_data_w : NATURAL := 16;
CONSTANT c_data_init : INTEGER := 0;
CONSTANT c_bsn_w : NATURAL := 16;
CONSTANT c_bsn_init : STD_LOGIC_VECTOR(c_bsn_w-1 DOWNTO 0) := TO_UVEC(3, c_bsn_w);
CONSTANT c_channel_init : INTEGER := 0;
CONSTANT c_err_init : NATURAL := 247;
CONSTANT c_sync_period : NATURAL := 7;
CONSTANT c_sync_offset : NATURAL := 2;
CONSTANT c_gap_size : NATURAL := 10;
CONSTANT c_block_period : NATURAL := g_block_size + c_gap_size;
CONSTANT c_xoff_timeout : NATURAL := c_block_period * g_bsn_latency_max * 2; -- xoff timeout to recover for next alignment attempt
CONSTANT c_sop_timeout : NATURAL := c_block_period * g_bsn_latency_max; -- sop timeout to end current aligment attempt
CONSTANT c_event_input : NATURAL := smallest(1, g_nof_streams-1); -- select special event input at which the event will apply, use >= g_nof_streams to disable the special events
CONSTANT c_buffer_nof_blocks : NATURAL := ceil_pow2(1 + g_bsn_latency_max); -- circular buffer size per input
TYPE t_data_arr IS ARRAY (g_nof_streams-1 DOWNTO 0) OF STD_LOGIC_VECTOR(c_data_w-1 DOWNTO 0);
TYPE t_bsn_arr IS ARRAY (g_nof_streams-1 DOWNTO 0) OF STD_LOGIC_VECTOR(c_bsn_w-1 DOWNTO 0);
TYPE t_err_arr IS ARRAY (g_nof_streams-1 DOWNTO 0) OF STD_LOGIC_VECTOR(c_dp_stream_error_w-1 DOWNTO 0);
TYPE t_channel_arr IS ARRAY (g_nof_streams-1 DOWNTO 0) OF STD_LOGIC_VECTOR(c_dp_stream_channel_w-1 DOWNTO 0);
TYPE t_rl_vec_arr IS ARRAY (g_nof_streams-1 DOWNTO 0) OF STD_LOGIC_VECTOR(0 TO c_rl);
TYPE t_tb_state IS (s_idle, s_bsn_mis_aligned, s_bsn_aligned, s_small_bsn_diff, s_large_bsn_diff, s_restore_bsn, s_disable_one_input, s_enable_inputs);
SIGNAL tb_end : STD_LOGIC := '0';
SIGNAL clk : STD_LOGIC := '1';
SIGNAL rst : STD_LOGIC := '1';
SIGNAL sl1 : STD_LOGIC := '1';
SIGNAL random : STD_LOGIC_VECTOR(15 DOWNTO 0) := (OTHERS=>'0'); -- use different lengths to have different random sequences
SIGNAL pulse : STD_LOGIC;
SIGNAL pulse_en : STD_LOGIC := '1';
SIGNAL node_index : NATURAL := 0;
SIGNAL in_siso_arr : t_dp_siso_arr(g_nof_streams-1 DOWNTO 0) := (OTHERS=>c_dp_siso_rdy);
SIGNAL in_sosi_arr : t_dp_sosi_arr(g_nof_streams-1 DOWNTO 0);
SIGNAL in_bsn : t_bsn_arr;
SIGNAL in_data : t_data_arr;
SIGNAL in_val : STD_LOGIC_VECTOR(g_nof_streams-1 DOWNTO 0);
SIGNAL in_sync : STD_LOGIC_VECTOR(g_nof_streams-1 DOWNTO 0);
SIGNAL in_sop : STD_LOGIC_VECTOR(g_nof_streams-1 DOWNTO 0);
SIGNAL in_eop : STD_LOGIC_VECTOR(g_nof_streams-1 DOWNTO 0);
SIGNAL in_err : t_err_arr;
SIGNAL in_channel : t_channel_arr;
SIGNAL mm_copi : t_mem_copi; -- read access to output block, all output streams share same mm_copi
SIGNAL mm_cipo_arr : t_mem_copi_arr(g_nof_streams-1 DOWNTO 0);
SIGNAL mm_sosi : t_dp_sosi; -- streaming information that signals that an output block can be read
SIGNAL out_siso_arr : t_dp_siso_arr(g_nof_streams-1 DOWNTO 0) := (OTHERS=>c_dp_siso_rdy);
SIGNAL out_sosi_arr : t_dp_sosi_arr(g_nof_streams-1 DOWNTO 0);
SIGNAL out_bsn : t_bsn_arr;
SIGNAL out_data : t_data_arr;
SIGNAL out_val : STD_LOGIC_VECTOR(g_nof_streams-1 DOWNTO 0);
SIGNAL out_sync : STD_LOGIC_VECTOR(g_nof_streams-1 DOWNTO 0);
SIGNAL out_sop : STD_LOGIC_VECTOR(g_nof_streams-1 DOWNTO 0);
SIGNAL out_eop : STD_LOGIC_VECTOR(g_nof_streams-1 DOWNTO 0);
SIGNAL out_gap : STD_LOGIC_VECTOR(g_nof_streams-1 DOWNTO 0) := (OTHERS=>'1');
SIGNAL out_err : t_err_arr;
SIGNAL out_channel : t_channel_arr;
SIGNAL tb_state : t_tb_state;
SIGNAL verify_done_arr : STD_LOGIC_VECTOR(g_nof_streams-1 DOWNTO 0) := (OTHERS=>'0');
SIGNAL default_end_arr : STD_LOGIC_VECTOR(g_nof_streams-1 DOWNTO 0) := (OTHERS=>'0');
SIGNAL default_end : STD_LOGIC;
SIGNAL verify_dis_arr : STD_LOGIC_VECTOR(g_nof_streams-1 DOWNTO 0) := (OTHERS=>'0');
SIGNAL verify_en_arr : STD_LOGIC_VECTOR(g_nof_streams-1 DOWNTO 0) := (OTHERS=>'0');
SIGNAL hold_out_sop : STD_LOGIC_VECTOR(g_nof_streams-1 DOWNTO 0);
SIGNAL prev_out_ready : t_rl_vec_arr;
SIGNAL prev_out_bsn : t_bsn_arr;
SIGNAL expected_out_bsn : t_bsn_arr;
SIGNAL prev_out_data : t_data_arr;
SIGNAL expected_out_data : t_data_arr;
SIGNAL verify_extra_end : STD_LOGIC := '0';
SIGNAL bsn_diff : INTEGER;
SIGNAL bsn_offset : INTEGER;
SIGNAL bsn_event : STD_LOGIC := '0'; -- pulse '1' triggers a BSN offset for an input
SIGNAL bsn_event_ack_arr : STD_LOGIC_VECTOR(g_nof_streams-1 DOWNTO 0) := (OTHERS=>'0');
SIGNAL bsn_event_ack : STD_LOGIC;
SIGNAL in_en_event : STD_LOGIC := '0'; -- pulse '1' indicates that the input enables in in_en_arr have been updated
SIGNAL in_en_arr : STD_LOGIC_VECTOR(g_nof_streams-1 DOWNTO 0) := (OTHERS=>'1'); -- default all inputs are enabled
BEGIN
clk <= (NOT clk) OR tb_end AFTER clk_period/2;
rst <= '1', '0' AFTER clk_period*7;
random <= func_common_random(random) WHEN rising_edge(clk);
proc_common_gen_duty_pulse(c_pulse_active, c_pulse_period+1, '1', rst, clk, pulse_en, pulse);
------------------------------------------------------------------------------
-- DATA GENERATION
------------------------------------------------------------------------------
-- Generate data path input data
gen_input : FOR I IN g_nof_streams-1 DOWNTO 0 GENERATE
p_stimuli : PROCESS
VARIABLE v_sync : STD_LOGIC := '0';
VARIABLE v_bsn : STD_LOGIC_VECTOR(c_bsn_w-1 DOWNTO 0) := c_bsn_init;
VARIABLE v_data : NATURAL := c_data_init;
VARIABLE v_channel : NATURAL := c_channel_init;
VARIABLE v_err : NATURAL := c_err_init;
VARIABLE v_diff_bsn : NATURAL := 0;
BEGIN
-- Create BSN misalignment between the input streams
v_diff_bsn := I MOD (g_diff_bsn+1);
v_data := v_data + I;
v_bsn := INCR_UVEC(v_bsn, v_diff_bsn);
in_sosi_arr(I) <= c_dp_sosi_rst;
proc_common_wait_until_low(clk, rst);
proc_common_wait_some_cycles(clk, c_xoff_timeout*2);
-- Create latency misalignment between the input streams
proc_common_wait_some_cycles(clk, I*g_diff_delay/g_nof_streams);
-- Begin of stimuli
FOR R IN 0 TO g_nof_repeat-v_diff_bsn-1 LOOP
v_sync := sel_a_b(TO_UINT(v_bsn) MOD c_sync_period = c_sync_offset, '1', '0');
proc_dp_gen_block_data(c_rl, TRUE, c_data_w, c_data_w, v_data, 0, 0, g_block_size, v_channel, v_err, v_sync, v_bsn, clk, in_en_arr(I), in_siso_arr(I), in_sosi_arr(I));
v_bsn := INCR_UVEC(v_bsn, 1);
v_data := v_data + g_block_size;
proc_common_wait_some_cycles(clk, c_gap_size); -- create gap between frames
END LOOP;
-- End of default stimuli
expected_out_bsn(I) <= INCR_UVEC(v_bsn, -1);
expected_out_data(I) <= TO_UVEC(v_data-1, c_data_w);
proc_common_wait_some_cycles(clk, 100); -- depends on stream control
default_end_arr(I) <= '1';
verify_done_arr(I) <= '1';
proc_common_wait_some_cycles(clk, 1);
verify_done_arr(I) <= '0';
--------------------------------------------------------------------------
-- Extra
--------------------------------------------------------------------------
proc_common_wait_some_cycles(clk, 500);
WHILE verify_extra_end /= '1' LOOP
v_sync := sel_a_b(TO_UINT(v_bsn) MOD c_sync_period = c_sync_offset, '1', '0');
proc_dp_gen_block_data(c_rl, TRUE, c_data_w, c_data_w, v_data, 0, 0, g_block_size, v_channel, v_err, v_sync, v_bsn, clk, in_en_arr(I), in_siso_arr(I), in_sosi_arr(I));
v_bsn := INCR_UVEC(v_bsn, 1);
bsn_event_ack_arr(I) <= '0';
IF I=c_event_input AND bsn_event='1' THEN
v_bsn := INCR_UVEC(v_bsn, bsn_offset);
bsn_event_ack_arr(I) <= '1';
END IF;
v_data := v_data + g_block_size;
proc_common_wait_some_cycles(clk, c_gap_size); -- create gap between frames
END LOOP;
-- End of extra stimuli
expected_out_bsn(I) <= INCR_UVEC(v_bsn, -1);
expected_out_data(I) <= TO_UVEC(v_data-1, c_data_w);
verify_done_arr(I) <= '1';
proc_common_wait_some_cycles(clk, 1);
verify_done_arr(I) <= '0';
WAIT;
END PROCESS;
END GENERATE;
default_end <= vector_and(default_end_arr);
bsn_event_ack <= vector_or(bsn_event_ack_arr);
p_special_stimuli : PROCESS
BEGIN
verify_dis_arr <= (OTHERS=>'0');
tb_state <= s_bsn_mis_aligned;
in_en_event <= '0';
in_en_arr <= (OTHERS=>'1');
----------------------------------------------------------------------------
-- Wait until default verify test is done
----------------------------------------------------------------------------
proc_common_wait_until_high(clk, default_end);
verify_dis_arr <= (OTHERS=>'1');
proc_common_wait_some_cycles(clk, 100);
verify_dis_arr <= (OTHERS=>'0');
tb_state <= s_bsn_aligned;
proc_common_wait_some_cycles(clk, 1000);
----------------------------------------------------------------------------
-- Verify change in input BSN offset
----------------------------------------------------------------------------
-- . enforce small BSN misalignment
tb_state <= s_small_bsn_diff;
verify_dis_arr <= (OTHERS=>'1');
bsn_offset <= -1;
bsn_event <= '1';
proc_common_wait_until_high(clk, bsn_event_ack);
bsn_event <= '0';
proc_common_wait_some_cycles(clk, 100);
verify_dis_arr <= (OTHERS=>'0');
proc_common_wait_some_cycles(clk, 1000);
verify_dis_arr <= (OTHERS=>'1');
-- . restore original BSN sequence
tb_state <= s_restore_bsn;
bsn_offset <= +1;
bsn_event <= '1';
proc_common_wait_until_high(clk, bsn_event_ack);
bsn_event <= '0';
proc_common_wait_some_cycles(clk, 100);
verify_dis_arr <= (OTHERS=>'0');
proc_common_wait_some_cycles(clk, 1000);
-- verify_dis_arr <= (OTHERS=>'1');
-- . enforce large BSN misalignment
tb_state <= s_large_bsn_diff;
bsn_offset <= -g_bsn_latency_max-1;
bsn_event <= '1';
proc_common_wait_until_high(clk, bsn_event_ack);
bsn_event <= '0';
-- expect no output, because difference remains too large, so do not restart verify_en here and leave it commented:
-- proc_common_wait_some_cycles(clk, 100);
-- verify_dis_arr <= (OTHERS=>'0');
proc_common_wait_some_cycles(clk, 1000);
verify_dis_arr <= (OTHERS=>'1');
-- . restore original BSN sequence
tb_state <= s_restore_bsn;
bsn_offset <= g_bsn_latency_max+1;
bsn_event <= '1';
proc_common_wait_until_high(clk, bsn_event_ack);
bsn_event <= '0';
proc_common_wait_some_cycles(clk, 100);
verify_dis_arr <= (OTHERS=>'0');
proc_common_wait_some_cycles(clk, 1000);
----------------------------------------------------------------------------
-- Verify change in input enables
----------------------------------------------------------------------------
tb_state <= s_disable_one_input;
verify_dis_arr <= (OTHERS=>'1');
in_en_event <= '1';
in_en_arr(c_event_input) <= '0'; -- switch an input off
proc_common_wait_some_cycles(clk, 1);
in_en_event <= '0';
proc_common_wait_some_cycles(clk, 100);
verify_dis_arr <= (OTHERS=>'0');
proc_common_wait_some_cycles(clk, 2000); -- keep this input off for a while
tb_state <= s_enable_inputs;
verify_dis_arr <= (OTHERS=>'1');
in_en_event <= '1';
in_en_arr(c_event_input) <= '1'; -- switch this input on
proc_common_wait_some_cycles(clk, 1);
in_en_event <= '0';
proc_common_wait_some_cycles(clk, 100);
verify_dis_arr <= (OTHERS=>'0');
proc_common_wait_some_cycles(clk, 500);
tb_state <= s_restore_bsn;
verify_dis_arr <= (OTHERS=>'1');
bsn_offset <= bsn_diff; -- use input 0 to restore original BSN sequence for input c_event_input, that got lost due to input disable
bsn_event <= '1';
proc_common_wait_until_high(clk, bsn_event_ack);
bsn_event <= '0';
proc_common_wait_some_cycles(clk, 100);
verify_dis_arr <= (OTHERS=>'0');
proc_common_wait_some_cycles(clk, 2000);
tb_state <= s_idle;
verify_extra_end <= '1';
proc_common_wait_some_cycles(clk, 500);
tb_end <= '1';
WAIT;
END PROCESS;
bsn_diff <= TO_UINT(in_sosi_arr(0).bsn) - TO_UINT(in_sosi_arr(c_event_input).bsn) WHEN rising_edge(clk) AND in_sosi_arr(0).sop='1';
------------------------------------------------------------------------------
-- DATA VERIFICATION
------------------------------------------------------------------------------
gen_verify : FOR I IN g_nof_streams-1 DOWNTO 0 GENERATE
-- Verification logistics
verify_en_arr(I) <= '1' WHEN rising_edge(clk) AND verify_dis_arr(I)='0' AND in_en_arr(I)='1' AND out_sosi_arr(I).sop='1' ELSE
'0' WHEN rising_edge(clk) AND verify_dis_arr(I)='1'; -- verify enable after first output sop
-- Ease in_sosi_arr monitoring
in_data(I) <= in_sosi_arr(I).data(c_data_w-1 DOWNTO 0);
in_val(I) <= in_sosi_arr(I).valid;
in_sop(I) <= in_sosi_arr(I).sop;
in_eop(I) <= in_sosi_arr(I).eop;
in_err(I) <= in_sosi_arr(I).err;
in_channel(I) <= in_sosi_arr(I).channel;
in_sync(I) <= in_sosi_arr(I).sync;
in_bsn(I) <= in_sosi_arr(I).bsn(c_bsn_w-1 DOWNTO 0);
-- Ease out_sosi_arr monitoring and verification
out_data(I) <= out_sosi_arr(I).data(c_data_w-1 DOWNTO 0);
out_val(I) <= out_sosi_arr(I).valid;
out_sop(I) <= out_sosi_arr(I).sop;
out_eop(I) <= out_sosi_arr(I).eop;
out_err(I) <= out_sosi_arr(I).err;
out_channel(I) <= out_sosi_arr(I).channel;
out_sync(I) <= out_sosi_arr(I).sync;
out_bsn(I) <= out_sosi_arr(I).bsn(c_bsn_w-1 DOWNTO 0);
-- Actual verification of the output streams
-- . Verify that the output valid fits with the output ready latency
proc_dp_verify_valid(c_rl, clk, verify_en_arr(I), out_siso_arr(I).ready, prev_out_ready(I), out_val(I));
-- . Verify that sop and eop come in pairs
proc_dp_verify_sop_and_eop(clk, out_val(I), out_sop(I), out_eop(I), hold_out_sop(I));
-- . Verify that the output is incrementing, like the input stimuli
proc_dp_verify_data("out_sosi.data", c_rl, clk, verify_en_arr(I), out_siso_arr(I).ready, out_val(I), out_data(I), prev_out_data(I));
proc_dp_verify_data("out_sosi.bsn", c_rl, clk, verify_en_arr(I), out_siso_arr(I).ready, out_sop(I), out_bsn(I), prev_out_bsn(I));
-- . Verify that the stimuli have been applied at all
proc_dp_verify_value(e_equal, clk, verify_done_arr(I), expected_out_data(I), prev_out_data(I));
proc_dp_verify_value(e_equal, clk, verify_done_arr(I), expected_out_bsn(I), prev_out_bsn(I));
END GENERATE;
------------------------------------------------------------------------------
-- DUT
------------------------------------------------------------------------------
u_bsn_align : ENTITY work.dp_bsn_align_v2
GENERIC MAP (
g_nof_streams => g_nof_streams,
g_bsn_latency_max => g_bsn_latency_max,
g_bsn_latency_use_node_index => g_bsn_latency_use_node_index,
g_block_size => g_block_size,
g_buffer_nof_blocks => c_buffer_nof_blocks,
g_bsn_w => g_bsn_w,
g_data_w => g_data_w,
g_filler_value => g_filler_value
)
PORT MAP (
dp_rst => rst,
dp_clk => clk,
-- Control
node_index => node_index,
in_en_arr => in_en_arr,
-- Streaming input
in_sosi_arr => in_sosi_arr,
-- Output via local MM in dp_clk domain
mm_copi => mm_copi,
mm_cipo_arr => mm_cipo_arr,
mm_sosi => mm_sosi
);
END tb;
-- --------------------------------------------------------------------------
-- Copyright 2021
-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/>
-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
--
-- Licensed under the Apache License, Version 2.0 (the "License");
-- you may not use this file except in compliance with the License.
-- You may obtain a copy of the License at
--
-- http://www.apache.org/licenses/LICENSE-2.0
--
-- Unless required by applicable law or agreed to in writing, software
-- distributed under the License is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-- See the License for the specific language governing permissions and
-- limitations under the License.
-- --------------------------------------------------------------------------
--
-- Author: E. Kooistra, 6 sept 2021
-- Purpose: Verify MM part of mmp_dp_bsn_align_v2
-- Description:
-- The functional part is already verified by tb_tb_dp_bsn_align_v2.vhd.
-- Usage:
-- > as 5
-- > run -all
LIBRARY IEEE, common_lib, technology_lib;
USE IEEE.std_logic_1164.ALL;
USE IEEE.numeric_std.ALL;
USE common_lib.common_pkg.ALL;
USE common_lib.tb_common_pkg.ALL;
USE common_lib.common_mem_pkg.ALL;
USE common_lib.tb_common_mem_pkg.ALL;
USE common_lib.common_str_pkg.ALL;
USE work.dp_stream_pkg.ALL;
USE work.tb_dp_pkg.ALL;
ENTITY tb_mmp_dp_bsn_align_v2 IS
END tb_mmp_dp_bsn_align_v2;
ARCHITECTURE tb OF tb_mmp_dp_bsn_align_v2 IS
CONSTANT c_mm_clk_period : TIME := 40 ns;
CONSTANT c_dp_clk_period : TIME := 10 ns;
CONSTANT c_cross_clock_domain_latency : NATURAL := 20;
CONSTANT c_report_note : BOOLEAN := FALSE; -- Use TRUE for tb debugging, else FALSE to keep Transcript window more empty
CONSTANT c_nof_input_sync : NATURAL := 10;
CONSTANT c_nof_block_per_sync : NATURAL := 32;
CONSTANT c_block_size : NATURAL := 10;
CONSTANT c_input_gap_size : NATURAL := 3;
CONSTANT c_sim_nof_blocks : NATURAL := c_nof_block_per_sync * c_nof_input_sync;
CONSTANT c_nof_streams : NATURAL := 2;
CONSTANT c_bsn_latency_max : NATURAL := 2;
CONSTANT c_bsn_latency_use_node_index : BOOLEAN := FALSE;
CONSTANT c_buffer_nof_blocks : NATURAL := ceil_pow2(1 + c_bsn_latency_max);
CONSTANT c_bsn_w : NATURAL := c_dp_stream_bsn_w;
CONSTANT c_data_w : NATURAL := 16;
CONSTANT c_filler_value : INTEGER := 0;
CONSTANT c_nof_clk_per_sync : NATURAL := 200*10**6;
CONSTANT c_nof_input_bsn_monitors : NATURAL := 0;
CONSTANT c_use_bsn_output_monitor : BOOLEAN := FALSE;
SIGNAL tb_end : STD_LOGIC := '0';
SIGNAL stimuli_end : STD_LOGIC := '0';
-- MM clock domain
SIGNAL mm_clk : STD_LOGIC := '1';
SIGNAL mm_rst : STD_LOGIC := '1';
SIGNAL reg_copi : t_mem_copi := c_mem_copi_rst;
SIGNAL reg_cipo : t_mem_cipo;
SIGNAL reg_input_monitor_copi : t_mem_copi := c_mem_copi_rst;
SIGNAL reg_input_monitor_cipo : t_mem_cipo;
SIGNAL reg_output_monitor_copi : t_mem_copi := c_mem_copi_rst;
SIGNAL reg_output_monitor_cipo : t_mem_cipo;
-- DP clock domain
SIGNAL dp_clk : STD_LOGIC := '1';
SIGNAL dp_rst : STD_LOGIC := '1';
SIGNAL node_index : NATURAL := 0; -- only used when g_bsn_latency_use_node_index is TRUE
SIGNAL stimuli_sosi : t_dp_sosi;
SIGNAL in_sosi_arr : t_dp_sosi_arr(c_nof_streams-1 DOWNTO 0);
SIGNAL mm_copi : t_mem_copi; -- read access to output block, all output streams share same mm_copi
SIGNAL mm_cipo_arr : t_mem_copi_arr(c_nof_streams-1 DOWNTO 0);
SIGNAL mm_sosi : t_dp_sosi; -- streaming information that signals that an output block can be read
BEGIN
dp_clk <= (NOT dp_clk) OR tb_end AFTER c_dp_clk_period/2;
mm_clk <= (NOT mm_clk) OR tb_end AFTER c_mm_clk_period/2;
dp_rst <= '1', '0' AFTER c_dp_clk_period*7;
mm_rst <= '1', '0' AFTER c_mm_clk_period*7;
------------------------------------------------------------------------------
-- MM stimuli and verification
------------------------------------------------------------------------------
p_stimuli_and_verify_mm : PROCESS
VARIABLE v_bsn : NATURAL;
BEGIN
proc_common_wait_until_low(dp_clk, mm_rst);
proc_common_wait_until_low(dp_clk, dp_rst);
proc_common_wait_some_cycles(mm_clk, 5);
---------------------------------------------------------------------------
-- End of test
---------------------------------------------------------------------------
proc_common_wait_until_high(dp_clk, stimuli_end);
tb_end <= '1';
WAIT;
END PROCESS;
------------------------------------------------------------------------------
-- Streaming stimuli
------------------------------------------------------------------------------
-- Generate data blocks with input sync
u_stimuli : ENTITY work.dp_stream_stimuli
GENERIC MAP (
g_sync_period => c_nof_block_per_sync,
g_err_init => 0,
g_err_incr => 0, -- do not increment, to not distract from viewing of BSN in Wave window
g_channel_init => 0,
g_channel_incr => 0, -- do not increment, to not distract from viewing of BSN in Wave window
g_nof_repeat => c_sim_nof_blocks,
g_pkt_len => c_block_size,
g_pkt_gap => c_input_gap_size
)
PORT MAP (
rst => dp_rst,
clk => dp_clk,
-- Generate stimuli
src_out => stimuli_sosi,
-- End of stimuli
tb_end => stimuli_end
);
in_sosi_arr <= (OTHERS => stimuli_sosi);
------------------------------------------------------------------------------
-- DUT
------------------------------------------------------------------------------
u_bsn_align : ENTITY work.mmp_dp_bsn_align_v2
GENERIC MAP (
g_nof_streams => c_nof_streams,
g_bsn_latency_max => c_bsn_latency_max,
g_bsn_latency_use_node_index => c_bsn_latency_use_node_index,
g_block_size => c_block_size,
g_buffer_nof_blocks => c_buffer_nof_blocks,
g_bsn_w => c_bsn_w,
g_data_w => c_data_w,
g_filler_value => c_filler_value,
g_nof_clk_per_sync => c_nof_clk_per_sync,
g_nof_input_bsn_monitors => c_nof_input_bsn_monitors,
g_use_bsn_output_monitor => c_use_bsn_output_monitor
)
PORT MAP (
mm_rst => mm_rst,
mm_clk => mm_clk,
reg_copi => reg_copi,
reg_cipo => reg_cipo,
reg_input_monitor_copi => reg_input_monitor_copi,
reg_input_monitor_cipo => reg_input_monitor_cipo,
reg_output_monitor_copi => reg_output_monitor_copi,
reg_output_monitor_cipo => reg_output_monitor_cipo,
dp_rst => dp_rst,
dp_clk => dp_clk,
node_index => node_index,
-- Streaming input
in_sosi_arr => in_sosi_arr,
-- Output via local MM in dp_clk domain
mm_copi => mm_copi,
mm_cipo_arr => mm_cipo_arr,
mm_sosi => mm_sosi
);
END tb;
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment