Skip to content
Snippets Groups Projects
Commit edd27847 authored by Kenneth Hiemstra's avatar Kenneth Hiemstra
Browse files

Merge branch 'master' of https://git.astron.nl/desp/hdl

parents dc3a38d2 5dcb9712
No related branches found
No related tags found
1 merge request!100Removed text for XSub that is now written in Confluence Subband correlator...
...@@ -108,6 +108,9 @@ synth_files = ...@@ -108,6 +108,9 @@ synth_files =
src/vhdl/dp_bsn_monitor.vhd src/vhdl/dp_bsn_monitor.vhd
src/vhdl/dp_bsn_monitor_reg.vhd src/vhdl/dp_bsn_monitor_reg.vhd
src/vhdl/mms_dp_bsn_monitor.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_distribute.vhd
src/vhdl/dp_ram_from_mm.vhd src/vhdl/dp_ram_from_mm.vhd
src/vhdl/dp_ram_from_mm_reg.vhd src/vhdl/dp_ram_from_mm_reg.vhd
...@@ -193,6 +196,7 @@ test_bench_files = ...@@ -193,6 +196,7 @@ test_bench_files =
tb/vhdl/tb_dp_bsn_align.vhd tb/vhdl/tb_dp_bsn_align.vhd
tb/vhdl/tb_mms_dp_bsn_align.vhd tb/vhdl/tb_mms_dp_bsn_align.vhd
tb/vhdl/tb_dp_bsn_monitor.vhd tb/vhdl/tb_dp_bsn_monitor.vhd
tb/vhdl/tb_dp_bsn_monitor_v2.vhd
tb/vhdl/tb_dp_bsn_source.vhd tb/vhdl/tb_dp_bsn_source.vhd
tb/vhdl/tb_dp_bsn_source_v2.vhd tb/vhdl/tb_dp_bsn_source_v2.vhd
tb/vhdl/tb_mms_dp_bsn_source.vhd tb/vhdl/tb_mms_dp_bsn_source.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:
-- . Reinier vd Walle
-- Purpose: Provide MM slave register for dp_bsn_monitor
-- Description:
--
-- Read only monitor register for streams with sync.
--
-- 31 24 23 16 15 8 7 0 wi
-- |-----------------|-----------------|-----------------|-----------------|
-- | sync timeout = [2], ready_stable = [1], xon_stable = [0] | 0
-- |-----------------------------------------------------------------------|
-- | bsn_at_sync[31: 0] | 1
-- |-----------------------------------------------------------------------|
-- | bsn_at_sync[63:32] | 2
-- |-----------------------------------------------------------------------|
-- | nof_sop[31: 0] | 3
-- |-----------------------------------------------------------------------|
-- | nof_valid[31: 0] | 4
-- |-----------------------------------------------------------------------|
-- | nof_err[31: 0] | 5
-- |-----------------------------------------------------------------------|
-- | latency[31: 0] | 6
-- |-----------------------------------------------------------------------|
-- --------------------------------------------------------------------------
LIBRARY IEEE, common_lib;
USE IEEE.STD_LOGIC_1164.ALL;
USE common_lib.common_pkg.ALL;
USE common_lib.common_mem_pkg.ALL;
ENTITY dp_bsn_monitor_reg_v2 IS
GENERIC (
g_cross_clock_domain : BOOLEAN := TRUE -- use FALSE when mm_clk and st_clk are the same, else use TRUE to cross the clock domain
);
PORT (
-- Clocks and reset
mm_rst : IN STD_LOGIC; -- reset synchronous with mm_clk
mm_clk : IN STD_LOGIC; -- memory-mapped bus clock
st_rst : IN STD_LOGIC; -- reset synchronous with st_clk
st_clk : IN STD_LOGIC; -- other clock domain clock
-- Memory Mapped Slave in mm_clk domain
sla_in : IN t_mem_mosi; -- actual ranges defined by c_mm_reg
sla_out : OUT t_mem_miso; -- actual ranges defined by c_mm_reg
-- MM registers in st_clk domain
mon_evt : IN STD_LOGIC; -- pulses when new monitor data is available regarding the previous sync interval
mon_sync_timeout : IN STD_LOGIC;
-- . siso
mon_ready_stable : IN STD_LOGIC;
mon_xon_stable : IN STD_LOGIC;
-- . sosi
mon_bsn_at_sync : IN STD_LOGIC_VECTOR;
mon_nof_sop : IN STD_LOGIC_VECTOR;
mon_nof_err : IN STD_LOGIC_VECTOR;
mon_nof_valid : IN STD_LOGIC_VECTOR;
mon_latency : IN STD_LOGIC_VECTOR
);
END dp_bsn_monitor_reg_v2;
ARCHITECTURE str OF dp_bsn_monitor_reg_v2 IS
-- Define the actual size of the MM slave register
CONSTANT c_mm_reg : t_c_mem := (latency => 1,
adr_w => 3,
dat_w => c_word_w, -- Use MM bus data width = c_word_w = 32 for all MM registers
nof_dat => 7,
init_sl => '0');
-- Registers in st_clk domain
SIGNAL mon_reg : STD_LOGIC_VECTOR(c_mm_reg.nof_dat*c_mm_reg.dat_w-1 DOWNTO 0) := (OTHERS=>'0');
BEGIN
-- Register mapping
mon_reg( 3-1 DOWNTO 0) <= mon_sync_timeout & mon_ready_stable & mon_xon_stable;
mon_reg(1*c_word_w-1 DOWNTO 3) <= (OTHERS=>'0');
mon_reg(3*c_word_w-1 DOWNTO 1*c_word_w) <= RESIZE_UVEC(mon_bsn_at_sync, c_longword_w);
mon_reg(4*c_word_w-1 DOWNTO 3*c_word_w) <= RESIZE_UVEC(mon_nof_sop, c_word_w);
mon_reg(5*c_word_w-1 DOWNTO 4*c_word_w) <= RESIZE_UVEC(mon_nof_valid, c_word_w);
mon_reg(6*c_word_w-1 DOWNTO 5*c_word_w) <= RESIZE_UVEC(mon_nof_err, c_word_w);
mon_reg(7*c_word_w-1 DOWNTO 6*c_word_w) <= RESIZE_UVEC(mon_latency, c_word_w);
u_reg : ENTITY common_lib.common_reg_r_w_dc
GENERIC MAP (
g_cross_clock_domain => g_cross_clock_domain,
g_in_new_latency => 1, -- mon_evt to mon_reg has latency 1 in dp_bsn_monitor
g_readback => FALSE,
g_reg => c_mm_reg
)
PORT MAP (
-- Clocks and reset
mm_rst => mm_rst,
mm_clk => mm_clk,
st_rst => st_rst,
st_clk => st_clk,
-- Memory Mapped Slave in mm_clk domain
sla_in => sla_in,
sla_out => sla_out,
-- MM registers in st_clk domain
reg_wr_arr => OPEN,
reg_rd_arr => OPEN,
in_new => mon_evt,
in_reg => mon_reg, -- read only
out_reg => OPEN -- no write
);
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:
-- . Reinier vd Walle
-- Purpose: Monitor the sosi and siso control of a stream per sync interval
-- Description:
-- The mon_evt pulses when new monitor output is available regarding the
-- previous in_sosi.sync interval:
-- . mon_sync_timeout = '1' when the in_sosi.sync did not occur
-- . mon_ready_stable = '1' when ready was always '1' during last sync interval
-- . mon_xon_stable = '1' when xon was always '1' during last sync interval
-- . mon_bsn_at_sync = BSN at sync
-- . mon_nof_sop = number of sop during last sync interval
-- . mon_nof_err = number of err at eop during last sync interval
-- . mon_nof_valid = number of valid during last sync interval;
-- . mon_latency = number of clock cycles between ref_sync and in_sosi.sync;
--
-- Remarks:
-- . Assumes RL > 0 so each active valid indicates a new data (with RL = 0 the
-- valid remains active until an acknowledge by ready)
-- . If mon_sync_timeout = '1', all output vectors are forced -1 (all ones) to
-- indicate they are not valid.
-- --------------------------------------------------------------------------
LIBRARY IEEE, common_lib;
USE IEEE.std_logic_1164.all;
USE IEEE.numeric_std.ALL;
USE common_lib.common_pkg.ALL;
USE work.dp_stream_pkg.ALL;
ENTITY dp_bsn_monitor_v2 IS
GENERIC (
g_sync_timeout : NATURAL := 200*10**6; -- choose >= nof clk cycles per sync period
g_error_bi : NATURAL := 0
);
PORT (
rst : IN STD_LOGIC := '0';
clk : IN STD_LOGIC;
-- ST interface
in_siso : IN t_dp_siso;
in_sosi : IN t_dp_sosi;
ref_sync : IN STD_LOGIC := '0'; -- reference sync input
-- MM interface
-- . control
mon_evt : OUT STD_LOGIC; -- pulses when new monitor output is available regarding the previous sync interval
mon_sync : OUT STD_LOGIC; -- pulses every in_sosi.sync interval
mon_sync_timeout : OUT STD_LOGIC;
-- . siso
mon_ready_stable : OUT STD_LOGIC;
mon_xon_stable : OUT STD_LOGIC;
-- . sosi
mon_bsn_at_sync : OUT STD_LOGIC_VECTOR;
mon_nof_sop : OUT STD_LOGIC_VECTOR;
mon_nof_err : OUT STD_LOGIC_VECTOR;
mon_nof_valid : OUT STD_LOGIC_VECTOR;
mon_latency : OUT STD_LOGIC_VECTOR
);
END dp_bsn_monitor_v2;
ARCHITECTURE rtl OF dp_bsn_monitor_v2 IS
CONSTANT c_sync_timeout_w : NATURAL := ceil_log2(g_sync_timeout);
CONSTANT c_bsn_w : NATURAL := mon_bsn_at_sync'LENGTH;
CONSTANT c_cnt_sop_w : NATURAL := mon_nof_sop'LENGTH;
CONSTANT c_cnt_valid_w : NATURAL := mon_nof_valid'LENGTH;
CONSTANT c_cnt_latency_w : NATURAL := mon_latency'LENGTH;
CONSTANT inv_mon_bsn_at_sync : STD_LOGIC_VECTOR(c_bsn_w-1 DOWNTO 0) := (OTHERS => '1');
CONSTANT inv_mon_nof_sop : STD_LOGIC_VECTOR(c_cnt_sop_w-1 DOWNTO 0) := (OTHERS => '1');
CONSTANT inv_mon_nof_err : STD_LOGIC_VECTOR(c_cnt_sop_w-1 DOWNTO 0) := (OTHERS => '1');
CONSTANT inv_mon_nof_valid : STD_LOGIC_VECTOR(c_cnt_valid_w-1 DOWNTO 0) := (OTHERS => '1');
CONSTANT inv_mon_latency : STD_LOGIC_VECTOR(c_cnt_latency_w-1 DOWNTO 0) := (OTHERS => '1');
SIGNAL ready : STD_LOGIC;
SIGNAL nxt_ready : STD_LOGIC;
SIGNAL ready_stable : STD_LOGIC;
SIGNAL xon : STD_LOGIC;
SIGNAL nxt_xon : STD_LOGIC;
SIGNAL xon_stable : STD_LOGIC;
SIGNAL err : STD_LOGIC;
SIGNAL nxt_err : STD_LOGIC;
SIGNAL valid : STD_LOGIC;
SIGNAL nxt_valid : STD_LOGIC;
SIGNAL sop : STD_LOGIC;
SIGNAL nxt_sop : STD_LOGIC;
SIGNAL sync : STD_LOGIC;
SIGNAL nxt_sync : STD_LOGIC;
SIGNAL bsn : STD_LOGIC_VECTOR(c_bsn_w-1 DOWNTO 0);
SIGNAL nxt_bsn : STD_LOGIC_VECTOR(c_bsn_w-1 DOWNTO 0);
SIGNAL cnt_sop : STD_LOGIC_VECTOR(c_cnt_sop_w-1 DOWNTO 0);
SIGNAL nof_sop : STD_LOGIC_VECTOR(c_cnt_sop_w-1 DOWNTO 0);
SIGNAL cnt_err : STD_LOGIC_VECTOR(c_cnt_sop_w-1 DOWNTO 0); -- use c_cnt_sop_w, because at maximium all frames have an error
SIGNAL nof_err : STD_LOGIC_VECTOR(c_cnt_sop_w-1 DOWNTO 0);
SIGNAL cnt_valid : STD_LOGIC_VECTOR(c_cnt_valid_w-1 DOWNTO 0);
SIGNAL nof_valid : STD_LOGIC_VECTOR(c_cnt_valid_w-1 DOWNTO 0);
SIGNAL cnt_latency : STD_LOGIC_VECTOR(c_cnt_latency_w-1 DOWNTO 0);
SIGNAL latency : STD_LOGIC_VECTOR(c_cnt_latency_w-1 DOWNTO 0);
SIGNAL i_mon_ready_stable : STD_LOGIC;
SIGNAL i_mon_xon_stable : STD_LOGIC;
SIGNAL i_mon_bsn_at_sync : STD_LOGIC_VECTOR(c_bsn_w-1 DOWNTO 0);
SIGNAL i_mon_nof_sop : STD_LOGIC_VECTOR(c_cnt_sop_w-1 DOWNTO 0);
SIGNAL i_mon_nof_err : STD_LOGIC_VECTOR(c_cnt_sop_w-1 DOWNTO 0);
SIGNAL i_mon_nof_valid : STD_LOGIC_VECTOR(c_cnt_valid_w-1 DOWNTO 0);
SIGNAL i_mon_latency : STD_LOGIC_VECTOR(c_cnt_latency_w-1 DOWNTO 0);
SIGNAL i_current_bsn : STD_LOGIC_VECTOR(c_bsn_w-1 DOWNTO 0);
SIGNAL sync_timeout_cnt : STD_LOGIC_VECTOR(c_sync_timeout_w-1 DOWNTO 0);
SIGNAL sync_timeout : STD_LOGIC;
SIGNAL sync_timeout_n : STD_LOGIC;
SIGNAL nxt_sync_timeout : STD_LOGIC;
SIGNAL sync_timeout_revt : STD_LOGIC;
SIGNAL nxt_mon_evt : STD_LOGIC;
SIGNAL nxt_mon_ready_stable : STD_LOGIC;
SIGNAL nxt_mon_xon_stable : STD_LOGIC;
SIGNAL nxt_mon_bsn_at_sync : STD_LOGIC_VECTOR(c_bsn_w-1 DOWNTO 0);
SIGNAL nxt_mon_nof_sop : STD_LOGIC_VECTOR(c_cnt_sop_w-1 DOWNTO 0);
SIGNAL nxt_mon_nof_err : STD_LOGIC_VECTOR(c_cnt_sop_w-1 DOWNTO 0);
SIGNAL nxt_mon_nof_valid : STD_LOGIC_VECTOR(c_cnt_valid_w-1 DOWNTO 0);
SIGNAL nxt_mon_latency : STD_LOGIC_VECTOR(c_cnt_latency_w-1 DOWNTO 0);
SIGNAL nxt_current_bsn : STD_LOGIC_VECTOR(c_bsn_w-1 DOWNTO 0);
BEGIN
mon_sync <= sync;
mon_sync_timeout <= sync_timeout;
mon_ready_stable <= i_mon_ready_stable;
mon_xon_stable <= i_mon_xon_stable;
mon_bsn_at_sync <= i_mon_bsn_at_sync WHEN sync_timeout='0' ELSE inv_mon_bsn_at_sync;
mon_nof_sop <= i_mon_nof_sop WHEN sync_timeout='0' ELSE inv_mon_nof_sop;
mon_nof_err <= i_mon_nof_err WHEN sync_timeout='0' ELSE inv_mon_nof_err;
mon_nof_valid <= i_mon_nof_valid WHEN sync_timeout='0' ELSE inv_mon_nof_valid;
mon_latency <= i_mon_latency WHEN sync_timeout='0' ELSE inv_mon_latency;
nxt_mon_evt <= sync OR sync_timeout_revt;
nxt_mon_ready_stable <= ready_stable WHEN sync='1' ELSE i_mon_ready_stable;
nxt_mon_xon_stable <= xon_stable WHEN sync='1' ELSE i_mon_xon_stable;
nxt_mon_bsn_at_sync <= bsn WHEN sync='1' ELSE i_mon_bsn_at_sync;
nxt_mon_nof_sop <= nof_sop WHEN sync='1' ELSE i_mon_nof_sop;
nxt_mon_nof_err <= nof_err WHEN sync='1' ELSE i_mon_nof_err;
nxt_mon_nof_valid <= nof_valid WHEN sync='1' ELSE i_mon_nof_valid;
nxt_mon_latency <= latency WHEN sync='1' ELSE i_mon_latency;
nof_sop <= INCR_UVEC(cnt_sop, 1); -- +1 because the sop at the sync also counts
nof_err <= cnt_err;
nof_valid <= INCR_UVEC(cnt_valid, 1); -- +1 because the valid at the sync also counts
latency <= cnt_latency;
u_sync_timeout_cnt : ENTITY common_lib.common_counter
GENERIC MAP (
g_width => c_sync_timeout_w
)
PORT MAP (
rst => rst,
clk => clk,
cnt_clr => sync,
cnt_en => sync_timeout_n,
count => sync_timeout_cnt
);
sync_timeout_n <= NOT nxt_sync_timeout;
nxt_sync_timeout <= '1' WHEN UNSIGNED(sync_timeout_cnt)>=g_sync_timeout ELSE '0';
u_sync_timeout_revt : ENTITY common_lib.common_evt
GENERIC MAP (
g_evt_type => "RISING",
g_out_invert => FALSE,
g_out_reg => FALSE
)
PORT MAP (
rst => rst,
clk => clk,
in_sig => sync_timeout,
out_evt => sync_timeout_revt
);
p_clk : PROCESS(rst, clk)
BEGIN
IF rst = '1' THEN
-- internal
ready <= '0';
xon <= '0';
valid <= '0';
sop <= '0';
err <= '0';
sync <= '0';
bsn <= (OTHERS=>'0');
-- output
mon_evt <= '0';
sync_timeout <= '0';
i_mon_ready_stable <= '0';
i_mon_xon_stable <= '0';
i_mon_bsn_at_sync <= (OTHERS=>'0');
i_mon_nof_sop <= (OTHERS=>'0');
i_mon_nof_err <= (OTHERS=>'0');
i_mon_nof_valid <= (OTHERS=>'0');
i_mon_latency <= (OTHERS=>'0');
i_current_bsn <= (OTHERS=>'0');
ELSIF rising_edge(clk) THEN
-- internal
ready <= nxt_ready;
xon <= nxt_xon;
valid <= nxt_valid;
sop <= nxt_sop;
err <= nxt_err;
sync <= nxt_sync;
bsn <= nxt_bsn;
-- output
mon_evt <= nxt_mon_evt;
sync_timeout <= nxt_sync_timeout;
i_mon_ready_stable <= nxt_mon_ready_stable;
i_mon_xon_stable <= nxt_mon_xon_stable;
i_mon_bsn_at_sync <= nxt_mon_bsn_at_sync;
i_mon_nof_sop <= nxt_mon_nof_sop;
i_mon_nof_err <= nxt_mon_nof_err;
i_mon_nof_valid <= nxt_mon_nof_valid;
i_mon_latency <= nxt_mon_latency;
i_current_bsn <= nxt_current_bsn;
END IF;
END PROCESS;
-- siso
nxt_ready <= in_siso.ready;
nxt_xon <= in_siso.xon;
u_ready_stable : ENTITY common_lib.common_stable_monitor
PORT MAP (
rst => rst,
clk => clk,
-- MM
r_in => ready,
r_stable => ready_stable,
r_stable_ack => sync
);
u_xon_stable : ENTITY common_lib.common_stable_monitor
PORT MAP (
rst => rst,
clk => clk,
-- MM
r_in => xon,
r_stable => xon_stable,
r_stable_ack => sync
);
-- Sample the BSN, because BSN is only valid during sop.
nxt_current_bsn <= in_sosi.bsn(c_bsn_w-1 DOWNTO 0) WHEN in_sosi.sop='1' ELSE i_current_bsn;
-- sosi
-- . no need to AND sop, eop with valid, because can only be active when valid = '1'
-- . no need to AND sync with sop, because can only be active when sop = '1'
nxt_valid <= in_sosi.valid;
nxt_sop <= in_sosi.sop;
nxt_sync <= in_sosi.sync;
nxt_err <= in_sosi.err(g_error_bi) WHEN in_sosi.eop='1' ELSE '0'; -- assume sosi.err(g_error_bi) = '1' at eop indicates an error
nxt_bsn <= in_sosi.bsn(c_bsn_w-1 DOWNTO 0) WHEN in_sosi.sop='1' ELSE bsn; -- keep bsn as defined at sop
u_cnt_sop : ENTITY common_lib.common_counter
GENERIC MAP (
g_width => c_cnt_sop_w
)
PORT MAP (
rst => rst,
clk => clk,
cnt_clr => sync,
cnt_en => sop,
count => cnt_sop
);
u_nof_err : ENTITY common_lib.common_counter
GENERIC MAP (
g_width => c_cnt_sop_w
)
PORT MAP (
rst => rst,
clk => clk,
cnt_clr => sync,
cnt_en => err,
count => cnt_err
);
u_cnt_valid : ENTITY common_lib.common_counter
GENERIC MAP (
g_width => c_cnt_valid_w
)
PORT MAP (
rst => rst,
clk => clk,
cnt_clr => sync,
cnt_en => valid,
count => cnt_valid
);
u_cnt_latency : ENTITY common_lib.common_counter
GENERIC MAP (
g_width => c_cnt_latency_w
)
PORT MAP (
rst => rst,
clk => clk,
cnt_clr => ref_sync,
cnt_en => '1',
count => cnt_latency
);
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:
-- . Reinier vd Walle
-- Purpose : MMS for dp_bsn_monitor_v2
-- Description: See dp_bsn_monitor_v2.vhd
-- --------------------------------------------------------------------------
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 mms_dp_bsn_monitor_v2 IS
GENERIC (
g_nof_streams : POSITIVE := 1;
g_cross_clock_domain : BOOLEAN := TRUE; -- use FALSE when mm_clk and dp_clk are the same, else use TRUE to cross the clock domain
g_sync_timeout : NATURAL := 200*10**6;
g_bsn_w : NATURAL := c_dp_stream_bsn_w;
g_error_bi : NATURAL := 0;
g_cnt_sop_w : NATURAL := c_word_w;
g_cnt_valid_w : NATURAL := c_word_w;
g_cnt_latency_w : NATURAL := c_word_w
);
PORT (
-- Memory-mapped clock domain
mm_rst : IN STD_LOGIC;
mm_clk : IN STD_LOGIC;
reg_mosi : IN t_mem_mosi;
reg_miso : OUT t_mem_miso;
-- Streaming clock domain
dp_rst : IN STD_LOGIC;
dp_clk : IN STD_LOGIC;
ref_sync : IN STD_LOGIC := '0'; -- ref Sync input
in_siso_arr : IN t_dp_siso_arr(g_nof_streams-1 DOWNTO 0) := (OTHERS=>c_dp_siso_rdy);
in_sosi_arr : IN t_dp_sosi_arr(g_nof_streams-1 DOWNTO 0)
);
END mms_dp_bsn_monitor_v2;
ARCHITECTURE str OF mms_dp_bsn_monitor_v2 IS
CONSTANT c_reg_adr_w : NATURAL := ceil_log2(7);
SIGNAL mon_evt_arr : STD_LOGIC_VECTOR(g_nof_streams-1 DOWNTO 0);
SIGNAL mon_sync_timeout_arr : STD_LOGIC_VECTOR(g_nof_streams-1 DOWNTO 0);
SIGNAL mon_ready_stable_arr : STD_LOGIC_VECTOR(g_nof_streams-1 DOWNTO 0);
SIGNAL mon_xon_stable_arr : STD_LOGIC_VECTOR(g_nof_streams-1 DOWNTO 0);
TYPE t_mon_bsn_arr IS ARRAY(g_nof_streams-1 DOWNTO 0) OF STD_LOGIC_VECTOR(g_bsn_w-1 DOWNTO 0);
TYPE t_mon_sop_arr IS ARRAY(g_nof_streams-1 DOWNTO 0) OF STD_LOGIC_VECTOR(g_cnt_sop_w-1 DOWNTO 0);
TYPE t_mon_val_arr IS ARRAY(g_nof_streams-1 DOWNTO 0) OF STD_LOGIC_VECTOR(g_cnt_valid_w-1 DOWNTO 0);
TYPE t_mon_lat_arr IS ARRAY(g_nof_streams-1 DOWNTO 0) OF STD_LOGIC_VECTOR(g_cnt_latency_w-1 DOWNTO 0);
SIGNAL mon_bsn_at_sync_arr : t_mon_bsn_arr;
SIGNAL mon_nof_sop_arr : t_mon_sop_arr;
SIGNAL mon_nof_err_arr : t_mon_sop_arr; -- use g_cnt_sop_w, because at maximium all frames have an error
SIGNAL mon_nof_valid_arr : t_mon_val_arr;
SIGNAL mon_latency_arr : t_mon_lat_arr;
SIGNAL reg_mosi_arr : t_mem_mosi_arr(g_nof_streams-1 DOWNTO 0);
SIGNAL reg_miso_arr : t_mem_miso_arr(g_nof_streams-1 DOWNTO 0);
BEGIN
u_common_mem_mux : ENTITY common_lib.common_mem_mux
GENERIC MAP (
g_nof_mosi => g_nof_streams,
g_mult_addr_w => c_reg_adr_w
)
PORT MAP (
mosi => reg_mosi,
miso => reg_miso,
mosi_arr => reg_mosi_arr,
miso_arr => reg_miso_arr
);
gen_stream : FOR i IN 0 TO g_nof_streams-1 GENERATE
u_reg : ENTITY work.dp_bsn_monitor_reg_v2
GENERIC MAP (
g_cross_clock_domain => g_cross_clock_domain
)
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_mosi_arr(i),
sla_out => reg_miso_arr(i),
-- MM registers in dp_clk domain
-- . control
mon_evt => mon_evt_arr(i),
mon_sync_timeout => mon_sync_timeout_arr(i),
-- . siso
mon_ready_stable => mon_ready_stable_arr(i),
mon_xon_stable => mon_xon_stable_arr(i),
-- . sosi
mon_bsn_at_sync => mon_bsn_at_sync_arr(i),
mon_nof_sop => mon_nof_sop_arr(i),
mon_nof_err => mon_nof_err_arr(i),
mon_nof_valid => mon_nof_valid_arr(i),
mon_latency => mon_latency_arr(i)
);
u_mon : ENTITY work.dp_bsn_monitor_v2
GENERIC MAP (
g_sync_timeout => g_sync_timeout,
g_error_bi => g_error_bi
)
PORT MAP (
rst => dp_rst,
clk => dp_clk,
-- ST interface
in_siso => in_siso_arr(i),
in_sosi => in_sosi_arr(i),
ref_sync => ref_sync,
-- MM interface
-- . control
mon_evt => mon_evt_arr(i), -- pulses when new monitor data is available regarding the previous sync interval
mon_sync => OPEN,
mon_sync_timeout => mon_sync_timeout_arr(i),
-- . siso
mon_ready_stable => mon_ready_stable_arr(i),
mon_xon_stable => mon_xon_stable_arr(i),
-- . sosi
mon_bsn_at_sync => mon_bsn_at_sync_arr(i),
mon_nof_sop => mon_nof_sop_arr(i),
mon_nof_err => mon_nof_err_arr(i),
mon_nof_valid => mon_nof_valid_arr(i),
mon_latency => mon_latency_arr(i)
);
END GENERATE;
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:
-- . Reinier vd Walle
-- Purpose: Verify dp_bsn_monitor_v2 for different RL
-- Description:
-- Usage:
-- > as 10
-- > run -all -- signal tb_end will stop the simulation by stopping the clk
-- . The verify procedures check the correct input and monitor results
-- --------------------------------------------------------------------------
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_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_monitor_v2 IS
GENERIC (
g_in_en : t_dp_flow_control_enum := e_active; -- always e_active, e_random or e_pulse flow control
g_nof_sync : NATURAL := 11
);
END tb_dp_bsn_monitor_v2;
ARCHITECTURE tb OF tb_dp_bsn_monitor_v2 IS
CONSTANT c_rl : NATURAL := 1;
CONSTANT c_data_w : NATURAL := 16;
CONSTANT c_data_init : INTEGER := 0;
CONSTANT c_frame_len : NATURAL := 20;
CONSTANT c_pulse_active : NATURAL := 1;
CONSTANT c_pulse_period : NATURAL := 7;
CONSTANT c_sync_period : NATURAL := 17;
CONSTANT c_sync_offset : NATURAL := 0;
CONSTANT c_sync_timeout : NATURAL := c_frame_len*c_sync_period;
CONSTANT c_nof_repeat : NATURAL := g_nof_sync * c_sync_period + 1;
CONSTANT c_ref_sync_latency : NATURAL := 7;
-- Error control
CONSTANT c_skip_sync_nr : INTEGER := -1; -- use e.g. 5 >= 0 to introduce a sync timeout at that sync interval 5 (causes missing sinc error by proc_dp_verify_sync), use -1 to disable skipping a sync
CONSTANT c_nof_err : NATURAL := 2; -- <= c_sync_period -- introduce frame errors
SIGNAL tb_end : STD_LOGIC := '0';
SIGNAL clk : STD_LOGIC := '1';
SIGNAL rst : STD_LOGIC := '1';
-- Flow control
SIGNAL random_0 : STD_LOGIC_VECTOR(14 DOWNTO 0) := (OTHERS=>'0'); -- use different lengths to have different random sequences
SIGNAL pulse_0 : STD_LOGIC;
SIGNAL pulse_en : STD_LOGIC := '1';
-- Stimuli
SIGNAL in_en : STD_LOGIC := '1';
SIGNAL in_siso : t_dp_siso := c_dp_siso_rdy;
SIGNAL in_sosi : t_dp_sosi;
SIGNAL ref_sync : STD_LOGIC := '0';
-- Output
SIGNAL out_siso : t_dp_siso;
-- Monitor in_sosi and out_siso
SIGNAL mon_evt : STD_LOGIC; -- pulses when new monitor output is available regarding the previous sync interval
SIGNAL mon_sync : STD_LOGIC; -- pulses every in_sync interval
SIGNAL mon_sync_timeout : STD_LOGIC;
SIGNAL mon_ready_stable : STD_LOGIC;
SIGNAL mon_xon_stable : STD_LOGIC;
SIGNAL mon_bsn_at_sync : STD_LOGIC_VECTOR(c_word_w-1 DOWNTO 0);
SIGNAL mon_nof_sop : STD_LOGIC_VECTOR(c_word_w-1 DOWNTO 0);
SIGNAL mon_nof_err : STD_LOGIC_VECTOR(c_word_w-1 DOWNTO 0);
SIGNAL mon_nof_valid : STD_LOGIC_VECTOR(c_word_w-1 DOWNTO 0);
SIGNAL mon_latency : STD_LOGIC_VECTOR(c_word_w-1 DOWNTO 0);
-- Verification
SIGNAL verify_en : STD_LOGIC := '0';
SIGNAL verify_done : STD_LOGIC := '0';
SIGNAL count_eop : NATURAL := 0;
SIGNAL prev_in_ready : STD_LOGIC_VECTOR(0 TO c_rl);
SIGNAL prev_in_data : STD_LOGIC_VECTOR(c_data_w-1 DOWNTO 0) := TO_SVEC(c_data_init-1, c_data_w);
SIGNAL in_bsn : STD_LOGIC_VECTOR(c_word_w-1 DOWNTO 0);
SIGNAL in_data : STD_LOGIC_VECTOR(c_data_w-1 DOWNTO 0);
SIGNAL in_sync : STD_LOGIC;
SIGNAL in_val : STD_LOGIC;
SIGNAL in_sop : STD_LOGIC;
SIGNAL in_eop : STD_LOGIC;
SIGNAL expected_in_data : STD_LOGIC_VECTOR(c_data_w-1 DOWNTO 0);
SIGNAL expected_bsn_at_sync : STD_LOGIC_VECTOR(c_word_w-1 DOWNTO 0);
SIGNAL expected_nof_sop : STD_LOGIC_VECTOR(c_word_w-1 DOWNTO 0);
SIGNAL expected_nof_err : STD_LOGIC_VECTOR(c_word_w-1 DOWNTO 0);
SIGNAL expected_nof_valid : STD_LOGIC_VECTOR(c_word_w-1 DOWNTO 0);
SIGNAL expected_latency : STD_LOGIC_VECTOR(c_word_w-1 DOWNTO 0);
BEGIN
clk <= (NOT clk) OR tb_end AFTER clk_period/2;
rst <= '1', '0' AFTER clk_period*7;
random_0 <= func_common_random(random_0) WHEN rising_edge(clk);
proc_common_gen_duty_pulse(c_pulse_active, c_pulse_period, '1', rst, clk, pulse_en, pulse_0);
------------------------------------------------------------------------------
-- SOSI DATA GENERATION
------------------------------------------------------------------------------
in_en <= '1' WHEN g_in_en=e_active ELSE
random_0(random_0'HIGH) WHEN g_in_en=e_random ELSE
pulse_0 WHEN g_in_en=e_pulse;
in_siso <= c_dp_siso_rdy;
-- Generate data path input data
p_sosi_stimuli : PROCESS
VARIABLE v_data_init : NATURAL;
VARIABLE v_nof_err : NATURAL;
VARIABLE v_err : NATURAL;
VARIABLE v_sync_cnt : NATURAL;
VARIABLE v_sync : STD_LOGIC;
BEGIN
v_data_init := c_data_init;
v_sync_cnt := 0;
v_nof_err := 0;
in_sosi <= c_dp_sosi_rst;
proc_common_wait_until_low(clk, rst);
proc_common_wait_some_cycles(clk, 5);
-- Begin of stimuli
FOR R IN 0 TO c_nof_repeat-1 LOOP
-- control the sync intervals
-- . introduce sync timeout by skipping a sync
-- . introduce frame errors via sosi.err
v_sync := sel_a_b(R MOD c_sync_period = c_sync_offset, '1', '0');
IF v_sync='1' THEN
v_sync_cnt := v_sync_cnt + 1;
IF v_sync_cnt=c_skip_sync_nr THEN
v_sync := '0';
END IF;
v_nof_err := 0;
ELSE
v_nof_err := v_nof_err + 1;
END IF;
v_err := 0;
IF v_nof_err<c_nof_err THEN
v_err := 1;
END IF;
proc_dp_gen_block_data(c_rl, TRUE, c_data_w, c_data_w, v_data_init, 0, 0, c_frame_len, 0, v_err, v_sync, TO_DP_BSN(R), clk, in_en, in_siso, in_sosi);
--proc_common_wait_some_cycles(clk, 10);
v_data_init := v_data_init + c_frame_len;
END LOOP;
-- End of stimuli
expected_in_data <= TO_UVEC(v_data_init-1, c_data_w);
proc_common_wait_until_high(clk, verify_done);
proc_common_wait_some_cycles(clk, 10);
tb_end <= '1';
WAIT;
END PROCESS;
expected_bsn_at_sync <= TO_UVEC( c_nof_repeat-1, c_word_w);
expected_nof_sop <= TO_UVEC( c_sync_period, c_word_w);
expected_nof_err <= TO_UVEC( c_nof_err, c_word_w);
expected_nof_valid <= TO_UVEC(c_frame_len*c_sync_period, c_word_w);
expected_latency <= TO_UVEC( c_ref_sync_latency, c_word_w);
------------------------------------------------------------------------------
-- SISO FLOW CONTROL GENERATION
------------------------------------------------------------------------------
p_siso_stimuli : PROCESS
BEGIN
out_siso <= c_dp_siso_rdy;
proc_common_wait_until_low(clk, rst);
proc_common_wait_some_cycles(clk, 5);
-- Pulse ready low
proc_common_wait_until_hi_lo(clk, in_sosi.sync);
proc_common_wait_until_hi_lo(clk, in_sosi.sop);
proc_common_wait_until_hi_lo(clk, in_sosi.sop);
proc_common_wait_some_cycles(clk, 3);
out_siso.ready <= '0';
proc_common_wait_some_cycles(clk, 1);
out_siso.ready <= '1';
-- Pulse xon low
proc_common_wait_until_hi_lo(clk, in_sosi.sop);
proc_common_wait_until_hi_lo(clk, in_sosi.sop);
proc_common_wait_some_cycles(clk, 3);
out_siso.xon <= '0';
proc_common_wait_some_cycles(clk, 1);
out_siso.xon <= '1';
-- Keep ready active
-- Keep xon active
proc_common_wait_until_hi_lo(clk, in_sosi.sync);
proc_common_wait_until_hi_lo(clk, in_sosi.sync);
-- Make xon low for whole interval
out_siso.xon <= '0';
proc_common_wait_until_hi_lo(clk, in_sosi.sync);
-- Make xon high during the interval
proc_common_wait_some_cycles(clk, 1);
out_siso.xon <= '1';
WAIT;
END PROCESS;
p_siso_verify : PROCESS
BEGIN
-- The assert conditions must manually be set such to fit the stimuli from p_siso_stimuli
proc_common_wait_until_hi_lo(clk, mon_sync);
ASSERT mon_ready_stable='0' REPORT "Wrong mon_ready_stable at sync 1" SEVERITY ERROR;
ASSERT mon_xon_stable='0' REPORT "Wrong mon_xon_stable at sync 1" SEVERITY ERROR;
proc_common_wait_until_hi_lo(clk, mon_sync);
ASSERT mon_ready_stable='0' REPORT "Wrong mon_ready_stable at sync 2" SEVERITY ERROR;
ASSERT mon_xon_stable='0' REPORT "Wrong mon_xon_stable at sync 2" SEVERITY ERROR;
proc_common_wait_until_hi_lo(clk, mon_sync);
ASSERT mon_ready_stable='1' REPORT "Wrong mon_ready_stable at sync 3" SEVERITY ERROR;
ASSERT mon_xon_stable='1' REPORT "Wrong mon_xon_stable at sync 3" SEVERITY ERROR;
proc_common_wait_until_hi_lo(clk, mon_sync);
ASSERT mon_ready_stable='1' REPORT "Wrong mon_ready_stable at sync 4" SEVERITY ERROR;
ASSERT mon_xon_stable='0' REPORT "Wrong mon_xon_stable at sync 4" SEVERITY ERROR;
proc_common_wait_until_hi_lo(clk, mon_sync);
ASSERT mon_ready_stable='1' REPORT "Wrong mon_ready_stable at sync 5" SEVERITY ERROR;
ASSERT mon_xon_stable='0' REPORT "Wrong mon_xon_stable at sync 5" SEVERITY ERROR;
proc_common_wait_until_hi_lo(clk, mon_sync);
ASSERT mon_ready_stable='1' REPORT "Wrong mon_ready_stable at sync 6" SEVERITY ERROR;
ASSERT mon_xon_stable='1' REPORT "Wrong mon_xon_stable at sync 6" SEVERITY ERROR;
WAIT;
END PROCESS;
p_ref_sync_stimuli : PROCESS
BEGIN
ref_sync <= '0';
proc_common_wait_until_low(clk, rst);
proc_common_wait_until_hi_lo(clk, in_sosi.sync);
proc_common_wait_some_cycles(clk, (c_sync_timeout-2-c_ref_sync_latency));
FOR I IN 0 TO c_nof_repeat-2 LOOP
ref_sync <= '1';
proc_common_wait_some_cycles(clk, 1);
ref_sync <= '0';
proc_common_wait_some_cycles(clk, c_sync_timeout-1);
END LOOP;
WAIT;
END PROCESS;
------------------------------------------------------------------------------
-- DATA VERIFICATION
------------------------------------------------------------------------------
-- Verification logistics
verify_en <= '1' WHEN rising_edge(clk) AND in_sosi.sop='1'; -- enable verify after first input sop
count_eop <= count_eop+1 WHEN rising_edge(clk) AND in_sosi.eop='1'; -- count number of input eop
verify_done <= '1' WHEN rising_edge(clk) AND count_eop = c_nof_repeat; -- signal verify done after c_nof_repeat frames
-- Actual verification of the input streams
proc_dp_verify_data("in_sosi.data", c_rl, clk, verify_en, in_siso.ready, in_sosi.valid, in_data, prev_in_data); -- Verify that the input is incrementing data, like the input stimuli
proc_dp_verify_valid(c_rl, clk, verify_en, in_siso.ready, prev_in_ready, in_sosi.valid); -- Verify that the input valid fits with the input ready latency
proc_dp_verify_value(e_equal, clk, verify_done, expected_in_data, prev_in_data); -- Verify that the stimuli have been applied at all
proc_dp_verify_sync(c_sync_period, c_sync_offset, clk, verify_en, in_sosi.sync, in_sosi.sop, in_sosi.bsn);
-- Monitoring
in_bsn <= in_sosi.bsn(c_word_w-1 DOWNTO 0);
in_data <= in_sosi.data(c_data_w-1 DOWNTO 0);
in_sync <= in_sosi.sync;
in_val <= in_sosi.valid;
in_sop <= in_sosi.sop;
in_eop <= in_sosi.eop;
------------------------------------------------------------------------------
-- MONITOR VERIFICATION
------------------------------------------------------------------------------
proc_dp_verify_value(e_equal, clk, verify_done, expected_bsn_at_sync, mon_bsn_at_sync);
proc_dp_verify_value(e_equal, clk, verify_done, expected_nof_sop, mon_nof_sop);
proc_dp_verify_value(e_equal, clk, verify_done, expected_nof_err, mon_nof_err);
proc_dp_verify_value(e_equal, clk, verify_done, expected_nof_valid, mon_nof_valid);
proc_dp_verify_value(e_equal, clk, verify_done, expected_latency, mon_latency);
------------------------------------------------------------------------------
-- DUT dp_bsn_monitor_v2
------------------------------------------------------------------------------
-- Tap the stream to the monitor
dut : ENTITY work.dp_bsn_monitor_v2
GENERIC MAP (
g_sync_timeout => c_sync_timeout
)
PORT MAP (
rst => rst,
clk => clk,
-- ST interface
in_siso => out_siso,
in_sosi => in_sosi,
ref_sync => ref_sync,
-- MM interface
-- . control
mon_evt => mon_evt,
mon_sync => mon_sync,
mon_sync_timeout => mon_sync_timeout,
-- . siso
mon_ready_stable => mon_ready_stable,
mon_xon_stable => mon_xon_stable,
-- . sosi
mon_bsn_at_sync => mon_bsn_at_sync,
mon_nof_sop => mon_nof_sop,
mon_nof_err => mon_nof_err,
mon_nof_valid => mon_nof_valid,
mon_latency => mon_latency
);
END tb;
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment