From 29c7e7f9d56eaa83e01d0cfc06427e957eb1cc50 Mon Sep 17 00:00:00 2001
From: donker <donker@astron.nl>
Date: Wed, 7 Oct 2020 15:58:51 +0200
Subject: [PATCH] processed review remarks and changed tb_

---
 .../base/dp/src/vhdl/dp_bsn_source_reg_v2.vhd |  40 ++---
 .../base/dp/src/vhdl/dp_bsn_source_v2.vhd     | 148 +++++++++--------
 libraries/base/dp/src/vhdl/dp_stream_pkg.vhd  |   6 +
 .../base/dp/src/vhdl/mms_dp_bsn_source_v2.vhd |   6 +-
 .../base/dp/tb/vhdl/tb_dp_bsn_source_v2.vhd   | 153 +++++++++++-------
 libraries/base/dp/tb/vhdl/tb_dp_pkg.vhd       |  54 +++++--
 .../dp/tb/vhdl/tb_mms_dp_bsn_source_v2.vhd    |   4 +-
 .../dp/tb/vhdl/tb_tb_dp_bsn_source_v2.vhd     |   4 +
 8 files changed, 256 insertions(+), 159 deletions(-)

diff --git a/libraries/base/dp/src/vhdl/dp_bsn_source_reg_v2.vhd b/libraries/base/dp/src/vhdl/dp_bsn_source_reg_v2.vhd
index fed0ff23ae..65c0b826c1 100644
--- a/libraries/base/dp/src/vhdl/dp_bsn_source_reg_v2.vhd
+++ b/libraries/base/dp/src/vhdl/dp_bsn_source_reg_v2.vhd
@@ -34,8 +34,8 @@
 --                                              RD '0' = DP off; RD '1' = DP on.
 --      [1]     WR  dp_on_pps          0x0   
 --  1   [31..0] WR  nof_clk_per_sync   0x0    
---  2   [31..0] RW  bsn[31..0]         0x0      write init_bsn, read current bsn
---  3   [31..0] RW  bsn[63..32]        0x0      write init_bsn, read current bsn     
+--  2   [31..0] RW  bsn[31..0]         0x0      write bsn_init, read current bsn
+--  3   [31..0] RW  bsn[63..32]        0x0      write bsn_init, read current bsn     
 --  ====================================================================================
 
 LIBRARY IEEE, common_lib;
@@ -64,7 +64,7 @@ ENTITY dp_bsn_source_reg_v2 IS
     st_on_pps           : OUT STD_LOGIC := '0';  -- level
     st_on_status        : IN  STD_LOGIC;
     st_nof_clk_per_sync : OUT STD_LOGIC_VECTOR(c_word_w-1 DOWNTO 0);  -- nof block per sync
-    st_init_bsn         : OUT STD_LOGIC_VECTOR;  -- wr init BSN
+    st_bsn_init         : OUT STD_LOGIC_VECTOR;  -- wr init BSN
     st_current_bsn      : IN  STD_LOGIC_VECTOR   -- rd current BSN
   );
 END dp_bsn_source_reg_v2;
@@ -72,7 +72,7 @@ END dp_bsn_source_reg_v2;
 
 ARCHITECTURE rtl OF dp_bsn_source_reg_v2 IS
 
-  CONSTANT c_bsn_w                : NATURAL := st_init_bsn'LENGTH;
+  CONSTANT c_bsn_w                : NATURAL := st_bsn_init'LENGTH;
   
   -- Define the actual size of the MM slave register
   CONSTANT c_mm_reg : t_c_mem := (latency  => 1,
@@ -90,8 +90,8 @@ ARCHITECTURE rtl OF dp_bsn_source_reg_v2 IS
   
   SIGNAL mm_nof_clk_per_sync : STD_LOGIC_VECTOR(c_word_w-1 DOWNTO 0);
   
-  SIGNAL mm_init_bsn           : STD_LOGIC_VECTOR(c_longword_w-1 DOWNTO 0);
-  SIGNAL mm_init_bsn_wr        : STD_LOGIC;
+  SIGNAL mm_bsn_init           : STD_LOGIC_VECTOR(c_longword_w-1 DOWNTO 0);
+  SIGNAL mm_bsn_init_wr        : STD_LOGIC;
   SIGNAL mm_current_bsn        : STD_LOGIC_VECTOR(c_longword_w-1 DOWNTO 0) := (OTHERS=>'0');
   SIGNAL mm_current_bsn_hi     : STD_LOGIC_VECTOR(c_word_w-1 DOWNTO 0) := (OTHERS=>'0');
   
@@ -116,15 +116,15 @@ BEGIN
       mm_on             <= '0';
       mm_on_pps        <= '0';
       mm_nof_clk_per_sync <= TO_UVEC(g_nof_clk_per_sync, c_word_w);
-      mm_init_bsn           <= (OTHERS=>'0');
-      mm_init_bsn_wr        <= '0';
+      mm_bsn_init           <= (OTHERS=>'0');
+      mm_bsn_init_wr        <= '0';
       mm_current_bsn_hi     <= (OTHERS=>'0');
     ELSIF rising_edge(mm_clk) THEN
       -- Read access defaults
       sla_out.rdval <= '0';
       
       -- Access event defaults
-      mm_init_bsn_wr    <= '0';
+      mm_bsn_init_wr    <= '0';
       
       -- Write access: set register value
       IF sla_in.wr = '1' THEN
@@ -138,10 +138,10 @@ BEGIN
             
           -- Write init BSN
           WHEN 2 =>
-            mm_init_bsn(31 DOWNTO  0)  <= sla_in.wrdata(31 DOWNTO 0);
+            mm_bsn_init(31 DOWNTO  0)  <= sla_in.wrdata(31 DOWNTO 0);
           WHEN 3 =>
-            mm_init_bsn(63 DOWNTO 32)  <= sla_in.wrdata(31 DOWNTO 0);
-            mm_init_bsn_wr             <= '1';
+            mm_bsn_init(63 DOWNTO 32)  <= sla_in.wrdata(31 DOWNTO 0);
+            mm_bsn_init_wr             <= '1';
           
           WHEN OTHERS => NULL;  -- not used MM addresses
         END CASE;
@@ -192,15 +192,15 @@ BEGIN
     st_on               <= mm_on;
     st_on_pps           <= mm_on_pps;
     st_nof_clk_per_sync <= mm_nof_clk_per_sync;
-    st_init_bsn         <= mm_init_bsn(c_bsn_w-1 DOWNTO 0);
+    st_bsn_init         <= mm_bsn_init(c_bsn_w-1 DOWNTO 0);
     
     p_st_clk : PROCESS(st_rst, st_clk)
     BEGIN
       IF st_rst='1' THEN
-        st_init_bsn <= TO_UVEC(0, c_bsn_w);
+        st_bsn_init <= TO_UVEC(0, c_bsn_w);
       ELSIF rising_edge(st_clk) THEN
-        IF mm_init_bsn_wr='1' THEN
-          st_init_bsn <= mm_init_bsn(c_bsn_w-1 DOWNTO 0);  -- use wr of mm_init_bsn high part for in_new to ensure proper transfer of double word
+        IF mm_bsn_init_wr='1' THEN
+          st_bsn_init <= mm_bsn_init(c_bsn_w-1 DOWNTO 0);  -- use wr of mm_bsn_init high part for in_new to ensure proper transfer of double word
         END IF;
       END IF;
     END PROCESS;
@@ -253,16 +253,16 @@ BEGIN
     );
     
     -- write occurs with sufficient margin before it is used, still use common_reg_cross_domain nonetheless
-    u_init_bsn : ENTITY common_lib.common_reg_cross_domain
+    u_bsn_init : ENTITY common_lib.common_reg_cross_domain
     PORT MAP (
       in_rst      => mm_rst,
       in_clk      => mm_clk,
-      in_new      => mm_init_bsn_wr,         -- use wr of mm_init_bsn high part for in_new to ensure proper transfer of double word
-      in_dat      => mm_init_bsn(c_bsn_w-1 DOWNTO 0),
+      in_new      => mm_bsn_init_wr,         -- use wr of mm_bsn_init high part for in_new to ensure proper transfer of double word
+      in_dat      => mm_bsn_init(c_bsn_w-1 DOWNTO 0),
       in_done     => OPEN,                   -- pulses when no more pending in_new
       out_rst     => st_rst,
       out_clk     => st_clk,
-      out_dat     => st_init_bsn,
+      out_dat     => st_bsn_init,
       out_new     => OPEN
     );
     
diff --git a/libraries/base/dp/src/vhdl/dp_bsn_source_v2.vhd b/libraries/base/dp/src/vhdl/dp_bsn_source_v2.vhd
index 5108162f14..f12b484d05 100644
--- a/libraries/base/dp/src/vhdl/dp_bsn_source_v2.vhd
+++ b/libraries/base/dp/src/vhdl/dp_bsn_source_v2.vhd
@@ -31,6 +31,9 @@
 -- Remarks:
 --   Starting the data path is only possible from the dp_off state, so one
 --   has to disable (dp_on='0') the data path before restarting it.
+--
+-- author : P.Donker  okt. 2020
+--
 
 LIBRARY IEEE, common_lib;
 USE IEEE.STD_LOGIC_1164.ALL;
@@ -43,7 +46,7 @@ ENTITY dp_bsn_source_v2 IS
     g_block_size         : NATURAL := 256;  
     g_nof_clk_per_sync   : NATURAL := 200 * 10**6; 
     g_bsn_w              : NATURAL := 48;
-    g_offset_w           : NATURAL := 4 
+    g_time_offset_w      : NATURAL := 10 
   );
   PORT (
     rst                : IN  STD_LOGIC;
@@ -55,10 +58,9 @@ ENTITY dp_bsn_source_v2 IS
 
     dp_on_status       : OUT STD_LOGIC;        
  
-    init_bsn           : IN  STD_LOGIC_VECTOR(g_bsn_w-1 DOWNTO 0) := (OTHERS=>'0');
+    bsn_init           : IN  STD_LOGIC_VECTOR(g_bsn_w-1 DOWNTO 0) := (OTHERS=>'0');
     nof_clk_per_sync   : IN  STD_LOGIC_VECTOR(c_word_w-1 DOWNTO 0) := TO_UVEC(g_nof_clk_per_sync, c_word_w);
-    offset_bsn         : IN  STD_LOGIC_VECTOR(g_offset_w-1 DOWNTO 0) := (OTHERS=>'0');
-    --offset_bsn         : IN  STD_LOGIC_VECTOR(g_offset_w-1 DOWNTO 0) := TO_UVEC(4, g_offset_w);
+    bsn_time_offset    : IN  STD_LOGIC_VECTOR(g_time_offset_w-1 DOWNTO 0) := (OTHERS=>'0');
 
     src_out            : OUT t_dp_sosi  -- only uses sync, bsn[], valid, sop and eop
   );
@@ -70,7 +72,21 @@ ARCHITECTURE rtl OF dp_bsn_source_v2 IS
   CONSTANT c_block_size_cnt_w : NATURAL := ceil_log2(g_block_size);
   CONSTANT c_block_cnt_zero   : STD_LOGIC_VECTOR(g_bsn_w-1 DOWNTO 0) := (OTHERS => '0');
 
-  TYPE t_state_enum IS (s_init, s_dp_off, s_dp_on_sop, s_dp_on, s_dp_on_eop, s_bsn_offset);
+  -- The state machine starts synchronously via s_bsn_time_offset, s_dp_on_sop to s_dp_on, or it starts
+  -- directly to s_dp_on. When in dp_on it loops between s_dp_on and s_dp_on_eop for every block.
+  -- If the BSN source is switched off, then after completing the block s_dp_on_eop goes back to
+  -- s_dp_off.
+  --
+  -- Sketch of the state machine:
+  --
+  -- s_init --> s_dp_off --> s_bsn_time_offset --                      ------------ (loop) <---
+  --            \       \                        \                    /                        \ 
+  --             \       ---------------------------> s_dp_on_sop --> s_dp_on --> s_dp_on_eop --
+  --              \                                                                            /
+  --               ----------------------------------------------------------------- (off) <--- 
+
+
+  TYPE t_state_enum IS (s_init, s_dp_off, s_bsn_time_offset, s_dp_on_sop, s_dp_on, s_dp_on_eop);
 
   SIGNAL state       : t_state_enum;
   SIGNAL nxt_state   : t_state_enum; 
@@ -79,17 +95,14 @@ ARCHITECTURE rtl OF dp_bsn_source_v2 IS
   SIGNAL block_size_cnt     : STD_LOGIC_VECTOR(c_block_size_cnt_w-1 DOWNTO 0);
   SIGNAL nxt_block_size_cnt : STD_LOGIC_VECTOR(c_block_size_cnt_w-1 DOWNTO 0);
   
-  --SIGNAL block_cnt          : STD_LOGIC_VECTOR(g_bsn_w-1 DOWNTO 0);
-  --SIGNAL nxt_block_cnt      : STD_LOGIC_VECTOR(g_bsn_w-1 DOWNTO 0);
-
   SIGNAL i_src_out          : t_dp_sosi := c_dp_sosi_init;
   SIGNAL nxt_src_out        : t_dp_sosi;
  
-  SIGNAL nxt_dp_on_status   : STD_LOGIC;
   SIGNAL i_dp_on_status     : STD_LOGIC;
+  SIGNAL nxt_dp_on_status   : STD_LOGIC;
 
-  SIGNAL nxt_offset_bsn_cnt : STD_LOGIC_VECTOR(g_offset_w-1 DOWNTO 0);
-  SIGNAL offset_bsn_cnt     : STD_LOGIC_VECTOR(g_offset_w-1 DOWNTO 0);
+  SIGNAL nxt_bsn_time_offset_cnt : STD_LOGIC_VECTOR(g_time_offset_w-1 DOWNTO 0);
+  SIGNAL bsn_time_offset_cnt     : STD_LOGIC_VECTOR(g_time_offset_w-1 DOWNTO 0);
 
   SIGNAL nxt_clk_cnt        : STD_LOGIC_VECTOR(c_word_w-1 DOWNTO 0);
   SIGNAL clk_cnt            : STD_LOGIC_VECTOR(c_word_w-1 DOWNTO 0);
@@ -101,41 +114,56 @@ BEGIN
   src_out <= i_src_out;
   dp_on_status <= i_dp_on_status;
 
-  p_state : PROCESS(state, prev_state, dp_on, dp_on_pps, pps, block_size_cnt, clk_cnt, init_bsn, i_src_out, i_dp_on_status, offset_bsn_cnt)
+  p_state : PROCESS(state, prev_state, dp_on, dp_on_pps, pps, block_size_cnt, clk_cnt, bsn_init, i_src_out, i_dp_on_status, bsn_time_offset_cnt)
   BEGIN  
-    nxt_state           <= state;   
-    nxt_src_out         <= i_src_out;
-    nxt_src_out.sync    <= '0';
-    nxt_src_out.valid   <= '0';
-    nxt_src_out.sop     <= '0';
-    nxt_src_out.eop     <= '0';
-    nxt_block_size_cnt  <= block_size_cnt;
-    nxt_clk_cnt         <= INCR_UVEC(clk_cnt, 1);
-    nxt_sync            <= sync;
-    nxt_dp_on_status    <= i_dp_on_status;
-    nxt_offset_bsn_cnt  <= offset_bsn_cnt;
+    nxt_state               <= state;
+    nxt_src_out             <= i_src_out;
+    nxt_src_out.sync        <= '0';
+    nxt_src_out.valid       <= '0';
+    nxt_src_out.sop         <= '0';
+    nxt_src_out.eop         <= '0';
+    nxt_block_size_cnt      <= block_size_cnt;
+    nxt_clk_cnt             <= INCR_UVEC(clk_cnt, 1);
+    nxt_sync                <= sync;
+    nxt_dp_on_status        <= i_dp_on_status;
+    nxt_bsn_time_offset_cnt <= bsn_time_offset_cnt;
 
     IF UNSIGNED(clk_cnt) = UNSIGNED(nof_clk_per_sync) - 1 THEN
       nxt_clk_cnt <=  (OTHERS=>'0');
-      nxt_sync    <= '1';  -- set sync signal on next sop
+      nxt_sync    <= '1';  -- will set src_out.sync on next src_out.sop
     END IF;
 
     CASE state IS
 
-      WHEN s_dp_on_eop =>
-        nxt_src_out.eop    <= '1';
-        nxt_src_out.valid  <= '1'; 
-        nxt_state          <= s_dp_on_sop;
-        nxt_block_size_cnt <= INCR_UVEC(block_size_cnt, 1);
-        IF dp_on = '0' THEN
-          nxt_state <= s_dp_off;
+      WHEN s_init =>
+        nxt_state <= s_dp_off;
+      
+      WHEN s_dp_off =>
+        nxt_dp_on_status <= '0';
+        nxt_src_out.bsn <= RESIZE_DP_BSN(bsn_init);
+        nxt_sync <= '0';
+        nxt_clk_cnt <=  (OTHERS=>'0');
+        IF dp_on = '1' THEN 
+          IF dp_on_pps = '1' THEN
+            nxt_sync <= '1';
+            IF pps = '1' THEN
+              IF UNSIGNED(bsn_time_offset) = 0 THEN
+                nxt_state   <= s_dp_on_sop;
+              ELSE
+                nxt_bsn_time_offset_cnt <= (OTHERS=>'0');
+                nxt_state          <= s_bsn_time_offset;
+              END IF;
+            END IF; 
+          ELSE 
+            nxt_state   <= s_dp_on_sop;
+          END IF;
         END IF;
 
-      WHEN s_dp_on =>
-        nxt_src_out.valid  <= '1';
-        nxt_block_size_cnt <= INCR_UVEC(block_size_cnt, 1);
-        IF UNSIGNED(block_size_cnt) = g_block_size -3 THEN
-          nxt_state        <= s_dp_on_eop;
+      WHEN s_bsn_time_offset =>
+        IF UNSIGNED(bsn_time_offset_cnt) = UNSIGNED(bsn_time_offset) THEN
+          nxt_state <= s_dp_on_sop;
+        ELSE
+          nxt_bsn_time_offset_cnt <= INCR_UVEC(bsn_time_offset_cnt, 1);
         END IF;
 
       WHEN s_dp_on_sop =>
@@ -145,38 +173,28 @@ BEGIN
         nxt_state          <= s_dp_on;
         nxt_block_size_cnt <= (OTHERS=>'0');
         IF prev_state = s_dp_on_eop THEN
-          nxt_src_out.bsn(g_bsn_w-1 DOWNTO 0) <= INCR_UVEC(i_src_out.bsn(g_bsn_w-1 DOWNTO 0), 1);
+          -- nxt_src_out.bsn(g_bsn_w-1 DOWNTO 0) <= INCR_UVEC(i_src_out.bsn(g_bsn_w-1 DOWNTO 0), 1);
+          nxt_src_out.bsn <= INCR_DP_BSN(i_src_out.bsn, 1, g_bsn_w);
         END IF;
         IF sync = '1' THEN 
           nxt_src_out.sync <= '1';
-          nxt_sync <= '0';  -- clear sync if set
+          nxt_sync <= '0';
         END IF;
 
-      WHEN s_dp_off =>
-        nxt_dp_on_status <= '0';
-        nxt_src_out.bsn <= RESIZE_DP_BSN(init_bsn);
-        nxt_sync <= '0';  -- clear sync if set
-        nxt_clk_cnt <=  (OTHERS=>'0');
-        IF dp_on = '1' THEN 
-          IF dp_on_pps = '1' THEN
-            IF pps = '1' THEN
-              IF UNSIGNED(offset_bsn) = 0 THEN
-                nxt_state   <= s_dp_on_sop;
-              ELSE
-                nxt_offset_bsn_cnt <= (OTHERS=>'0');
-                nxt_state          <= s_bsn_offset;
-              END IF;
-            END IF; 
-          ELSE 
-            nxt_state   <= s_dp_on_sop;
-          END IF;
+      WHEN s_dp_on =>
+        nxt_src_out.valid  <= '1';
+        nxt_block_size_cnt <= INCR_UVEC(block_size_cnt, 1);
+        IF UNSIGNED(block_size_cnt) = g_block_size -3 THEN
+          nxt_state        <= s_dp_on_eop;
         END IF;
-    
-      WHEN s_bsn_offset =>
-        IF offset_bsn_cnt = offset_bsn THEN
-          nxt_state <= s_dp_on_sop;
-        ELSE
-          nxt_offset_bsn_cnt <= INCR_UVEC(offset_bsn_cnt, 1);
+
+      WHEN s_dp_on_eop =>
+        nxt_src_out.eop    <= '1';
+        nxt_src_out.valid  <= '1'; 
+        nxt_state          <= s_dp_on_sop;
+        nxt_block_size_cnt <= INCR_UVEC(block_size_cnt, 1);
+        IF dp_on = '0' THEN
+          nxt_state <= s_dp_off;
         END IF;
 
       WHEN OTHERS => -- s_init
@@ -192,22 +210,20 @@ BEGIN
       prev_state     <= s_init;
       state          <= s_init;
       i_src_out      <= c_dp_sosi_rst;
-      --block_cnt      <= (OTHERS=>'0');
       clk_cnt        <= (OTHERS=>'0');
       sync           <= '0'; 
       block_size_cnt <= (OTHERS=>'0');
       i_dp_on_status <= '0';
-      offset_bsn_cnt <= (OTHERS=>'0');
+      bsn_time_offset_cnt <= (OTHERS=>'0');
     ELSIF rising_edge(clk) THEN
       prev_state     <= state;
       state          <= nxt_state;
       i_src_out      <= nxt_src_out;
-      --block_cnt      <= nxt_block_cnt;
       clk_cnt        <= nxt_clk_cnt;
       sync           <= nxt_sync;
       block_size_cnt <= nxt_block_size_cnt;
       i_dp_on_status <= nxt_dp_on_status;
-      offset_bsn_cnt <= nxt_offset_bsn_cnt;
+      bsn_time_offset_cnt <= nxt_bsn_time_offset_cnt;
     END IF;
   END PROCESS;
 
diff --git a/libraries/base/dp/src/vhdl/dp_stream_pkg.vhd b/libraries/base/dp/src/vhdl/dp_stream_pkg.vhd
index bf43a639f3..677d106cf4 100644
--- a/libraries/base/dp/src/vhdl/dp_stream_pkg.vhd
+++ b/libraries/base/dp/src/vhdl/dp_stream_pkg.vhd
@@ -264,6 +264,7 @@ PACKAGE dp_stream_pkg Is
   FUNCTION INCR_DP_DATA(    vec : STD_LOGIC_VECTOR; dec : INTEGER; w : NATURAL) RETURN STD_LOGIC_VECTOR;  -- unsigned vec(w-1:0) + dec
   FUNCTION INCR_DP_SDATA(   vec : STD_LOGIC_VECTOR; dec : INTEGER; w : NATURAL) RETURN STD_LOGIC_VECTOR;  --   signed vec(w-1:0) + dec
   FUNCTION INCR_DP_DSP_DATA(vec : STD_LOGIC_VECTOR; dec : INTEGER; w : NATURAL) RETURN STD_LOGIC_VECTOR;  --   signed vec(w-1:0) + dec
