diff --git a/libraries/base/dp/dp.peripheral.yaml b/libraries/base/dp/dp.peripheral.yaml
index 74d172965d295f2123617941affb695757951ee7..6d38ee172529145bc9e302121ef92abc0b6b0f41 100644
--- a/libraries/base/dp/dp.peripheral.yaml
+++ b/libraries/base/dp/dp.peripheral.yaml
@@ -442,6 +442,31 @@ peripherals:
               access_mode: RW
 
 
+  - peripheral_name: dp_strobe_total_count
+    peripheral_description: "Count strobes"
+    parameters:
+      - { name: g_nof_counts_max, value: 15 }  # fixed by REGMAP
+      - { name: g_nof_counts, value: 1 }  # actual nof counts, <= g_nof_counts_max
+    mm_ports:
+      # MM port for dp_strobe_total_count.vhd
+      - mm_port_name: REG_DP_STROBE_TOTAL_COUNT
+        mm_port_type: REG
+        mm_port_span: ceil_pow2(g_nof_counts_max*2 + 1) * MM_BUS_SIZE
+        mm_port_description: ""
+        fields:
+          - - field_name: counts
+              field_description: "Total number of strobes counters."
+              number_of_fields: g_nof_counts
+              address_offset: 0
+              user_width: 64
+              radix: uint64
+              access_mode: RO
+          - - field_name: clear
+              field_description: "Read or write this register to clear all counters."
+              address_offset: (g_nof_counts_max*2 + 1) * MM_BUS_SIZE  # 31 * MM_BUS_SIZE
+              access_mode: RW
+
+
   - peripheral_name: dp_block_validate_err    # pi_dp_block_validate_err.py
     peripheral_description: "Validate the error field of a DP block"
     parameters:
diff --git a/libraries/base/dp/hdllib.cfg b/libraries/base/dp/hdllib.cfg
index 9b765dc7bd6f22a9238a3c2cd224115d94b1e1c4..db5cbc473d90fa0409bb0d748cd84ce3f2d2e370 100644
--- a/libraries/base/dp/hdllib.cfg
+++ b/libraries/base/dp/hdllib.cfg
@@ -63,6 +63,7 @@ synth_files =
     src/vhdl/dp_fifo_from_mm_reg.vhd
     src/vhdl/dp_fifo_monitor.vhd
     src/vhdl/dp_fifo_monitor_arr.vhd
+    src/vhdl/dp_strobe_total_count.vhd
     src/vhdl/dp_block_validate_err.vhd
     src/vhdl/mms_dp_fifo_to_mm.vhd
     src/vhdl/mms_dp_fifo_from_mm.vhd
@@ -186,8 +187,6 @@ synth_files =
     src/vhdl/dp_selector.vhd
     src/vhdl/mms_dp_scale.vhd
     
-    
-    
     tb/vhdl/dp_stream_player.vhd
     tb/vhdl/dp_sosi_recorder.vhd
     tb/vhdl/dp_stream_rec_play.vhd
@@ -201,6 +200,7 @@ test_bench_files =
     tb/vhdl/dp_stream_stimuli.vhd
     tb/vhdl/dp_stream_verify.vhd
     
+    tb/vhdl/tb_dp_strobe_total_count.vhd
     tb/vhdl/tb_dp_block_select.vhd
     tb/vhdl/tb_dp_block_validate_length.vhd
     tb/vhdl/tb_dp_block_validate_err.vhd
@@ -286,8 +286,8 @@ test_bench_files =
     tb/vhdl/tb_mms_dp_force_data_serial_arr.vhd
     tb/vhdl/tb_mms_dp_gain_arr.vhd
     tb/vhdl/tb_mms_dp_gain_serial_arr.vhd
-    
 
+    tb/vhdl/tb_tb_dp_strobe_total_count.vhd
     tb/vhdl/tb_tb_dp_block_select.vhd
     tb/vhdl/tb_tb_dp_block_validate_length.vhd
     tb/vhdl/tb_tb_dp_block_validate_err.vhd
diff --git a/libraries/base/dp/src/vhdl/dp_block_validate_err.vhd b/libraries/base/dp/src/vhdl/dp_block_validate_err.vhd
index fc6371e48c42cde1980a574cb24b7dea68c13d91..a7e549c4b8a12bacb3932f9764817b5a579258e0 100644
--- a/libraries/base/dp/src/vhdl/dp_block_validate_err.vhd
+++ b/libraries/base/dp/src/vhdl/dp_block_validate_err.vhd
@@ -261,7 +261,7 @@ BEGIN
 
   count_reg((g_nof_err_counts+1) * c_word_w - 1 DOWNTO g_nof_err_counts * c_word_w ) <= RESIZE_UVEC(hold_cnt_discarded, c_word_w);
 
-  gen_blk_cnt_32b : IF g_blk_cnt_w < c_word_w GENERATE
+  gen_blk_cnt_32b : IF g_blk_cnt_w <= c_word_w GENERATE
     count_reg((g_nof_err_counts+2) * c_word_w - 1 DOWNTO (g_nof_err_counts+1) * c_word_w ) <= RESIZE_UVEC(hold_cnt_blk, c_word_w);  -- low part
     count_reg((g_nof_err_counts+3) * c_word_w - 1 DOWNTO (g_nof_err_counts+2) * c_word_w ) <= (OTHERS=>'0');  -- high part (not used)
   END GENERATE;
diff --git a/libraries/base/dp/src/vhdl/dp_strobe_total_count.vhd b/libraries/base/dp/src/vhdl/dp_strobe_total_count.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..19c033c715a2f338236f57fe02356754f8ac4aa5
--- /dev/null
+++ b/libraries/base/dp/src/vhdl/dp_strobe_total_count.vhd
@@ -0,0 +1,215 @@
+-------------------------------------------------------------------------------
+--
+-- Copyright 2022
+-- 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: E. Kooistra
+-- Purpose:
+--   Count strobes
+-- Description:
+-- * g_nof_counts >= 1, maximum g_nof_counts_max = 15
+--   There are g_nof_counts in parallel, one clear that clears them all
+--   . count any strobe like e.g. sync, sop, valid, error flag, ...
+--   . MM read or write of clear registers clears all counter immediately,
+--     the clear data value is dont care.
+--   . the count clips at 2**g_count_w-1 in case of overflow when g_clip =
+--     TRUE, else it wraps and continues from 0.
+-- * g_count_w <= 64
+--   Internally the counts have width g_count_w <= 64, on the MM interface
+--   all counts use 2 words, so 64 bits.
+-- * ref_sync:
+--   . Enable or re-enable count starts at a ref_sync.
+--   . MM read of a count shows the strobe count that is captured at a ref_sync
+--    (default input ref_sync = '1' when not used)
+-- * g_mm_w = c_word_w
+--   Default use g_mm_w = 32b for MM, but support < 32 to ease verification of
+--   count values > 2**g_mm_w.
+--
+-------------------------------------------------------------------------------
+-- REGMAP
+-- . address span is (g_nof_counts_max + 1)*2 = 32
+-------------------------------------------------------------------------------
+--  wi                          Bits    R/W Name                        Default
+--  ===========================================================================
+--  0                           [31..0] RO  count[0]                    0x0
+--  1                           [63.32]
+--  2                           [31..0] RO  count[1]                    0x0
+--  3                           [63.32]
+--  .                            .      .   .                           .
+--  .                            .
+--  (g_nof_counts-1)*2          [31..0] RO  count[g_nof_counts-1]       0x0
+--  (g_nof_counts-1)*2 + 1      [63.32]
+--  .                            .      .   .                           .
+--  .                            .
+--  (g_nof_counts_max-1)*2      [31..0] RO  count[g_nof_counts_max-1]   0x0
+--  (g_nof_counts_max-1)*2 + 1  [63.32]
+--  g_nof_counts_max*2          [31..0] RW  clear                       0x0
+--  g_nof_counts_max*2 + 1      [31..0] RO  rsvd                        0x0
+--  ===========================================================================
+--
+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;
+
+ENTITY dp_strobe_total_count IS
+  GENERIC (
+    g_mm_w           : NATURAL := c_word_w;
+    g_nof_counts_max : NATURAL := 15;  -- fixed by REGMAP
+    g_nof_counts     : NATURAL := 1;  -- actual nof counts, <= g_nof_counts_max
+    g_count_w        : NATURAL := c_longword_w;  -- actual count width, max is c_longword_w due to two mm word width
+    g_clip           : BOOLEAN := TRUE
+  );
+  PORT (
+    dp_rst        : IN STD_LOGIC;
+    dp_clk        : IN STD_LOGIC;
+
+    ref_sync      : IN STD_LOGIC := '1';
+    in_strobe_arr : IN STD_LOGIC_VECTOR(g_nof_counts-1 DOWNTO 0);
+
+    mm_rst        : IN STD_LOGIC;
+    mm_clk        : IN STD_LOGIC;
+
+    reg_mosi      : IN t_mem_mosi := c_mem_mosi_rst;
+    reg_miso      : OUT t_mem_miso
+  );
+END dp_strobe_total_count;
+
+ARCHITECTURE rtl OF dp_strobe_total_count IS
+
+  CONSTANT c_nof_words      : NATURAL := g_nof_counts_max*2 + 1;  -- +1 for clear
+  CONSTANT c_clear_adr      : NATURAL := g_nof_counts_max*2;  -- after counters in REGMAP
+
+  -- Define the size of the MM slave register
+  CONSTANT c_mm_reg : t_c_mem := (latency  => 1,
+                                  adr_w    => ceil_log2(c_nof_words),
+                                  dat_w    => g_mm_w,  -- Use MM bus data width = c_word_w = 32 for all MM registers
+                                  nof_dat  => c_nof_words,
+                                  init_sl  => '0');
+
+  TYPE t_cnt_arr IS ARRAY (INTEGER RANGE <>) OF STD_LOGIC_VECTOR(g_count_w-1 DOWNTO 0);
+
+  -- Registers in dp_clk domain
+  SIGNAL ref_sync_reg      : STD_LOGIC := '0';
+  SIGNAL in_strobe_reg_arr : STD_LOGIC_VECTOR(g_nof_counts-1 DOWNTO 0) := (OTHERS=>'0');
+  SIGNAL rd_reg            : STD_LOGIC_VECTOR(c_mm_reg.nof_dat*c_mm_reg.dat_w-1 DOWNTO 0) := (OTHERS=>'0');
+  SIGNAL mm_cnt_clr        : STD_LOGIC;
+  SIGNAL cnt_clr           : STD_LOGIC;
+  SIGNAL cnt_en            : STD_LOGIC := '0';
+  SIGNAL cnt_en_arr        : STD_LOGIC_VECTOR(g_nof_counts-1 DOWNTO 0);
+  SIGNAL cnt_arr           : t_cnt_arr(g_nof_counts-1 DOWNTO 0);
+  SIGNAL hold_cnt_arr      : t_cnt_arr(g_nof_counts-1 DOWNTO 0) := (OTHERS=>(OTHERS=>'0'));
+  
+BEGIN
+ 
+  ASSERT g_nof_counts <= g_nof_counts_max REPORT "Too many counters to fit REGMAP." SEVERITY FAILURE;
+  ASSERT g_count_w <= g_mm_w*2 REPORT "Too wide counter to fit REGMAP." SEVERITY FAILURE;
+
+  mm_cnt_clr <= (reg_mosi.rd OR reg_mosi.wr) WHEN TO_UINT(reg_mosi.address(c_mm_reg.adr_w-1 DOWNTO 0)) = c_clear_adr ELSE '0' ;
+
+  u_common_spulse : ENTITY common_lib.common_spulse
+    PORT MAP (
+      in_rst    => mm_rst,
+      in_clk    => mm_clk,
+      in_pulse  => mm_cnt_clr,
+      out_rst   => dp_rst,
+      out_clk   => dp_clk,
+      out_pulse => cnt_clr
+    );
+
+  -- . register ref_sync to ease timing closure for ref_sync fanout
+  ref_sync_reg <= ref_sync WHEN rising_edge(dp_clk);
+
+  -- . register in_strobe_arr to preserve alignment with ref_sync
+  in_strobe_reg_arr <= in_strobe_arr WHEN rising_edge(dp_clk);
+
+  -- . clear strobe counters immediately at cnt_clr
+  -- . start strobe counters after ref_sync, e.g. to align strobe counters in different nodes in
+  --   case the input was (already) active during the cnt_clr
+  cnt_en <= '0' WHEN cnt_clr = '1' ELSE '1' WHEN ref_sync_reg = '1' ELSE cnt_en;
+
+  -- strobe counters
+  gen_counters : FOR I IN 0 TO g_nof_counts-1 GENERATE
+    cnt_en_arr(I) <= cnt_en AND in_strobe_reg_arr(I);
+
+    u_counter : ENTITY common_lib.common_counter
+    GENERIC MAP (
+      g_width => g_count_w,
+      g_clip  => g_clip
+    )
+    PORT MAP (
+      rst => dp_rst,
+      clk => dp_clk,
+
+      cnt_clr => cnt_clr,
+      cnt_en  => cnt_en_arr(I),
+      count   => cnt_arr(I)
+    );
+  END GENERATE;
+
+  -- Hold counter values at ref_sync_reg to have stable values for MM read for comparision between nodes
+  p_hold_counters : PROCESS(dp_clk)
+  BEGIN
+    IF rising_edge(dp_clk) THEN
+      IF cnt_clr = '1' THEN
+        hold_cnt_arr <= (OTHERS=>(OTHERS=>'0'));
+      ELSIF ref_sync_reg = '1' THEN
+        hold_cnt_arr <= cnt_arr;
+      END IF;
+    END IF;
+  END PROCESS;
+
+  -- Register mapping
+  gen_cnt : FOR I IN 0 TO g_nof_counts-1 GENERATE
+    gen_reg_32b : IF g_count_w <= g_mm_w GENERATE
+      rd_reg((2*I + 1) * g_mm_w - 1 DOWNTO (2*I + 0) * g_mm_w) <= RESIZE_UVEC(hold_cnt_arr(I), g_mm_w);  -- low part
+      rd_reg((2*I + 2) * g_mm_w - 1 DOWNTO (2*I + 1) * g_mm_w) <= (OTHERS=>'0');  -- high part (not used)
+    END GENERATE;
+    gen_reg_64b : IF g_count_w > g_mm_w GENERATE
+      rd_reg((2*I + 1) * g_mm_w - 1 DOWNTO (2*I + 0) * g_mm_w) <= hold_cnt_arr(I)(g_mm_w-1 DOWNTO 0);  -- low part
+      rd_reg((2*I + 2) * g_mm_w - 1 DOWNTO (2*I + 1) * g_mm_w) <= RESIZE_UVEC(hold_cnt_arr(I)(g_count_w-1 DOWNTO g_mm_w), g_mm_w);  -- high part
+    END GENERATE;
+  END GENERATE;
+
+  u_reg : ENTITY common_lib.common_reg_r_w_dc
+  GENERIC MAP (
+    g_cross_clock_domain => TRUE,
+    g_readback           => FALSE,
+    g_reg                => c_mm_reg
+  )
+  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,
+    sla_out     => reg_miso,
+    
+    -- MM registers in st_clk domain
+    reg_wr_arr  => OPEN,
+    reg_rd_arr  => OPEN,
+    in_reg      => rd_reg,  -- read only
+    out_reg     => OPEN     -- no write
+  );
+  
+END rtl;
diff --git a/libraries/base/dp/tb/vhdl/tb_dp_block_validate_err.vhd b/libraries/base/dp/tb/vhdl/tb_dp_block_validate_err.vhd
index fe42dfd3e3b166855f7f7b010564e46a73c8dc6c..28a7f82ed29d03426177bf249443fe0149150c4c 100644
--- a/libraries/base/dp/tb/vhdl/tb_dp_block_validate_err.vhd
+++ b/libraries/base/dp/tb/vhdl/tb_dp_block_validate_err.vhd
@@ -86,14 +86,14 @@ ARCHITECTURE tb OF tb_dp_block_validate_err IS
   SIGNAL stimuli_end       : STD_LOGIC;
   SIGNAL stimuli_sosi      : t_dp_sosi;
   SIGNAL stimuli_siso      : t_dp_siso;
-  SIGNAL stimuli_cnt_reg   : NATURAL;
-  SIGNAL stimuli_cnt       : NATURAL;
+
   SIGNAL verify_sosi       : t_dp_sosi;
   SIGNAL verify_siso       : t_dp_siso := c_dp_siso_rdy;
   SIGNAL reference_cnt     : NATURAL;
   SIGNAL reference_cnt_reg : NATURAL;
   SIGNAL reference_sosi    : t_dp_sosi;
   SIGNAL reference_siso    : t_dp_siso := c_dp_siso_rdy;
+
   SIGNAL reg_mosi          : t_mem_mosi := c_mem_mosi_rst;
   SIGNAL reg_miso          : t_mem_miso := c_mem_miso_rst;
 
diff --git a/libraries/base/dp/tb/vhdl/tb_dp_strobe_total_count.vhd b/libraries/base/dp/tb/vhdl/tb_dp_strobe_total_count.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..24f22387fdcd454352a37f80ca0b964ae7e47553
--- /dev/null
+++ b/libraries/base/dp/tb/vhdl/tb_dp_strobe_total_count.vhd
@@ -0,0 +1,202 @@
+-------------------------------------------------------------------------------
+--
+-- Copyright 2022
+-- 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: E. Kooistra
+-- Purpose: Test bench for dp_strobe_total_count.vhd
+-- Description:
+-- * maximum g_count_w = 31 to fit in largest NATURAL
+-- * Use g_mm_w < c_word_w = 32 to simulate large counts in feasible time.
+-- * Use g_nof_sync in combination with g_mm_w and g_count_w to achieve
+--   . a count > 2**g_mm_w that uses the high part of an MM word
+--   . a count > 2**(g_mm_w*2) that will clip at 2**g_mm_w - 1
+-- Usage:
+-- . as 5
+-- . run -all
+
+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 common_lib.tb_common_mem_pkg.ALL;
+USE common_lib.common_str_pkg.ALL;
+USE common_lib.tb_common_pkg.ALL;
+USE work.dp_stream_pkg.ALL;
+
+ENTITY tb_dp_strobe_total_count IS
+  GENERIC (
+    g_mm_w                 : NATURAL := 8;
+    g_count_w              : NATURAL := 7;
+    g_nof_blocks_per_sync  : NATURAL := 10;
+    g_nof_valid_per_blk    : NATURAL := 10;
+    g_nof_sync             : NATURAL := 10;
+    g_gap_size             : NATURAL := 3
+  );
+END tb_dp_strobe_total_count;
+
+
+ARCHITECTURE tb OF tb_dp_strobe_total_count IS
+
+  ------------------------------------------------------------------------------
+  -- Clock & reset
+  ------------------------------------------------------------------------------
+  CONSTANT c_dp_clk_period  : TIME := 5 ns;
+  CONSTANT c_mm_clk_period  : TIME := 10 ns;
+
+  CONSTANT c_skip_nof_sync         : NATURAL := 3;
+  CONSTANT c_tb_nof_sync           : NATURAL := c_skip_nof_sync + g_nof_sync;
+  CONSTANT c_clip                  : BOOLEAN := TRUE;
+
+  -- dut
+  CONSTANT c_nof_counts_max        : NATURAL := 15;
+  CONSTANT c_nof_counts            : NATURAL := 3;  -- count stimuli.sync, sop, valid
+  CONSTANT c_count_max             : NATURAL := 2**g_count_w - 1;
+  CONSTANT c_mm_addr_clear         : NATURAL := c_nof_counts_max*2;
+
+  -- c_tb_nof_sync - c_skip_nof_sync because first sync intervals are skipped
+  -- by using clear, and -1, because stimuli_sosi.sync is used as ref_sync,
+  -- and ref_sync is used to hold the counts.
+  CONSTANT c_exp_nof_sync          : NATURAL := c_tb_nof_sync - c_skip_nof_sync - 1;
+  CONSTANT c_nof_blk               : NATURAL := g_nof_blocks_per_sync * c_exp_nof_sync;
+  CONSTANT c_exp_nof_sop           : NATURAL := sel_a_b(c_nof_blk < c_count_max, c_nof_blk, c_count_max);
+  CONSTANT c_nof_valid             : NATURAL := c_nof_blk * g_nof_valid_per_blk;
+  CONSTANT c_exp_nof_valid         : NATURAL := sel_a_b(c_nof_valid < c_count_max, c_nof_valid, c_count_max);
+
+  SIGNAL dp_clk             : STD_LOGIC := '1';
+  SIGNAL mm_clk             : STD_LOGIC := '1';
+  SIGNAL rst                : STD_LOGIC := '1';
+  SIGNAL tb_end             : STD_LOGIC := '0';
+  
+  SIGNAL stimuli_rst        : STD_LOGIC := '1';
+  SIGNAL stimuli_end        : STD_LOGIC;
+  SIGNAL stimuli_sosi       : t_dp_sosi;
+  SIGNAL stimuli_strobe_arr : STD_LOGIC_VECTOR(c_nof_counts-1 DOWNTO 0);
+
+  SIGNAL reg_mosi           : t_mem_mosi := c_mem_mosi_rst;
+  SIGNAL reg_miso           : t_mem_miso := c_mem_miso_rst;
+
+  SIGNAL rd_count_arr       : t_natural_arr(c_nof_counts-1 DOWNTO 0);
+  SIGNAL exp_count_arr      : t_natural_arr(c_nof_counts-1 DOWNTO 0) := (c_exp_nof_valid, c_exp_nof_sop, c_exp_nof_sync);
+
+BEGIN
+  
+  ------------------------------------------------------------------------------
+  -- Clock & reset
+  ------------------------------------------------------------------------------
+  dp_clk <= (NOT dp_clk) OR tb_end AFTER c_dp_clk_period/2;
+  mm_clk <= (NOT mm_clk) OR tb_end AFTER c_mm_clk_period/2;
+  rst <= '1', '0' AFTER c_dp_clk_period*7;
+
+  ------------------------------------------------------------------------------
+  -- Stimuli: 
+  ------------------------------------------------------------------------------
+
+  stimuli_rst <= '1', '0' AFTER c_dp_clk_period*17;
+
+  -- Generate snk_in with data frames
+  u_stimuli : ENTITY work.dp_stream_stimuli
+  GENERIC MAP (
+    g_sync_period => g_nof_blocks_per_sync,
+    g_nof_repeat  => g_nof_blocks_per_sync * c_tb_nof_sync,
+    g_pkt_len     => g_nof_valid_per_blk,
+    g_pkt_gap     => g_gap_size
+  )
+  PORT MAP (
+    rst               => stimuli_rst,
+    clk               => dp_clk,
+  
+    -- Generate stimuli
+    src_out           => stimuli_sosi,
+
+    -- End of stimuli
+    tb_end            => stimuli_end
+  );
+
+  stimuli_strobe_arr(0) <= stimuli_sosi.sync;
+  stimuli_strobe_arr(1) <= stimuli_sosi.sop;
+  stimuli_strobe_arr(2) <= stimuli_sosi.valid;
+
+  ------------------------------------------------------------------------------
+  -- DUT
+  ------------------------------------------------------------------------------     
+  u_dut : ENTITY work.dp_strobe_total_count
+  GENERIC MAP (
+    g_mm_w           => g_mm_w,
+    g_nof_counts_max => c_nof_counts_max,
+    g_nof_counts     => c_nof_counts,
+    g_count_w        => g_count_w,
+    g_clip           => c_clip
+  )
+  PORT MAP (
+    dp_rst        => rst,
+    dp_clk        => dp_clk,
+
+    ref_sync      => stimuli_sosi.sync,
+    in_strobe_arr => stimuli_strobe_arr,
+
+    mm_rst        => rst,
+    mm_clk        => mm_clk,
+
+    reg_mosi      => reg_mosi,
+    reg_miso      => reg_miso
+  );
+
+  ------------------------------------------------------------------------------
+  -- Verification
+  ------------------------------------------------------------------------------
+  
+  p_mm : PROCESS
+    VARIABLE v_rd_data  : STD_LOGIC_VECTOR(g_mm_w-1 DOWNTO 0);
+    VARIABLE v_rd_count : NATURAL;
+  BEGIN
+    -- Wait until strobes have started, skip first sync intervals
+    FOR I IN 0 TO c_skip_nof_sync-1 LOOP
+      proc_common_wait_until_lo_hi(dp_clk, stimuli_sosi.sync);
+    END LOOP;
+    proc_common_wait_some_cycles(dp_clk, 1);
+    -- Clear to restart counting at next sync interval
+    proc_mem_mm_bus_wr(c_mm_addr_clear, 1, mm_clk, reg_mosi);
+
+    proc_common_wait_until_lo_hi(dp_clk, stimuli_end);
+    proc_common_wait_some_cycles(dp_clk, 10);
+
+    proc_common_wait_some_cycles(mm_clk, 1);
+    FOR I IN 0 TO c_nof_counts-1 LOOP
+      -- read low part
+      proc_mem_mm_bus_rd(I*2, mm_clk, reg_miso, reg_mosi);
+      proc_mem_mm_bus_rd_latency(1, mm_clk);
+      v_rd_data := reg_miso.rddata(g_mm_w-1 DOWNTO 0);
+      v_rd_count := TO_UINT(v_rd_data);
+      -- read and add high part
+      proc_mem_mm_bus_rd(I*2+1, mm_clk, reg_miso, reg_mosi);
+      proc_mem_mm_bus_rd_latency(1, mm_clk);
+      v_rd_data := reg_miso.rddata(g_mm_w-1 DOWNTO 0);
+      v_rd_count := v_rd_count + TO_UINT(v_rd_data) * 2**g_mm_w;
+      rd_count_arr(I) <= v_rd_count;
+      ASSERT exp_count_arr(I) = v_rd_count REPORT "Wrong total block count(" & NATURAL'IMAGE(I) & ")" SEVERITY ERROR;
+    END LOOP;
+
+    proc_common_wait_some_cycles(dp_clk, 100);
+    tb_end <= '1';
+    WAIT;
+  END PROCESS;
+  
+END tb;
diff --git a/libraries/base/dp/tb/vhdl/tb_tb_dp_strobe_total_count.vhd b/libraries/base/dp/tb/vhdl/tb_tb_dp_strobe_total_count.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..f96672f9c71c9bcfb700bf6d62b7ef1598ba2dbb
--- /dev/null
+++ b/libraries/base/dp/tb/vhdl/tb_tb_dp_strobe_total_count.vhd
@@ -0,0 +1,61 @@
+-------------------------------------------------------------------------------
+--
+-- Copyright 2022
+-- 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: E. Kooistra
+-- Purpose: Verify multiple variations of tb_dp_strobe_total_count
+-- Usage:
+-- > as 3
+-- > run -all
+
+LIBRARY IEEE;
+USE IEEE.std_logic_1164.ALL;
+
+ENTITY tb_tb_dp_strobe_total_count IS
+END tb_tb_dp_strobe_total_count;
+
+
+ARCHITECTURE tb OF tb_tb_dp_strobe_total_count IS
+
+  SIGNAL tb_end : STD_LOGIC := '0';  -- declare tb_end to avoid 'No objects found' error on 'when -label tb_end'
+  
+BEGIN
+  --g_mm_w                 : NATURAL := c_word_w;
+  --g_count_w              : NATURAL := 16;
+  --g_nof_blocks_per_sync  : NATURAL := 10;
+  --g_nof_valid_per_blk    : NATURAL := 10;
+  --g_nof_sync             : NATURAL := 10;
+  --g_gap_size             : NATURAL := 0;
+
+  -- Use g_nof_blocks_per_sync * g_nof_valid_per_blk = 100 valid per sync and
+  -- use g_nof_sync = 10, so maximum expected valid count is 900.
+  -- Maximum expected sop count is 90
+  -- Maximum expected sync count is 9
+
+  -- Default usage
+  u_mm32b_cnt16b_no_gap  : ENTITY work.tb_dp_strobe_total_count GENERIC MAP(32, 16,  10,10,  10, 0);
+  u_mm32b_cnt16b_gap     : ENTITY work.tb_dp_strobe_total_count GENERIC MAP(32, 16,  10,10,  10, 3);
+  
+  -- Check MM high word and counter overflow (clipping)
+  u_mm8b_cnt16b_high     : ENTITY work.tb_dp_strobe_total_count GENERIC MAP(8, 16,  10,10,  10, 3);  -- use high part
+  u_mm8b_cnt9b_overflow  : ENTITY work.tb_dp_strobe_total_count GENERIC MAP(8,  9,  10,10,  10, 3);  -- cause overflow to clip count high part
+  u_mm8b_cnt7b_overflow  : ENTITY work.tb_dp_strobe_total_count GENERIC MAP(8,  7,  10,10,  10, 3);  -- cause overflow to clip count low part
+
+END tb;