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 7f15f845fc365470ac223203310aa98097df13eb..669522d47e037d52d3ec6f18bfedf652f93fc080 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
@@ -19,22 +19,28 @@
 --
 -------------------------------------------------------------------------------
 
--- Author: P. Donker
--- Verify if eop and sop come in pairs and if sync is at sop and at expected_sync puls.
--- The tb is using a SSN (second sample number) and BSN (block sample number) generator as reference
--- for the test, it uses g_pps_interval and g_block_size for generator timing settings.
--- Start/Stop BSN source tests:
--- 1) test 1x asynchronously (dp_on_pps='0') without automatic check, check visualy in wave window.
--- 2) test 3x synchronously (dp_on_pps='1') with automatic check.
+-- Author: P. Donker, E. Kooistra
+-- Purpose: Tb to verify that the BS source can be started in any PPS interval
+--          to create the BSN grid and sync interval as defined in Fig. 3.1 in
+--          [1].
+-- Decsription:
+-- * Start/Stop BSN source tests:
+--   1) test 1x asynchronously (dp_on_pps='0') without automatic check, check
+--      visualy in wave window.
+--   2) test 3x synchronously (dp_on_pps='1') with automatic check.
+-- . Verify if bs_sosi.eop and bs_sosi.sop come in pairs
+-- . Verify that bs_sosi.sync is at bs_sosi.sop
+-- . Verify that bs_sosi has fixed latency with respect to ref_grid
+--
+-- References:
+-- [1] https://support.astron.nl/confluence/display/L2M/L2+STAT+Decision%3A+Timing+in+Station
+-- [2] https://support.astron.nl/confluence/display/L2M/L6+FWLIB+Design+Document%3A+BSN+source+with+offset
 --
--- [doc] = https://support.astron.nl/confluence/display/L2M/L6+FWLIB+Design+Document%3A+BSN+source+with+offset
-
 -- Usage:
 -- > as 10
 -- > run -all
 -- . sop, eop are verified automatically
--- . sync and bsn are verified automatically
--- and then manually verify on/off in Wave window
+-- . sync and bsn are verified automatically using the ref_grid
 
 LIBRARY IEEE, common_lib, dp_lib;
 USE IEEE.STD_LOGIC_1164.ALL;
@@ -46,193 +52,196 @@ USE dp_lib.tb_dp_pkg.ALL;
 
 ENTITY tb_dp_bsn_source_v2 IS
   GENERIC (
-    g_nof_pps      : NATURAL := 20;
-    g_pps_interval : NATURAL := 230;
-    g_block_size   : NATURAL := 32 
+    g_nof_pps      : NATURAL := 10;
+    g_pps_interval : NATURAL := 10; --101;
+    g_block_size   : NATURAL := 7 --23
   );
 END tb_dp_bsn_source_v2;
 
 ARCHITECTURE tb OF tb_dp_bsn_source_v2 IS
 
-  CONSTANT c_clk_period   : TIME    := 10 ns;
-  CONSTANT c_bsn_w        : NATURAL := 31;
-  CONSTANT c_dut_latency  : NATURAL := 2;
+  CONSTANT c_nof_repeat        : NATURAL := 3;
+
+  CONSTANT c_clk_period        : TIME    := 10 ns;
+  CONSTANT c_bsn_w             : NATURAL := 31;
+  CONSTANT c_bsn_time_offset_w : NATURAL := ceil_log2(g_block_size);
+
+  -- Minimum latency between sync and PPS, due to logic in DUT
+  CONSTANT c_dut_latency       : NATURAL := 3;
 
   -- The state name tells what kind of test is being done
   TYPE t_state_enum IS (
     s_disable,
-    s_start,
-    s_pps_start
+    s_dp_on,
+    s_dp_on_pps
   );
 
-  SIGNAL tb_state     : t_state_enum;
+  -- Define the PPS (SSN) and BSN grid that both start at 0 according to Figure 3.1 in [1]:
+  TYPE t_time_grid IS RECORD
+    pps  : STD_LOGIC;  -- pulse per second, g_pps_interval clk per pps interval
+    ssn  : NATURAL;  -- seconds sequence number
+    bsn  : NATURAL;  -- block sequence number, g_block_size clk per block
+    sync : STD_LOGIC;  -- active at sop when pps is active or was active
+    sop  : STD_LOGIC;   -- start of block
+    eop  : STD_LOGIC;  -- end of block
+  END RECORD;
 
+  CONSTANT c_time_grid_rst : t_time_grid := ('0', 0, 0, '0', '0', '0');
+
+  -- Reference grid
+  SIGNAL ref_grid        : t_time_grid := c_time_grid_rst;
+  SIGNAL ssn_eop         : STD_LOGIC := '0';
+  SIGNAL hold_pps        : STD_LOGIC := '0';
+  SIGNAL nxt_hold_pps    : STD_LOGIC := '0';
+
+  -- Tb
   SIGNAL tb_end       : STD_LOGIC := '0';
   SIGNAL rst          : STD_LOGIC := '1';
   SIGNAL clk          : STD_LOGIC := '1';
+  SIGNAL tb_state        : t_state_enum := s_disable;
 
   -- DUT
-  SIGNAL dp_on        : STD_LOGIC := '0';
-  SIGNAL dp_on_pps    : STD_LOGIC := '0';
-  SIGNAL bsn_init     : STD_LOGIC_VECTOR(c_bsn_w-1 DOWNTO 0) := (OTHERS=>'0');
-
-  SIGNAL bs_sosi      : t_dp_sosi;
+  SIGNAL dp_on           : STD_LOGIC := '0';
+  SIGNAL dp_on_pps       : STD_LOGIC := '0';
+  SIGNAL dp_on_status    : STD_LOGIC;
+  SIGNAL bs_restart      : STD_LOGIC;
+  SIGNAL bsn_init        : STD_LOGIC_VECTOR(c_bsn_w-1 DOWNTO 0) := (OTHERS=>'0');
+  SIGNAL bsn_time_offset : STD_LOGIC_VECTOR(c_bsn_time_offset_w-1 DOWNTO 0) := (OTHERS=>'0');
+  SIGNAL bs_sosi         : t_dp_sosi;
 
   -- Verify
-  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;
-  SIGNAL dbg_nof_blk         : NATURAL   := 0;
-  SIGNAL dbg_accumulate      : NATURAL   := 0;
-  SIGNAL dbg_expected_bsn    : NATURAL   := 0;
+  SIGNAL exp_grid           : t_time_grid;
+  SIGNAL unexpected_bs_sync : STD_LOGIC;
+  SIGNAL sl0                : STD_LOGIC := '0';
+  SIGNAL verify_en          : STD_LOGIC := '0';
+  SIGNAL verify_sync        : STD_LOGIC := '0';
+  SIGNAL hold_bs_sop        : STD_LOGIC;
+  SIGNAL prev_bs_valid      : STD_LOGIC;
+  SIGNAL bs_starts_cnt      : NATURAL := 0;
+
+  SIGNAL dbg_nof_blk        : NATURAL;
+  SIGNAL dbg_accumulate     : NATURAL;
+  SIGNAL dbg_expected_bsn   : NATURAL;
 
 BEGIN
 
-  -----------------------------------------------------------------------------
-  -- Stimuli
-  -----------------------------------------------------------------------------
   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