+  FUNCTION INCR_DP_BSN(     vec : STD_LOGIC_VECTOR; dec : INTEGER; w : NATURAL) RETURN STD_LOGIC_VECTOR;  -- unsigned vec(w-1:0) + dec
   
   FUNCTION REPLICATE_DP_DATA(  seq  : STD_LOGIC_VECTOR                 ) RETURN STD_LOGIC_VECTOR;  -- replicate seq as often as fits in c_dp_stream_data_w
   FUNCTION UNREPLICATE_DP_DATA(data : STD_LOGIC_VECTOR; seq_w : NATURAL) RETURN STD_LOGIC_VECTOR;  -- unreplicate data to width seq_w, return low seq_w bits and set mismatch MSbits bits to '1'
@@ -573,6 +574,11 @@ PACKAGE BODY dp_stream_pkg IS
     RETURN RESIZE_DP_DSP_DATA(STD_LOGIC_VECTOR(SIGNED(vec(w-1 DOWNTO 0)) + dec));
   END INCR_DP_DSP_DATA;  
   
+  FUNCTION INCR_DP_BSN(vec : STD_LOGIC_VECTOR; dec : INTEGER; w : NATURAL) RETURN STD_LOGIC_VECTOR IS
+  BEGIN
+    RETURN RESIZE_DP_BSN(STD_LOGIC_VECTOR(UNSIGNED(vec(w-1 DOWNTO 0)) + dec));
+  END INCR_DP_BSN;
+
   FUNCTION REPLICATE_DP_DATA(seq : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR IS
     CONSTANT c_seq_w            : NATURAL := seq'LENGTH;
     CONSTANT c_nof_replications : NATURAL := ceil_div(c_dp_stream_data_w, c_seq_w);
diff --git a/libraries/base/dp/src/vhdl/mms_dp_bsn_source_v2.vhd b/libraries/base/dp/src/vhdl/mms_dp_bsn_source_v2.vhd
index 501e886099..3ca46fb3ca 100644
--- a/libraries/base/dp/src/vhdl/mms_dp_bsn_source_v2.vhd
+++ b/libraries/base/dp/src/vhdl/mms_dp_bsn_source_v2.vhd
@@ -59,7 +59,7 @@ ARCHITECTURE str OF mms_dp_bsn_source_v2 IS
   SIGNAL dp_on              : STD_LOGIC;
   SIGNAL dp_on_pps          : STD_LOGIC;
   SIGNAL nof_clk_per_sync   : STD_LOGIC_VECTOR(c_word_w-1 DOWNTO 0);
-  SIGNAL init_bsn           : STD_LOGIC_VECTOR(g_bsn_w-1 DOWNTO 0);
+  SIGNAL bsn_init           : STD_LOGIC_VECTOR(g_bsn_w-1 DOWNTO 0);
   
   SIGNAL i_bs_sosi          : t_dp_sosi;
 
@@ -92,7 +92,7 @@ BEGIN
     st_on_pps             => dp_on_pps,
     st_on_status          => dp_on_status,
     st_nof_clk_per_sync   => nof_clk_per_sync,
-    st_init_bsn           => init_bsn,
+    st_bsn_init           => bsn_init,
     st_current_bsn        => capture_bsn
   );
   
@@ -110,7 +110,7 @@ BEGIN
     dp_on              => dp_on,
     dp_on_pps          => dp_on_pps,
     dp_on_status       => dp_on_status,
-    init_bsn           => init_bsn,
+    bsn_init           => bsn_init,
     nof_clk_per_sync   => nof_clk_per_sync,
     -- Streaming
     src_out            => i_bs_sosi
diff --git a/libraries/base/dp/tb/vhdl/tb_dp_bsn_source_v2.vhd b/libraries/base/dp/tb/vhdl/tb_dp_bsn_source_v2.vhd
index 591d5e9262..8fe8c59f7f 100644
--- a/libraries/base/dp/tb/vhdl/tb_dp_bsn_source_v2.vhd
+++ b/libraries/base/dp/tb/vhdl/tb_dp_bsn_source_v2.vhd
@@ -36,18 +36,16 @@ USE dp_lib.tb_dp_pkg.ALL;
 
 ENTITY tb_dp_bsn_source_v2 IS
   GENERIC (
-    g_sync_offset  : NATURAL := 0;  -- must be < c_sync_period for proc_dp_verify_sync
-    g_clk_per_sync : NATURAL := 240
+    g_pps_interval : NATURAL := 240;
+    g_block_size   : NATURAL := 32 
   );
 END tb_dp_bsn_source_v2;
 
 ARCHITECTURE tb OF tb_dp_bsn_source_v2 IS
 
   CONSTANT c_clk_period   : TIME    := 10 ns;
