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

Added g_use_steps to support COUNTER sequence data with...

Added g_use_steps to support COUNTER sequence data with c_diag_seq_rx_reg_nof_steps=4 allowed increment step sizes. Did not verify it yet. Default g_use_steps=FALSE still simulates OK.
parent 6467816b
No related branches found
No related tags found
No related merge requests found
......@@ -164,7 +164,9 @@ PACKAGE diag_pkg IS
CONSTANT c_diag_seq_tx_reg_nof_dat : NATURAL := 3;
CONSTANT c_diag_seq_tx_reg_adr_w : NATURAL := ceil_log2(c_diag_seq_tx_reg_nof_dat);
CONSTANT c_diag_seq_rx_reg_nof_dat : NATURAL := 4;
CONSTANT c_diag_seq_rx_reg_nof_steps_wi : NATURAL := 4;
CONSTANT c_diag_seq_rx_reg_nof_steps : NATURAL := 4;
CONSTANT c_diag_seq_rx_reg_nof_dat : NATURAL := c_diag_seq_rx_reg_nof_steps_wi + c_diag_seq_rx_reg_nof_steps;
CONSTANT c_diag_seq_rx_reg_adr_w : NATURAL := ceil_log2(c_diag_seq_rx_reg_nof_dat);
-- Record with all diag seq MM register fields
......
......@@ -20,15 +20,11 @@
--
--------------------------------------------------------------------------------
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_lfsr_sequences_pkg.ALL;
-- Purpose: Verify received continuous PRSG or COUNTER test sequence data.
-- Purpose: Verify received continuous test sequence data.
-- Description:
-- The diag_rx_seq can operate in one of two modes that depend on g_use_steps:
--
-- . g_use_steps = FALSE
-- The test data can be PRSG or COUNTER dependent on diag_sel.
-- The Rx is enabled by diag_en. Typically the Tx should already be running,
-- but it is also allowed to first enable the Rx.
......@@ -50,10 +46,49 @@ USE common_lib.common_lfsr_sequences_pkg.ALL;
-- The diag_sample keeps the last valid in_dat value. When diag_en='0' it is
-- reset to 0. Reading diag_sample via MM gives an impression of the valid
-- in_dat activity.
--
-- . g_use_steps = TRUE
-- The test data is fixed to COUNTER and diag_sel is ignored. The rx_seq can
-- verify counter data that increments in steps that are specified via
-- diag_steps_arr[3:0]. Up to g_nof_steps <= c_diag_seq_rx_reg_nof_steps = 4
-- step sizes are supported. If all steps are set to 1 then there is no
-- difference compared using the COUNTER in g_use_steps = FALSE. Constant
-- value data can be verified by setting alls step to 0. Usinf different
-- steps is useful when the data is generated in linear incrementing order,
-- but received in a different order. Eg. like after a transpose operation
-- where blocks of data are written in row and and read in colums:
--
-- tx: 0 1 2 3 4 5 6 7 8 9 10 11
-- transpose: 0 1 4 5 8 9 2 3 6 7 10 11
-- rx steps: +1 +1 +1 +1 +1 +1
-- -11 +3 +3 -7 +3 +3
--
-- The step size value range is set by the 32 bit range of the VHDL integer.
-- Therefore typically g_dat_w should be <= 32 b. For a transpose that
-- contains more than 2**32 data words this means that the COUNTER data
-- wraps within the transpose. This is acceptable, because it use g_dat_w
-- <= 32 then still provides sufficient coverage to detect all errors.
--
-- Data errors that match a step size cannot be detected. However if such
-- an error occurs then typically the next increment will cause a mismatch.
--
-- The feature of being able to detect errors per bit as with g_use_steps=
-- FALSE is not supported when g_use_steps=TRUE. Therefore the
-- diag_res[g_dat_w-1:0] = -1 (ll '1') when a difference occurs that is no
-- in diag_steps_arr.
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_lfsr_sequences_pkg.ALL;
USE work.diag_pkg.ALL;
ENTITY diag_rx_seq IS
GENERIC (
g_input_reg : BOOLEAN := FALSE; -- Use unregistered input to save logic, use registered input to ease achieving timing constrains.
g_use_steps : BOOLEAN := FALSE;
g_nof_steps : NATURAL := c_diag_seq_rx_reg_nof_steps;
g_sel : STD_LOGIC := '1'; -- '0' = PRSG, '1' = COUNTER
g_cnt_w : NATURAL := c_word_w;
g_dat_w : NATURAL := 12;
......@@ -67,6 +102,7 @@ ENTITY diag_rx_seq IS
-- Static control input (connect via MM or leave open to use default)
diag_en : IN STD_LOGIC; -- '0' = init and disable, '1' = enable
diag_sel : IN STD_LOGIC := g_sel;
diag_steps_arr : t_integer_arr(g_nof_steps-1 DOWNTO 0) := (OTHERS=>1);
diag_res : OUT STD_LOGIC_VECTOR(g_diag_res_w-1 DOWNTO 0); -- diag_res valid indication bits & aggregate diff of in_dat during diag_en
diag_res_val : OUT STD_LOGIC;
diag_sample : OUT STD_LOGIC_VECTOR(g_dat_w-1 DOWNTO 0); -- monitor last valid in_dat
......@@ -126,6 +162,16 @@ ARCHITECTURE rtl OF diag_rx_seq IS
SIGNAL i_diag_sample : STD_LOGIC_VECTOR(g_dat_w-1 DOWNTO 0);
SIGNAL nxt_diag_sample : STD_LOGIC_VECTOR(g_dat_w-1 DOWNTO 0);
TYPE t_dat_arr IS ARRAY (INTEGER RANGE <>) OF STD_LOGIC_VECTOR(g_dat_w-1 DOWNTO 0);
SIGNAL ref_dat_arr : t_dat_arr(g_nof_steps-1 DOWNTO 0);
SIGNAL nxt_ref_dat_arr : t_dat_arr(g_nof_steps-1 DOWNTO 0);
SIGNAL diff_arr : STD_LOGIC_VECTOR(g_nof_steps-1 DOWNTO 0);
SIGNAL nxt_diff_arr : STD_LOGIC_VECTOR(g_nof_steps-1 DOWNTO 0);
SIGNAL diff_detect : STD_LOGIC;
SIGNAL nxt_diff_detect : STD_LOGIC;
SIGNAL diff_hold : STD_LOGIC;
BEGIN
diag_dis <= NOT diag_en;
......@@ -175,13 +221,18 @@ BEGIN
in_val_dly2 <= in_val_dly1;
-- Internal.
in_val_2_dly <= in_val_2 & in_val_2_dly(0 TO c_diag_res_latency-2);
diag_res_int <= nxt_diag_res;
diag_res_en <= nxt_diag_res_en;
diag_res_val <= nxt_diag_res_val;
-- . g_use_steps=FALSE
prsg <= nxt_prsg;
cntr <= nxt_cntr;
ref_dat <= nxt_ref_dat;
diff_dat <= nxt_diff_dat;
diag_res_int <= nxt_diag_res;
diag_res_en <= nxt_diag_res_en;
diag_res_val <= nxt_diag_res_val;
-- . g_use_steps=TRUE
ref_dat_arr <= nxt_ref_dat_arr;
diff_arr <= nxt_diff_arr;
diff_detect <= nxt_diff_detect;
-- Outputs.
i_diag_sample <= nxt_diag_sample;
END IF;
......@@ -220,13 +271,14 @@ BEGIN
-- Use in_val_2_act instead of in_val_2 to have stable start in case diag_dis takes just a pulse and in_val is continue high
in_val_2_act <= vector_and(in_val_2 & in_val_2_dly);
------------------------------------------------------------------------------
-- Compare the in_dat bus with the reference dat
------------------------------------------------------------------------------
-- Use the first valid in_dat after diag_en='1' to initialize the reference data sequence
ref_en <= in_val_1;
-- Use the detection of second valid in_dat after diag_en='1' to start detection of differences
diff_dis <= NOT in_val_2_act;
no_steps : IF g_use_steps=FALSE GENERATE
-- Determine next reference dat based on current input dat
common_lfsr_nxt_seq(c_lfsr_nr, -- IN
ref_en, -- IN
in_val_reg, -- IN, use in_val_reg to allow gaps in the input data valid stream
......@@ -238,9 +290,8 @@ BEGIN
nxt_ref_dat <= prsg WHEN diag_sel='0' ELSE cntr;
-- The ref_dat has latency 2 compared to the in_dat, because of the register
-- stage in psrg/cntr and the register stage in ref_dat.
p_diff : PROCESS (diff_dat, ref_dat, in_val_dly2, in_dat_dly2)
-- Detect difference per bit. The ref_dat has latency 2 compared to the in_dat, because of the register stage in psrg/cntr and the register stage in ref_dat.
p_diff_dat : PROCESS (diff_dat, ref_dat, in_val_dly2, in_dat_dly2)
BEGIN
nxt_diff_dat <= diff_dat;
IF in_val_dly2='1' THEN
......@@ -250,13 +301,6 @@ BEGIN
END IF;
END PROCESS;
------------------------------------------------------------------------------
-- Hold any difference on the in_dat bus lines
------------------------------------------------------------------------------
diff_dis <= NOT in_val_2_act;
gen_verify_dat : FOR I IN in_dat'RANGE GENERATE
-- Detect and report undefined diff input 'X', which in simulation leaves diff_res at OK, because switch_high only acts on '1'
p_sim_only : PROCESS(clk)
......@@ -268,6 +312,7 @@ BEGIN
END IF;
END PROCESS;
-- Hold any difference on the in_dat bus lines
u_dat : ENTITY common_lib.common_switch
PORT MAP(
clk => clk,
......@@ -277,6 +322,58 @@ BEGIN
out_level => diff_res(I)
);
END GENERATE;
END GENERATE;
use_steps : IF g_use_steps=TRUE GENERATE
-- Determine next reference data for all steps increments of current input dat
p_ref_dat_arr : PROCESS(in_dat_reg, in_val_reg, ref_dat_arr)
BEGIN
nxt_ref_dat_arr <= ref_dat_arr;
IF in_val_reg='1' THEN
FOR I IN g_nof_steps-1 DOWNTO 0 LOOP
nxt_ref_dat_arr(I) <= INCR_UVEC(in_dat_reg, diag_steps_arr(I));
END LOOP;
END IF;
END PROCESS;
-- Detect difference for each step. The ref_dat_arr has latency 1 compared to the input dat
p_diff_arr : PROCESS(diff_arr, in_val_dly1, in_dat_dly1, ref_dat_arr)
BEGIN
nxt_diff_arr <= diff_arr;
IF in_val_dly1='1' THEN
nxt_diff_arr <= (OTHERS=>'1');
FOR I IN g_nof_steps-1 DOWNTO 0 LOOP
IF UNSIGNED(ref_dat_arr(I))=UNSIGNED(in_dat_dly1) THEN
nxt_diff_arr(I) <= '0';
END IF;
END LOOP;
END IF;
END PROCESS;
-- detect diff when no step counter value matches
p_diff_detect : PROCESS(diff_detect, diff_arr, in_val_dly2)
BEGIN
nxt_diff_detect <= diff_detect;
IF in_val_dly2='1' THEN
nxt_diff_detect <= '0';
IF vector_and(diff_arr)='1' THEN
nxt_diff_detect <= '1';
END IF;
END IF;
END PROCESS;
-- hold detected diff value
u_dat : ENTITY common_lib.common_switch
PORT MAP(
clk => clk,
rst => rst,
switch_high => diff_detect,
switch_low => diff_dis,
out_level => diff_hold
);
diff_dat <= (OTHERS=> diff_hold);
END GENERATE;
------------------------------------------------------------------------------
......
......@@ -37,6 +37,14 @@
-- |-----------------------------------------------------------------------|
-- | rx_sample[g_seq_dat_w-1:0] | 3 RO
-- |-----------------------------------------------------------------------|
-- | diag_steps_arr[0][g_seq_dat_w-1:0] | 4 RW
-- |-----------------------------------------------------------------------|
-- | diag_steps_arr[1][g_seq_dat_w-1:0] | 5 RW
-- |-----------------------------------------------------------------------|
-- | diag_steps_arr[2][g_seq_dat_w-1:0] | 6 RW
-- |-----------------------------------------------------------------------|
-- | diag_steps_arr[3][g_seq_dat_w-1:0] | 7 RW
-- |-----------------------------------------------------------------------|
--
-- . g_nof_streams
-- The MM control register for stream I in 0:g_nof_streams-1 starts at word
......@@ -78,6 +86,13 @@
-- The rx_sample keeps the last valid in_dat value. When diag_en='0' it is
-- reset to 0. Reading rx_sample via MM gives an impression of the valid
-- in_dat activity.
--
-- . g_use_steps
-- When g_use_steps=FALSE then diag_sel selects whether PSRG or COUNTER
-- data with increment +1 is used to verify the input data.
-- When g_use_steps=TRUE then the g_nof_steps =
-- c_diag_seq_rx_reg_nof_steps = 4 MM step registers define the allowed
-- COUNTER increment values.
LIBRARY IEEE, common_lib, dp_lib;
USE IEEE.std_logic_1164.ALL;
......@@ -91,6 +106,8 @@ USE work.diag_pkg.ALL;
ENTITY mms_diag_rx_seq IS
GENERIC (
g_nof_streams : NATURAL := 1;
g_use_steps : BOOLEAN := FALSE;
g_nof_steps : NATURAL := c_diag_seq_rx_reg_nof_steps;
g_seq_dat_w : NATURAL := c_word_w; -- >= 1, test sequence data width
g_data_w : NATURAL := c_word_w -- >= g_seq_dat_w, user data width
);
......@@ -115,23 +132,30 @@ ARCHITECTURE str OF mms_diag_rx_seq IS
-- Define MM slave register size
CONSTANT c_mm_reg : t_c_mem := (latency => 1,
adr_w => c_diag_seq_rx_reg_adr_w, -- = 2
adr_w => c_diag_seq_rx_reg_adr_w,
dat_w => c_word_w, -- Use MM bus data width = c_word_w = 32 for all MM registers
nof_dat => c_diag_seq_rx_reg_nof_dat, -- = 4
nof_dat => c_diag_seq_rx_reg_nof_dat,
init_sl => '0');
-- Define MM slave register fields for Python peripheral using pi_common.py (specify MM register access per word, not per individual bit because mm_fields assumes 1 field per MM word)
CONSTANT c_mm_reg_field_arr : t_common_field_arr(c_mm_reg.nof_dat-1 DOWNTO 0) :=
( ( field_name_pad("control"), "RW", 2, field_default(0) ), -- control[1:0] = diag_sel & diag_en
( field_name_pad("result"), "RO", 2, field_default(0) ), -- result[1:0] = res_val_n & res_ok_n
( field_name_pad("rx_cnt"), "RO", c_word_w, field_default(0) ),
( field_name_pad("rx_sample"), "RO", c_word_w, field_default(0) ));
( ( field_name_pad("control"), "RW", 2, field_default(0) ), -- [0] = control[1:0] = diag_sel & diag_en
( field_name_pad("result"), "RO", 2, field_default(0) ), -- [1] = result[1:0] = res_val_n & res_ok_n
( field_name_pad("rx_cnt"), "RO", c_word_w, field_default(0) ), -- [2]
( field_name_pad("rx_sample"), "RO", c_word_w, field_default(0) ), -- [3]
( field_name_pad("step_0"), "RW", c_word_w, field_default(1) ), -- [4] = diag_steps_arr[0]
( field_name_pad("step_1"), "RW", c_word_w, field_default(1) ), -- [5] = diag_steps_arr[1]
( field_name_pad("step_2"), "RW", c_word_w, field_default(1) ), -- [6] = diag_steps_arr[2]
( field_name_pad("step_3"), "RW", c_word_w, field_default(1) )); -- [7] = diag_steps_arr[3], c_diag_seq_rx_reg_nof_steps = 4
CONSTANT c_reg_slv_w : NATURAL := c_mm_reg.nof_dat*c_mm_reg.dat_w;
CONSTANT c_nof_steps_wi : NATURAL := c_diag_seq_rx_reg_nof_steps_wi;
TYPE t_reg_slv_arr IS ARRAY (INTEGER RANGE <>) OF STD_LOGIC_VECTOR(c_reg_slv_w-1 DOWNTO 0);
TYPE t_seq_dat_arr IS ARRAY (INTEGER RANGE <>) OF STD_LOGIC_VECTOR(g_seq_dat_w-1 DOWNTO 0);
TYPE t_data_arr IS ARRAY (INTEGER RANGE <>) OF STD_LOGIC_VECTOR(g_data_w-1 DOWNTO 0);
TYPE t_steps_2arr IS ARRAY (INTEGER RANGE <>) OF t_integer_arr(g_nof_steps-1 DOWNTO 0);
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);
......@@ -142,6 +166,7 @@ ARCHITECTURE str OF mms_diag_rx_seq IS
SIGNAL diag_en_arr : STD_LOGIC_VECTOR(g_nof_streams-1 DOWNTO 0);
SIGNAL diag_sel_arr : STD_LOGIC_VECTOR(g_nof_streams-1 DOWNTO 0);
SIGNAL diag_steps_2arr : t_steps_2arr(g_nof_streams-1 DOWNTO 0);
SIGNAL rx_cnt_arr : t_slv_32_arr(g_nof_streams-1 DOWNTO 0); -- can use t_slv_32_arr because c_mm_reg.dat_w = c_word_w = 32 fixed
SIGNAL rx_sample_arr : t_seq_dat_arr(g_nof_streams-1 DOWNTO 0);
......@@ -191,6 +216,8 @@ BEGIN
-- detect rx sequence errors
u_diag_rx_seq: ENTITY WORK.diag_rx_seq
GENERIC MAP (
g_use_steps => g_use_steps,
g_nof_steps => g_nof_steps,
g_cnt_w => c_word_w,
g_dat_w => g_seq_dat_w,
g_diag_res_w => g_seq_dat_w -- do not use g_seq_dat_w+1 to include NOT diag_res_val in MSbit, instead use diag_res_val output
......@@ -202,6 +229,7 @@ BEGIN
-- Write and read back registers:
diag_en => diag_en_arr(I),
diag_sel => diag_sel_arr(I),
diag_steps_arr => diag_steps_2arr(I),
-- Read only registers:
diag_res => diag_res_arr(I),
......@@ -222,12 +250,16 @@ BEGIN
-- . write ctrl_reg_arr
diag_en_arr(I) <= ctrl_reg_arr(I)(0); -- address 0, data bit [0]
diag_sel_arr(I) <= ctrl_reg_arr(I)(1); -- address 0, data bit [1]
-- address 1, not used for control
gen_diag_steps_2arr : FOR J IN 0 TO g_nof_steps-1 GENERATE
diag_steps_2arr(I)(J) <= TO_UINT(ctrl_reg_arr(I)(g_seq_dat_w-1 + (c_nof_steps_wi+J)*c_word_w DOWNTO (c_nof_steps_wi+J)*c_word_w)); -- address 4, 5, 6, 7
END GENERATE;
-- . read stat_reg_arr
p_stat_reg_arr : PROCESS(ctrl_reg_arr, stat_res_ok_n_arr, stat_res_val_n_arr, rx_cnt_arr, rx_sample_arr)
BEGIN
-- Default write / readback:
stat_reg_arr(I) <= ctrl_reg_arr(I); -- address 0: control read back
stat_reg_arr(I) <= ctrl_reg_arr(I); -- default control read back
-- Status read only:
stat_reg_arr(I)( 0+1*c_word_w) <= stat_res_ok_n_arr(I); -- address 1, data bit [0]
stat_reg_arr(I)( 1+1*c_word_w) <= stat_res_val_n_arr(I); -- address 1, data bit [1]
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment