From cc83660f5a6c42fdf7c3aeec6a21af9e830d5476 Mon Sep 17 00:00:00 2001
From: Erik Kooistra <kooistra@astron.nl>
Date: Fri, 3 Apr 2015 13:39:16 +0000
Subject: [PATCH] Support MM programmable diag_mod for tx CNTR sequence wrap
 values <= 2**g_seq_dat_w.

---
 libraries/base/diag/src/vhdl/diag_tx_seq.vhd  | 10 ++++-
 .../base/diag/src/vhdl/mms_diag_tx_seq.vhd    | 37 +++++++++++++------
 2 files changed, 34 insertions(+), 13 deletions(-)

diff --git a/libraries/base/diag/src/vhdl/diag_tx_seq.vhd b/libraries/base/diag/src/vhdl/diag_tx_seq.vhd
index 640816f533..bd8acd0922 100644
--- a/libraries/base/diag/src/vhdl/diag_tx_seq.vhd
+++ b/libraries/base/diag/src/vhdl/diag_tx_seq.vhd
@@ -37,6 +37,8 @@ USE common_lib.common_lfsr_sequences_pkg.ALL;
 --   output is valid for every active out_ready, to support streaming flow
 --   control. With g_latency=1 the out_val is active one cycle after diag_req,
 --   by using g_latency=0 outval is active in the same cycle as diag_req.
+--   Use diag_mod=0 for default binary wrap at 2**g_dat_w. For diag_rx_seq
+--   choose diag_step = 2**g_seq_dat_w - diag_mod + g_cnt_incr to verify ok.
 
 ENTITY diag_tx_seq IS
   GENERIC (
@@ -56,6 +58,7 @@ ENTITY diag_tx_seq IS
     diag_sel   : IN  STD_LOGIC := g_sel;  -- '0' = PRSG sequence data, '1' = COUNTER sequence data
     diag_dc    : IN  STD_LOGIC := '0';    -- '0' = output diag_sel sequence data, '1' = output constant diag_init data
     diag_init  : IN  STD_LOGIC_VECTOR(g_dat_w-1 DOWNTO 0) := TO_UVEC(g_init, g_dat_w);  -- init value for out_dat when diag_en = '0'
+    diag_mod   : IN  STD_LOGIC_VECTOR(g_dat_w-1 DOWNTO 0) := TO_UVEC(0, g_dat_w);       -- default 0 to wrap modulo 2*g_dat_w
     -- ST output
     diag_req   : IN  STD_LOGIC := '1';   -- '1' = request output, '0' = halt output
     out_cnt    : OUT STD_LOGIC_VECTOR(g_cnt_w-1 DOWNTO 0);  -- count valid output test sequence data
@@ -73,7 +76,8 @@ ARCHITECTURE rtl OF diag_tx_seq IS
   
   SIGNAL prsg            : STD_LOGIC_VECTOR(out_dat'RANGE);
   SIGNAL nxt_prsg        : STD_LOGIC_VECTOR(out_dat'RANGE);
-  SIGNAL cntr            : STD_LOGIC_VECTOR(out_dat'RANGE);
+  SIGNAL cntr            : STD_LOGIC_VECTOR(out_dat'RANGE) := (OTHERS=>'0');  -- init to avoid Warning: "NUMERIC_STD."<": metavalue detected" with UNSIGNED()
+  SIGNAL next_cntr       : STD_LOGIC_VECTOR(out_dat'RANGE) := (OTHERS=>'0');  -- init to avoid Warning: "NUMERIC_STD."<": metavalue detected" with UNSIGNED()
   SIGNAL nxt_cntr        : STD_LOGIC_VECTOR(out_dat'RANGE);
   
   SIGNAL nxt_out_dat     : STD_LOGIC_VECTOR(out_dat'RANGE);
@@ -124,7 +128,9 @@ BEGIN
                       prsg,         -- IN
                       cntr,         -- IN
                       nxt_prsg,     -- OUT
-                      nxt_cntr);    -- OUT
+                      next_cntr);   -- OUT
+                      
+  nxt_cntr <= next_cntr WHEN UNSIGNED(next_cntr) < UNSIGNED(diag_mod) ELSE SUB_UVEC(next_cntr, diag_mod);
   
   nxt_out_dat <= diag_init WHEN diag_dc='1' ELSE prsg WHEN diag_sel='0' ELSE cntr;
   nxt_out_val <= diag_en AND diag_req;  -- 'en' for entire test on/off, 'req' for dynamic invalid gaps in the stream
diff --git a/libraries/base/diag/src/vhdl/mms_diag_tx_seq.vhd b/libraries/base/diag/src/vhdl/mms_diag_tx_seq.vhd
index 722a991a64..ac548d61f7 100644
--- a/libraries/base/diag/src/vhdl/mms_diag_tx_seq.vhd
+++ b/libraries/base/diag/src/vhdl/mms_diag_tx_seq.vhd
@@ -35,6 +35,8 @@
 --  |-----------------------------------------------------------------------|
 --  |                                 tx_cnt[31:0]                          |  2  RO
 --  |-----------------------------------------------------------------------|
+--  |                               diag_mod[31:0]                          |  3  RW
+--  |-----------------------------------------------------------------------|
 --
 -- . g_use_usr_input
 --   When g_use_usr_input=TRUE then the tx_seq data overrules the usr_sosi_arr
@@ -125,8 +127,14 @@
 --   since diag_en went active. An incrementing tx_cnt shows that data is
 --   being transmitted.
 --
-
-LIBRARY IEEE, common_lib, dp_lib;
+-- . diag_mod
+--    CNTR counts modulo diag_mod, so diag_mod becomes 0. Use diag_mod = 0
+--    for default binary wrap at 2**g_seq_dat_w. For diag_rx_seq choose
+--    diag_step = 2**g_seq_dat_w - diag_mod + g_cnt_incr to verify ok as 
+--    simulated with tb_tb_diag_rx_seq. In this mms_diag_tx_seq g_cnt_incr=1
+--    fixed for diag_tx_seq.
+
+LIBRARY IEEE, common_lib, dp_lib;  -- init value for out_dat when diag_en = '0'
 USE IEEE.std_logic_1164.ALL;
 USE common_lib.common_pkg.ALL;
 USE common_lib.common_mem_pkg.ALL;
@@ -165,16 +173,17 @@ ARCHITECTURE str OF mms_diag_tx_seq IS
 
   -- Define MM slave register size
   CONSTANT c_mm_reg      : t_c_mem  := (latency  => 1,
-                                        adr_w    => c_diag_seq_tx_reg_adr_w,    -- = 2
+                                        adr_w    => c_diag_seq_tx_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_tx_reg_nof_dat,  -- = 3
+                                        nof_dat  => c_diag_seq_tx_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",        3, field_default(0) ),  -- control[2:0] = diag_dc & diag_sel & diag_en
                                   ( field_name_pad("init"),    "RW", c_word_w, field_default(0) ),
-                                  ( field_name_pad("tx_cnt"),  "RO", c_word_w, field_default(0) ));
+                                  ( field_name_pad("tx_cnt"),  "RO", c_word_w, field_default(0) ),
+                                  ( field_name_pad("modulo"),  "RW", c_word_w, field_default(0) ));
   
   CONSTANT c_reg_slv_w   : NATURAL := c_mm_reg.nof_dat*c_mm_reg.dat_w;
 
@@ -198,6 +207,9 @@ ARCHITECTURE str OF mms_diag_tx_seq IS
   SIGNAL diag_init_mm_arr      : t_slv_32_arr(g_nof_streams-1 DOWNTO 0) := (OTHERS=>(OTHERS=>'0'));  -- can use t_slv_32_arr because c_mm_reg.dat_w = c_word_w = 32 fixed
   SIGNAL diag_init_arr         : t_seq_dat_arr(g_nof_streams-1 DOWNTO 0) := (OTHERS=>(OTHERS=>'0'));
 
+  SIGNAL diag_mod_mm_arr       : t_slv_32_arr(g_nof_streams-1 DOWNTO 0) := (OTHERS=>(OTHERS=>'0'));  -- can use t_slv_32_arr because c  -- init value for out_dat when diag_en = '0'_mm_reg.dat_w = c_word_w = 32 fixed
+  SIGNAL diag_mod_arr          : t_seq_dat_arr(g_nof_streams-1 DOWNTO 0) := (OTHERS=>(OTHERS=>'0'));
+  
   SIGNAL tx_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 tx_dat_arr            : t_seq_dat_arr(g_nof_streams-1 DOWNTO 0);
   SIGNAL tx_val_arr            : STD_LOGIC_VECTOR(g_nof_streams-1 DOWNTO 0);
@@ -230,6 +242,7 @@ BEGIN
       diag_sel  => diag_sel_arr(I),
       diag_dc   => diag_dc_arr(I),
       diag_init => diag_init_arr(I),
+      diag_mod  => diag_mod_arr(I),
 
       -- Streaming
       diag_req  => tx_req_arr(I),
@@ -247,12 +260,14 @@ BEGIN
     tx_seq_sosi_arr(I).valid <= tx_val_arr(I);
 
     -- Register mapping
-    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]
-    diag_dc_arr(I)      <= ctrl_reg_arr(I)(                           2);  -- address 0, data bit [2]
-    diag_init_mm_arr(I) <= ctrl_reg_arr(I)(2*c_word_w-1 DOWNTO c_word_w);  -- address 1, data bits [31:0]
-
-    diag_init_arr(I)    <= RESIZE_UVEC(diag_init_mm_arr(I), g_seq_dat_w);
+    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]
+    diag_dc_arr(I)      <= ctrl_reg_arr(I)(                             2);  -- address 0, data bit [2]
+    diag_init_mm_arr(I) <= ctrl_reg_arr(I)(2*c_word_w-1 DOWNTO   c_word_w);  -- address 1, data bits [31:0]
+    diag_mod_mm_arr(I)  <= ctrl_reg_arr(I)(4*c_word_w-1 DOWNTO 3*c_word_w);  -- address 3, data bits [31:0]
+
+    diag_init_arr(I) <= RESIZE_UVEC(diag_init_mm_arr(I), g_seq_dat_w);
+    diag_mod_arr(I)  <= RESIZE_UVEC(diag_mod_mm_arr(I), g_seq_dat_w);
 
     p_stat_reg : PROCESS(ctrl_reg_arr(I), tx_cnt_arr)
     BEGIN
-- 
GitLab