-
-  CONSTANT c_block_size   : NATURAL := 32; -- 31;
-  CONSTANT c_bsn_w        : NATURAL := 31; -- 16;
-  CONSTANT c_sync_period  : NATURAL := 8;
+  CONSTANT c_bsn_w        : NATURAL := 31;
+  CONSTANT c_dut_latency  : NATURAL := 2;
 
   -- The state name tells what kind of test is being done
   TYPE t_state_enum IS (
@@ -61,21 +59,35 @@ ARCHITECTURE tb OF tb_dp_bsn_source_v2 IS
   SIGNAL tb_end       : STD_LOGIC := '0';
   SIGNAL rst          : STD_LOGIC := '1';
   SIGNAL clk          : STD_LOGIC := '1';
-  SIGNAL pps          : STD_LOGIC;
 
   -- DUT
   SIGNAL dp_on        : STD_LOGIC := '0';
   SIGNAL dp_on_pps    : STD_LOGIC := '0';
-  SIGNAL init_bsn     : STD_LOGIC_VECTOR(c_bsn_w-1 DOWNTO 0) := (OTHERS=>'0');
+  SIGNAL bsn_init     : STD_LOGIC_VECTOR(c_bsn_w-1 DOWNTO 0) := (OTHERS=>'0');
 
   SIGNAL bs_sosi      : t_dp_sosi;
 
   -- Verify
-  SIGNAL verify_sync  : STD_LOGIC := '1';
+  SIGNAL verify_sync  : STD_LOGIC := '0';
   SIGNAL hold_bs_sop  : STD_LOGIC;
 
   SIGNAL tb_bsn_cnt   : INTEGER := 0;
 
+  -- Define the PPS grid and the BSN grid that both start at 0 according to Figure 3.1 in [doc]:
+  SIGNAL SSN                 : NATURAL   := 0;
+  SIGNAL BSN                 : NATURAL   := 0;
+  
+  SIGNAL pps_sop             : STD_LOGIC := '0';
+  SIGNAL nxt_pps_sop         : STD_LOGIC := '0';
+  SIGNAL pps_eop             : STD_LOGIC := '0';
+  SIGNAL bsn_sop             : STD_LOGIC := '0';
+  SIGNAL nxt_bsn_sop         : STD_LOGIC := '0';
+  SIGNAL bsn_eop             : STD_LOGIC := '0';
+  SIGNAL expected_sync       : STD_LOGIC := '0';
+  SIGNAL expected_sync_dly   : STD_LOGIC := '0';
+  SIGNAL expected_bsn        : NATURAL   := 0;
+  SIGNAL expected_offset_bsn : NATURAL   := 0;
+
 BEGIN
 
   -----------------------------------------------------------------------------
@@ -84,70 +96,93 @@ BEGIN
   rst <= '1', '0' AFTER c_clk_period*7;
   clk <= (NOT clk) OR tb_end AFTER c_clk_period/2;
 
+  
+  -- SSN/BSN generator
+  SSN <= SSN + 1 WHEN rising_edge(clk) AND pps_eop='1';              -- Seconds Sequence Number
+  BSN <= BSN + 1 WHEN rising_edge(clk) AND bsn_eop='1';              -- Block Sequence Number
+
+  proc_common_gen_pulse(1, g_pps_interval, '1', rst, clk, nxt_pps_sop);  -- make PPS grid with pps_sop at start of interval
+  pps_sop <= nxt_pps_sop AFTER c_clk_period;
+  pps_eop <= pps_sop'DELAYED((g_pps_interval-1)*c_clk_period);     -- make PPS grid with pps_eop at end of intervals
+  
+  proc_common_gen_pulse(1, g_block_size, '1', rst, clk, nxt_bsn_sop);    -- make BSN grid with bsn_sop at start of interval
+  bsn_sop <= nxt_bsn_sop AFTER c_clk_period;
+  bsn_eop <= bsn_sop'DELAYED((g_block_size-1)*c_clk_period);       -- make BSN grid with bsn_eop at end of interval
+ 
+  -- Define the expected sync that occurs when pps_sop = bsn sop, or else at the first bsn_sop after the pps_sop, see Figure 3.1 in [doc].
+  p_expected_sync : PROCESS
+  BEGIN
+    WAIT UNTIL rising_edge(clk);
+    expected_sync <= '0';
+    proc_common_wait_until_lo_hi(clk, pps_sop);
+    IF bsn_sop = '1' THEN
+      expected_sync <= '1';
+      expected_bsn <= BSN+1;
+      expected_offset_bsn <= 0;
+    ELSE
+      proc_common_wait_until_lo_hi(clk, bsn_sop);
+      expected_sync <= '1';
+      expected_bsn <= BSN+1;
+      expected_offset_bsn <= (BSN+1) * g_block_size - SSN * g_pps_interval;
+    END IF;
+  END PROCESS;
+  
+  expected_sync_dly <= expected_sync'DELAYED(c_dut_latency*c_clk_period);
+
   -- MM control
   p_mm : PROCESS
+    VARIABLE v_bsn_time_offset : NATURAL;
+    VARIABLE v_bsn_init        : NATURAL;
   BEGIN
     tb_end   <= '0';
     tb_state <= s_disable;
-    pps      <= '0';
+    --pps      <= '0';
 
     dp_on   <= '0';
     dp_on_pps  <= '0';
-    init_bsn <= TO_UVEC(g_sync_offset, c_bsn_w);
 
     -- Get synchronous to clk
     proc_common_wait_until_low(clk, rst);
     proc_common_wait_some_cycles(clk, 500);
 
-    -- Start by making dp_on high
-    tb_state <= s_start;
-    dp_on <= '1';
-    proc_common_wait_some_cycles(clk, 2000);
-
-    -- Stop by making dp_on low
-    tb_state <= s_disable;
-    dp_on <= '0';
-    proc_common_wait_some_cycles(clk, 1000);
-
-    -- Now start on PPS
-    tb_state <= s_pps_start;
-    dp_on_pps <= '1';
+    -- Start asynchronously by making dp_on high
+    proc_common_wait_until_hi_lo(clk, expected_sync);
+    tb_state  <= s_pps_start;
+    dp_on_pps <= '0';
     dp_on     <= '1';
-    proc_common_wait_some_cycles(clk, 10);
-    pps <= '1';
-    proc_common_wait_some_cycles(clk, 1);
-    pps <= '0';
-    proc_common_wait_some_cycles(clk, 1000);
-
-    -- Stop by making dp_on low
-    tb_state <= s_disable;
-    dp_on <= '0';
-    dp_on_pps <= '0'; --No PPS trigger next time
-    proc_common_wait_some_cycles(clk, 1000);
-
-    -- Start by making dp_on high
-    tb_state <= s_start;
-    dp_on <= '1';
-    proc_common_wait_some_cycles(clk, 2500);
-
+    verify_sync <= '0';  -- only verify visualy in wave window
+    proc_common_wait_some_cycles(clk, 10*g_pps_interval);
+    verify_sync <= '0';
     -- Stop by making dp_on low
     tb_state <= s_disable;
     dp_on <= '0';
     dp_on_pps <= '0';
-    proc_common_wait_some_cycles(clk, 1000);
-
-    -- Now start on next PPS and continue forever
-    init_bsn <= TO_UVEC(g_sync_offset, c_bsn_w);
-    tb_state <= s_pps_start;
-    dp_on_pps <= '1';
-    dp_on     <= '1';
-    proc_common_wait_some_cycles(clk, 20);
-    pps <= '1';
-    proc_common_wait_some_cycles(clk, 1);
-    pps <= '0';
-
+    proc_common_wait_some_cycles(clk, 3*g_pps_interval);
+
+    -- Start synchronously by making dp_on high at pps
+    FOR i IN 0 TO 2 LOOP
+      -- Now start on PPS
+      proc_common_wait_until_hi_lo(clk, expected_sync);
+      v_bsn_time_offset := ((SSN + 1) * g_pps_interval) MOD g_block_size;
+      v_bsn_init := ((SSN + 1) * g_pps_interval) / g_block_size;
+      IF v_bsn_time_offset = 0 THEN
+        bsn_init <= TO_UVEC(v_bsn_init, c_bsn_w); 
+      ELSE
+        bsn_init <= TO_UVEC(v_bsn_init+1, c_bsn_w); 
+      END IF;
+      tb_state  <= s_pps_start;
+      dp_on_pps <= '1';
+      dp_on     <= '1';
+      verify_sync <= '1';  -- verify automatically in test bench
+      proc_common_wait_some_cycles(clk, 10*g_pps_interval);
+      verify_sync <= '0';
+      -- Stop by making dp_on low
+      tb_state <= s_disable;
+      dp_on <= '0';
+      dp_on_pps <= '0';
+      proc_common_wait_some_cycles(clk, 3*g_pps_interval);
+    END LOOP;
 
-    proc_common_wait_some_cycles(clk, 10000);
     tb_end   <= '1';
     WAIT;
   END PROCESS;
@@ -157,7 +192,7 @@ BEGIN
   -- Verification
   -----------------------------------------------------------------------------
   proc_dp_verify_sop_and_eop(clk, bs_sosi.valid, bs_sosi.sop, bs_sosi.eop, hold_bs_sop);                        -- Verify that sop and eop come in pairs
-  proc_dp_verify_sync_v2(c_sync_period, g_sync_offset, clk, verify_sync, bs_sosi.sync, bs_sosi.sop, bs_sosi.bsn, tb_bsn_cnt);  -- Verify sync at sop and at expected BSN
+  proc_dp_verify_sync(clk, verify_sync, bs_sosi.sync, bs_sosi.sop, expected_sync_dly);  -- Verify sync at sop and at expected_sync
 
   -----------------------------------------------------------------------------
   -- DUT: dp_bsn_source_v2
@@ -165,18 +200,18 @@ BEGIN
 
   dut : ENTITY work.dp_bsn_source_v2
   GENERIC MAP (
-    g_block_size         => c_block_size,
-    g_nof_clk_per_sync   => g_clk_per_sync,
+    g_block_size         => g_block_size,
+    g_nof_clk_per_sync   => g_pps_interval,
     g_bsn_w              => c_bsn_w
   )
   PORT MAP (
     rst       => rst,
     clk       => clk,
-    pps       => pps,
+    pps       => pps_sop,
     -- MM control
     dp_on     => dp_on,
     dp_on_pps => dp_on_pps,
-    init_bsn  => init_bsn,
+    bsn_init  => bsn_init,
     -- Streaming
     src_out   => bs_sosi
   );
diff --git a/libraries/base/dp/tb/vhdl/tb_dp_pkg.vhd b/libraries/base/dp/tb/vhdl/tb_dp_pkg.vhd
index 4388148c87..381a32262b 100644
--- a/libraries/base/dp/tb/vhdl/tb_dp_pkg.vhd
+++ b/libraries/base/dp/tb/vhdl/tb_dp_pkg.vhd
@@ -466,6 +466,13 @@ PACKAGE tb_dp_pkg IS
                                 SIGNAL   sop           : IN    STD_LOGIC;
                                 SIGNAL   bsn           : IN    STD_LOGIC_VECTOR);
 