+  -----------------------------------------------------------------------------
+  -- Generate reference time grid
+  -----------------------------------------------------------------------------
+  proc_common_gen_pulse(1, g_pps_interval, '1', sl0, clk, ref_grid.pps);
+  proc_common_gen_pulse(1, g_block_size, '1', sl0, clk, ref_grid.sop);
+  ref_grid.eop <= ref_grid.sop'DELAYED((g_block_size - 1) * c_clk_period);
+  ssn_eop <= ref_grid.pps'DELAYED((g_pps_interval - 1) * c_clk_period);
+  ref_grid.ssn <= ref_grid.ssn + 1 WHEN rising_edge(clk) AND ssn_eop = '1';
+  ref_grid.bsn <= ref_grid.bsn + 1 WHEN rising_edge(clk) AND ref_grid.eop = '1';
+
+  -- Issue sync at start of block
+  p_ref_grid_sync : PROCESS(ref_grid, hold_pps)
   BEGIN
-    WAIT UNTIL rising_edge(clk);
-    expected_sync <= '0';
-    proc_common_wait_until_high(clk, pps_sop);
-    IF bsn_sop = '1' THEN
-      expected_sync <= '1';
-      expected_bsn <= BSN+1;
-      expected_offset_bsn <= 0;
-    ELSE
-      proc_common_wait_until_high(clk, bsn_sop);
-      expected_sync <= '1';
-      expected_bsn <= BSN+1;
-      expected_offset_bsn <= (BSN+1) * g_block_size - SSN * g_pps_interval;
+    ref_grid.sync <= '0';
+    nxt_hold_pps <= hold_pps;
+
+    IF ref_grid.pps = '1' THEN
+      IF ref_grid.sop = '1' THEN
+        ref_grid.sync <= '1';  -- immediately issue sync
+      ELSE
+        nxt_hold_pps <= '1';  -- wait until next block
+      END IF;
+    END IF;
+
+    IF hold_pps = '1' THEN
+      IF ref_grid.sop = '1' THEN
+        ref_grid.sync <= '1';  -- issue pending sync
+        nxt_hold_pps <= '0';
+      END IF;
     END IF;
   END PROCESS;
-  
-  expected_sync_dly <= expected_sync'DELAYED(c_dut_latency*c_clk_period);
 
-  -- MM control
+  hold_pps <= nxt_hold_pps WHEN rising_edge(clk);
+
+  exp_grid <= ref_grid'DELAYED(c_dut_latency * c_clk_period);
+
+  -----------------------------------------------------------------------------
+  -- Stimuli
+  -----------------------------------------------------------------------------
   p_mm : PROCESS
-    VARIABLE v_bsn_time_offset : NATURAL;
+    VARIABLE v_ssn             : NATURAL;
     VARIABLE v_bsn_init        : NATURAL;
+    VARIABLE v_bsn_time_offset : NATURAL;
   BEGIN
-    tb_end   <= '0';
-    tb_state <= s_disable;
-    --pps      <= '0';
-
-    dp_on   <= '0';
-    dp_on_pps  <= '0';
-
     -- Get synchronous to clk
     proc_common_wait_until_low(clk, rst);
-    proc_common_wait_some_cycles(clk, 500);
+    proc_common_wait_some_cycles(clk, 10);
 
     -- Start asynchronously by making dp_on high
-    proc_common_wait_until_high(clk, expected_sync_dly);
-    tb_state  <= s_pps_start;
+    verify_en <= '0';  -- only verify visualy in wave window
+    tb_state <= s_dp_on;
     dp_on_pps <= '0';
-    dp_on     <= '1';
-    verify_sync <= '0';  -- only verify visualy in wave window
+    dp_on <= '1';
     proc_common_wait_some_cycles(clk, g_nof_pps*g_pps_interval);
-    verify_sync <= '0';
-    -- Stop by making dp_on low
     tb_state <= s_disable;
     dp_on <= '0';
     dp_on_pps <= '0';
-    
-    -- wait until one pps_interval before next begin of SSN generator (pps_sop = bsn_sop)    
-    proc_common_wait_until_high(clk, pps_sop);
-    v_bsn_time_offset := ((SSN + 2) * g_pps_interval) MOD g_block_size;
-    WHILE v_bsn_time_offset > 0 LOOP
-      proc_common_wait_some_cycles(clk, g_pps_interval);
-      v_bsn_time_offset := ((SSN + 2) * g_pps_interval) MOD g_block_size;
-    END LOOP;
+    proc_common_wait_some_cycles(clk, 10);
 