+-- Verify the DUT output sync
+  PROCEDURE proc_dp_verify_sync(SIGNAL   clk           : IN    STD_LOGIC;
+                                SIGNAL   verify_en     : IN    STD_LOGIC;
+                                SIGNAL   sync          : IN    STD_LOGIC;
+                                SIGNAL   sop           : IN    STD_LOGIC;
+                                SIGNAL   expected_sync : IN    STD_LOGIC);
+
   -- Verify the DUT output sync
   PROCEDURE proc_dp_verify_sync_v2(CONSTANT c_sync_period : IN    NATURAL;
                                    CONSTANT c_sync_offset : IN    NATURAL;
@@ -2233,6 +2240,35 @@ PACKAGE BODY tb_dp_pkg IS
   END proc_dp_verify_sync;
 
 
+  ------------------------------------------------------------------------------
+  -- PROCEDURE: Verify the DUT output sync
+  -- . sync is defined such that it can only be active at sop
+  ------------------------------------------------------------------------------
+  PROCEDURE proc_dp_verify_sync(SIGNAL   clk             : IN    STD_LOGIC;
+                                SIGNAL   verify_en       : IN    STD_LOGIC;
+                                SIGNAL   sync            : IN    STD_LOGIC;
+                                SIGNAL   sop             : IN    STD_LOGIC;
+                                SIGNAL   expected_sync   : IN    STD_LOGIC) IS
+  BEGIN
+    IF rising_edge(clk) THEN
+      IF verify_en='1' THEN
+        -- Check for unexpected sync
+        IF sync='1' THEN
+          ASSERT expected_sync='1'
+            REPORT "Error: Unexpected sync at BSN" SEVERITY ERROR;
+          ASSERT sop = '1'
+            REPORT "Error: Unexpected sync at inactive sop" SEVERITY ERROR;
+        END IF;
+        -- Check for missing sync
+        IF sop='1' AND expected_sync='1' THEN
+          ASSERT sync = '1'
+            REPORT "Error: Missing sync" SEVERITY ERROR;
+        END IF;
+      END IF;
+    END IF;
+  END proc_dp_verify_sync;
+
+
   ------------------------------------------------------------------------------
   -- PROCEDURE: Verify the DUT output sync
   -- . sync is defined such that it can only be active at sop
@@ -2248,24 +2284,24 @@ PACKAGE BODY tb_dp_pkg IS
                                    SIGNAL   tb_bsn_cnt      : INOUT INTEGER) IS
     CONSTANT c_bsn_w         : NATURAL := sel_a_b(bsn'LENGTH>31, 31, bsn'LENGTH);  -- use maximally 31 bit of BSN slv to allow calculations with integers
 
-    VARIABLE v_valid_sync_period : BOOLEAN;
-    VARIABLE v_tb_bsn_cnt        : INTEGER;
+    VARIABLE v_expected_sync : BOOLEAN;
+    VARIABLE v_tb_bsn_cnt    : INTEGER;
   BEGIN
     IF rising_edge(clk) THEN
       IF verify_en='1' THEN
+        -- Determine whether sync is expected at this bsn
 
-        v_valid_sync_period := FALSE;
+        v_expected_sync := FALSE;
         v_tb_bsn_cnt := tb_bsn_cnt;  -- assign signal to variable
 
         -- on sync check if tb_bsn_cnt is a valid value
         -- valid is c_sync_period or c_sync_period-1
         IF sync='1' THEN
           IF v_tb_bsn_cnt=c_sync_period OR v_tb_bsn_cnt=c_sync_period-1 THEN
-            v_valid_sync_period := TRUE;
+            v_expected_sync := TRUE;
             --REPORT "bsn count valid " & int_to_str(v_tb_bsn_cnt);
           ELSE
-            v_valid_sync_period := FALSE;
-            REPORT "bsn count not valid " & int_to_str(v_tb_bsn_cnt) SEVERITY ERROR;
+            v_expected_sync := FALSE;
           END IF;
 
           v_tb_bsn_cnt := 0;  -- reset tb_bsn_cnt
@@ -2285,13 +2321,13 @@ PACKAGE BODY tb_dp_pkg IS
 
         -- Check for unexpected sync
         IF sync='1' THEN
-          ASSERT v_valid_sync_period = TRUE
-            REPORT "Error: Unexpected sync at BSN" SEVERITY ERROR;
+          ASSERT v_expected_sync = TRUE
+            REPORT "Error: Unexpected BSN count " & int_to_str(v_tb_bsn_cnt) SEVERITY ERROR;
           ASSERT sop = '1'
             REPORT "Error: Unexpected sync at inactive sop" SEVERITY ERROR;
         END IF;
         -- Check for missing sync
-        IF sop='1' AND v_valid_sync_period=TRUE THEN
+        IF sop='1' AND v_expected_sync=TRUE THEN
           ASSERT sync = '1'
             REPORT "Error: Missing sync" SEVERITY ERROR;
         END IF;
diff --git a/libraries/base/dp/tb/vhdl/tb_mms_dp_bsn_source_v2.vhd b/libraries/base/dp/tb/vhdl/tb_mms_dp_bsn_source_v2.vhd
index 5984c4d6af..7d40dff868 100644
--- a/libraries/base/dp/tb/vhdl/tb_mms_dp_bsn_source_v2.vhd
+++ b/libraries/base/dp/tb/vhdl/tb_mms_dp_bsn_source_v2.vhd
@@ -52,7 +52,7 @@ ARCHITECTURE tb OF tb_mms_dp_bsn_source_v2 IS
   CONSTANT c_block_size                 : NATURAL := 100;
   CONSTANT c_nof_block_per_sync         : NATURAL := 15;
   CONSTANT c_sync_interval              : NATURAL := c_nof_block_per_sync * c_block_size;
-  CONSTANT c_init_bsn                   : NATURAL := c_nof_block_per_sync;
+  CONSTANT c_bsn_init                   : NATURAL := c_nof_block_per_sync;
     
   CONSTANT c_mm_addr_dp_on              : NATURAL := 0;
   CONSTANT c_mm_addr_nof_block_per_sync : NATURAL := 1;
@@ -90,7 +90,7 @@ BEGIN
      proc_common_wait_some_cycles(clk, 10);
 
      -- Write initial BSN and number of block per sync interval
-     proc_mem_mm_bus_wr(c_mm_addr_bsn_lo,                       c_init_bsn, clk, mm_miso, mm_mosi);
+     proc_mem_mm_bus_wr(c_mm_addr_bsn_lo,                       c_bsn_init, clk, mm_miso, mm_mosi);
      proc_mem_mm_bus_wr(c_mm_addr_bsn_hi,                                0, clk, mm_miso, mm_mosi);  -- must also write hi part to trigger transfer accross clock domain
      proc_mem_mm_bus_wr(c_mm_addr_nof_block_per_sync, c_nof_block_per_sync, clk, mm_miso, mm_mosi);
      proc_common_wait_some_cycles(clk, c_cross_clock_domain_latency);
diff --git a/libraries/base/dp/tb/vhdl/tb_tb_dp_bsn_source_v2.vhd b/libraries/base/dp/tb/vhdl/tb_tb_dp_bsn_source_v2.vhd
index d1c1641225..2e4e682cd0 100644
--- a/libraries/base/dp/tb/vhdl/tb_tb_dp_bsn_source_v2.vhd
+++ b/libraries/base/dp/tb/vhdl/tb_tb_dp_bsn_source_v2.vhd
@@ -35,6 +35,10 @@ END tb_tb_dp_bsn_source_v2;
 ARCHITECTURE tb OF tb_tb_dp_bsn_source_v2 IS
   SIGNAL tb_end : STD_LOGIC := '0';  -- declare tb_end to avoid 'No objects found' error on 'when -label tb_end'
 BEGIN
+  -- from tb_dp_bsn_source_v2.vhd
+  --
+  -- g_sync_offset  : NATURAL := 0  
+  -- g_clk_per_sync : NATURAL := 240
 
   --                                         (sync_offset, clk_per_sync)
   -- test different clk_per_sync
-- 
GitLab