-    -- Start synchronously by making dp_on high at pps
-    FOR i IN 0 TO 2 LOOP
-      -- Now start on PPS
-      proc_common_wait_until_high(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;
+    -- Start synchronously by making dp_on and dp_on_pps high
+    verify_en <= '1';  -- verify automatically in test bench
+
+    FOR I IN 0 TO c_nof_repeat-1 LOOP
+      -- Wait some variable time between tests, to enforce testing different
+      -- bsn_time_offset values
+      proc_common_wait_some_cycles(clk, 20);
+      proc_common_wait_some_cycles(clk, I*g_pps_interval);
+
+      -- Wait until in the beginning of PPS interval
+      proc_common_wait_until_hi_lo(clk, ref_grid.pps);
+      proc_common_wait_some_cycles(clk, c_dut_latency);
+
+      -- Determine bsn_init and bsn_time_offset for BSN source start
+      -- . bsn_init = BSN at sync
+      -- . bsn_time_offset = number of clk that sync occurs after PPS
+      v_ssn := ref_grid.ssn + 1;  -- +1 to prepare start in next PPS interval
+      v_bsn_init := ceil_div(v_SSN * g_pps_interval, g_block_size);  -- Equation 3.6 in [1]
+      v_bsn_time_offset := v_bsn_init * g_block_size - v_SSN * g_pps_interval;  -- Equation 3.7 in [1]
+      bsn_init <= TO_UVEC(v_bsn_init, c_bsn_w);  --
+      bsn_time_offset <= TO_UVEC(v_bsn_time_offset, c_bsn_time_offset_w);
+      -- Start synchronously by making dp_on and dp_on_pps high
+      tb_state  <= s_dp_on_pps;
       dp_on_pps <= '1';
-      dp_on     <= '1';
-      verify_sync <= '1';  -- verify automatically in test bench
+      dp_on <= '1';
       proc_common_wait_some_cycles(clk, g_nof_pps*g_pps_interval);
-      verify_sync <= '0';
-      -- Stop by making dp_on low
       tb_state <= s_disable;
       dp_on <= '0';
       dp_on_pps <= '0';
-      
-      -- wait until one pps_interval before next begin of SSN generator (pps_sop = bsn_sop)    
-      proc_common_wait_until_high(clk, pps_sop);
-      v_bsn_time_offset := ((SSN + 2) * g_pps_interval) MOD g_block_size;
-      WHILE v_bsn_time_offset > 0 LOOP
-        proc_common_wait_some_cycles(clk, g_pps_interval);
-        v_bsn_time_offset := ((SSN + 2) * g_pps_interval) MOD g_block_size;
-      END LOOP;
-
     END LOOP;
 
-    tb_end   <= '1';
+    proc_common_wait_some_cycles(clk, 10);
+    ASSERT bs_starts_cnt = 1 + c_nof_repeat REPORT "Wrong number of BSN source starts." SEVERITY ERROR;
+
+    tb_end <= '1';
     WAIT;
   END PROCESS;
 
 
   -----------------------------------------------------------------------------
   -- Verification
+  -- . Some aspects of bs_sosi are verified multiple times in different ways,
+  --   this overlap is fine, because the tb and DUT are rather complicated, so
+  --   using different approaches also helpt to verify the tb itself.
   -----------------------------------------------------------------------------
+  verify_sync <= verify_en AND bs_sosi.valid;
+
   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(clk, verify_sync, bs_sosi.sync, bs_sosi.sop, expected_sync_dly);  -- Verify sync at sop and at expected_sync
-
-  -- Verify sync at sop and at expected_sync again:
-  -- . now using the proc_dp_verify_sync() variant for dp_bsn_source_v2 that
-  --   can verify fractional sync periods.
-  -- . the proc_dp_verify_sync() v2 variant was made later, so in fact
-  --   this tb_dp_bsn_source_v2 verifies this new v2 procedure.
-  proc_dp_verify_sync(TO_UINT(bsn_init),
-                      g_pps_interval,
+  --proc_dp_verify_sync(clk, verify_sync, bs_sosi.sync, exp_grid.sop, exp_grid.sync);  -- Verify sync at sop and at expected_sync
+
+  -- Verify sync at sop and at expected_sync
+  proc_dp_verify_sync(g_pps_interval,
                       g_block_size,
                       clk,
-                      verify_sync,
+                      verify_en,
                       bs_sosi.sync,
                       bs_sosi.sop,
                       bs_sosi.bsn,
@@ -240,6 +249,28 @@ BEGIN
                       dbg_accumulate,
                       dbg_expected_bsn);
 
+  -- Verify bs_sosi by comparing with exp_grid, this again verifies bs_sosi.sync, sop and bsn
+  p_verify_bs_sosi_grid : PROCESS(clk)
+  BEGIN
+    IF rising_edge(clk) THEN
+      unexpected_bs_sync <= '0';
+      IF verify_en = '1' AND bs_sosi.valid = '1' THEN
+        ASSERT TO_UINT(bs_sosi.bsn) = exp_grid.bsn REPORT "Wrong bs_sosi.bsn /= exp_grid.bsn" SEVERITY ERROR;
+        ASSERT bs_sosi.sync = exp_grid.sync REPORT "Wrong bs_sosi.sync /= exp_grid.sync" SEVERITY ERROR;
+        ASSERT bs_sosi.sop = exp_grid.sop REPORT "Wrong bs_sosi.sop /= exp_grid.sop" SEVERITY ERROR;
+        ASSERT bs_sosi.eop = exp_grid.eop REPORT "Wrong bs_sosi.eop /= exp_grid.eop" SEVERITY ERROR;
+        -- Mark error in Wave window
+        IF bs_sosi.sync = '1' AND bs_sosi.sync /= exp_grid.sync THEN
+          unexpected_bs_sync <= '1';
+        END IF;
+      END IF;
+    END IF;
+  END PROCESS;
+
+  -- Verify that bs_sosi.valid = '1' did happen after dp_on
+  prev_bs_valid <= bs_sosi.valid WHEN rising_edge(clk);
+  bs_starts_cnt <= bs_starts_cnt + 1 WHEN rising_edge(clk) AND bs_sosi.valid = '1' AND prev_bs_valid = '0';
+
   -----------------------------------------------------------------------------
   -- DUT: dp_bsn_source_v2
   -----------------------------------------------------------------------------
@@ -248,18 +279,25 @@ BEGIN
   GENERIC MAP (
     g_block_size         => g_block_size,
     g_nof_clk_per_sync   => g_pps_interval,
-    g_bsn_w              => c_bsn_w
+    g_bsn_w              => c_bsn_w,
+    g_bsn_time_offset_w  => c_bsn_time_offset_w
   )
   PORT MAP (
-    rst       => rst,
-    clk       => clk,
-    pps       => pps_sop,
+    rst              => rst,
+    clk              => clk,
+    pps              => ref_grid.pps,
     -- MM control
-    dp_on     => dp_on,
-    dp_on_pps => dp_on_pps,
-    bsn_init  => bsn_init,
+    dp_on            => dp_on,
+    dp_on_pps        => dp_on_pps,
+
+    dp_on_status     => dp_on_status,  -- = src_out.valid
+    bs_restart       => bs_restart,    -- = src_out.sop for first sop after dp_on went high
+
+    bsn_init         => bsn_init,
+    bsn_time_offset  => bsn_time_offset,
+
     -- Streaming
-    src_out   => bs_sosi
+    src_out          => bs_sosi
   );
 
 END tb;