diff --git a/libraries/base/common/src/vhdl/common_counter.vhd b/libraries/base/common/src/vhdl/common_counter.vhd
index 4a3dd59d1da1b92a0722d2e6523a57e95ed58881..d4826da0ff55f29abdd3b937430ab18051055fcf 100644
--- a/libraries/base/common/src/vhdl/common_counter.vhd
+++ b/libraries/base/common/src/vhdl/common_counter.vhd
@@ -22,6 +22,7 @@
 -- Purpose : Counter with extra options
 -- Description:
 --   - default wrap at 2**g_width or special wrap at fixed g_max or dynamically via cnt_max
+--   - count can be clipped instead of wrapped by setting g_clip to True.
 --   - default increment +1 or other g_step_size
 --   - external clr
 --   - external load with g_init or dynamically via load
@@ -42,7 +43,8 @@ ENTITY common_counter IS
     g_init      : INTEGER := 0;
     g_width     : NATURAL := 32;
     g_max       : NATURAL := 0;  -- default 0 to disable the g_max setting. 
-    g_step_size : INTEGER := 1   -- counting in steps of g_step_size, can be + or -
+    g_step_size : INTEGER := 1;  -- counting in steps of g_step_size, can be + or -
+    g_clip      : BOOLEAN := FALSE -- when True, counter will clip at g_max, if g_max = 0 and g_step_size > 0, the counter clips at 2**g_width -1.
   );
   PORT (
     rst     : IN  STD_LOGIC := '0';    -- either use asynchronous rst or synchronous cnt_clr
@@ -51,7 +53,8 @@ ENTITY common_counter IS
     cnt_clr : IN  STD_LOGIC := '0';    -- synchronous cnt_clr is only interpreted when clken is active
     cnt_ld  : IN  STD_LOGIC := '0';    -- cnt_ld loads the output count with the input load value, independent of cnt_en
     cnt_en  : IN  STD_LOGIC := '1';
-    cnt_max : IN  STD_LOGIC_VECTOR(g_width-1 DOWNTO 0) := TO_UVEC(sel_a_b(ceil_log2(g_max+1)>g_width, 0, g_max),  g_width);  -- see remarks
+    cnt_max : IN  STD_LOGIC_VECTOR(g_width-1 DOWNTO 0) := sel_a_b( g_step_size > 0 AND g_max = 0, array_init('1', g_width), 
+                                                          sel_a_b( ceil_log2(g_max+1) > g_width,  array_init('1', g_width), TO_UVEC(g_max, g_width) ));  -- see remarks
     load    : IN  STD_LOGIC_VECTOR(g_width-1 DOWNTO 0) := TO_SVEC(g_init, g_width);
     count   : OUT STD_LOGIC_VECTOR(g_width-1 DOWNTO 0)
   );
@@ -60,7 +63,6 @@ END common_counter;
 
 ARCHITECTURE rtl OF common_counter IS
    
-  CONSTANT zeros    : STD_LOGIC_VECTOR(count'RANGE) := (OTHERS => '0');           -- used to check if cnt_max is zero
   SIGNAL reg_count  : STD_LOGIC_VECTOR(count'RANGE) := TO_SVEC(g_init, g_width);  -- in case rst is not used
   SIGNAL nxt_count  : STD_LOGIC_VECTOR(count'RANGE) := TO_SVEC(g_init, g_width);  -- to avoid Warning: NUMERIC_STD.">=": metavalue detected, returning FALSE, when using unsigned()
   SIGNAL comb_count : STD_LOGIC_VECTOR(count'RANGE) := TO_SVEC(g_init, g_width);  -- to avoid Warning: NUMERIC_STD.">=": metavalue detected, returning FALSE, when using unsigned()
@@ -87,10 +89,14 @@ BEGIN
   p_count : PROCESS(reg_count, cnt_clr, cnt_en, cnt_ld, load, cnt_max)
   BEGIN
     nxt_count <= reg_count;
-    IF cnt_clr='1' OR (reg_count=cnt_max AND cnt_max /= zeros) THEN
+    IF cnt_clr='1' THEN
       nxt_count <= (OTHERS => '0');
     ELSIF cnt_ld='1' THEN
       nxt_count <= load;
+    ELSIF reg_count=cnt_max THEN
+      IF NOT g_clip THEN
+        nxt_count <= (OTHERS => '0');
+      END IF;
     ELSIF cnt_en='1' THEN
       nxt_count <= INCR_UVEC(reg_count, g_step_size);
     END IF;
diff --git a/libraries/base/dp/hdllib.cfg b/libraries/base/dp/hdllib.cfg
index 521d6753de27da8f29ca2d24d0edfb29bdd8eaa2..df7d5faad304285832f2a0ebc5dd69219470430f 100644
--- a/libraries/base/dp/hdllib.cfg
+++ b/libraries/base/dp/hdllib.cfg
@@ -31,6 +31,7 @@ synth_files =
     src/vhdl/dp_pipeline_ready.vhd
     src/vhdl/dp_block_resize.vhd
     src/vhdl/dp_block_validate_length.vhd
+    src/vhdl/dp_block_validate_bsn_at_sync.vhd
     src/vhdl/dp_block_select.vhd
     src/vhdl/mms_dp_block_select.vhd
     src/vhdl/dp_force_data_parallel.vhd
@@ -61,6 +62,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_block_validate_err.vhd
     src/vhdl/mms_dp_fifo_to_mm.vhd
     src/vhdl/mms_dp_fifo_from_mm.vhd
     src/vhdl/mms_dp_fifo_fill.vhd
@@ -195,6 +197,8 @@ test_bench_files =
     
     tb/vhdl/tb_dp_block_select.vhd
     tb/vhdl/tb_dp_block_validate_length.vhd
+    tb/vhdl/tb_dp_block_validate_err.vhd
+    tb/vhdl/tb_dp_block_validate_bsn_at_sync.vhd
     tb/vhdl/tb_dp_block_reshape.vhd
     tb/vhdl/tb_dp_block_reshape_sync.vhd
     tb/vhdl/tb_dp_block_gen.vhd
@@ -275,6 +279,8 @@ test_bench_files =
 
     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
+    tb/vhdl/tb_tb_dp_block_validate_bsn_at_sync.vhd
     tb/vhdl/tb_tb_dp_block_reshape.vhd
     tb/vhdl/tb_tb_dp_block_reshape_sync.vhd
     tb/vhdl/tb_tb_dp_block_gen.vhd
@@ -341,6 +347,8 @@ regression_test_vhdl =
     
     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
+    tb/vhdl/tb_tb_dp_block_validate_bsn_at_sync.vhd
     tb/vhdl/tb_tb_dp_block_reshape.vhd
     tb/vhdl/tb_tb_dp_block_reshape_sync.vhd
     tb/vhdl/tb_tb_dp_block_gen.vhd
diff --git a/libraries/base/dp/src/vhdl/dp_block_validate_bsn_at_sync.vhd b/libraries/base/dp/src/vhdl/dp_block_validate_bsn_at_sync.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..b71ce78bc5cdfcf2bbfbee099bbde6ea961265e9
--- /dev/null
+++ b/libraries/base/dp/src/vhdl/dp_block_validate_bsn_at_sync.vhd
@@ -0,0 +1,229 @@
+-------------------------------------------------------------------------------
+--
+-- Copyright 2021
+-- 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: R vd Walle
+-- Purpose:
+-- The dp_block_validate_bsn_at_sync.vhd checks whether the remote block 
+-- sequence number (BSN) at the start of an in_sosi.sync interval is equal to 
+-- the local BSN at start of the local bs_sosi.sync interval.
+-- Description:
+-- The dp_block_validate_bsn_at_sync.vhd holds the local BSN that it gets at 
+-- each bs_sosi.sync and uses that when it receives the remote BSN at the 
+-- in_sosi.sync. The dp_validate_bsn_at_sync.vhd compares the entire 
+-- g_bsn_w bit BSN. If the remote BSN at in_sosi.sync and the local BSN at 
+-- bs_sosi.sync are:
+--   . Not equal, then discard all subsequent in_sosi blocks until the next 
+--     in_sosi .sync
+--   . Equal, then pass on all subsequent in_sosi blocks until the next 
+--     in_sosi.sync
+-- Only packets with channel = g_check_channel are checked. Other packets are 
+-- just passed on.
+-- The dp_block_validate_bsn_at_sync.vhd maintains a total number of 
+-- in_sosi.sync counter and a number of discarded sync intervals counter, that 
+-- can be read via the MM interface.
+-- Remarks:
+--  . g_check_channel is needed for designs like the ring. The 
+--    dp_block_validate_bsn_at_sync.vhd only has to check the remote packets 
+--    from its neighbour ring node that is at one hop distance. The packets 
+--    that have traveled one hop have in_sosi.channel = g_check_channel = 1. 
+--    The packets at other channels from more distant PN are just passed on. 
+--    These packets have already been checked by the 
+--    dp_block_validate_bsn_at_sync.vhd on other PN. In this way it is 
+--    suffiicent to have one instance of dp_block_validate_bsn_at_sync.vhd per 
+--    PN.
+-------------------------------------------------------------------------------
+-- REGMAP
+-------------------------------------------------------------------------------
+--  wi                  Bits    R/W Name                  Default                                         
+--  =====================================================================
+--  0                   [31..0] RO  nof_sync_discarded      0x0    
+--  1                   [31..0] RO  nof_sync                0x0   
+--  2                   [31..0] RW  clear                   0x0 read or write to clear counters  
+--  =====================================================================
+-------------------------------------------------------------------------------
+LIBRARY IEEE, common_lib;
+USE IEEE.std_logic_1164.all;
+USE IEEE.numeric_std.all;
+USE work.dp_stream_pkg.ALL;
+USE common_lib.common_pkg.ALL;
+USE common_lib.common_mem_pkg.ALL;
+
+ENTITY dp_block_validate_bsn_at_sync IS
+  GENERIC (
+    g_check_channel  : NATURAL := 0;
+    g_bsn_w          : NATURAL := c_dp_stream_bsn_w
+  );
+  PORT (
+    dp_rst       : IN  STD_LOGIC;
+    dp_clk       : IN  STD_LOGIC;
+    -- ST sink
+    in_sosi       : IN  t_dp_sosi;
+    bs_sosi       : IN  t_dp_sosi;
+    -- ST source
+    out_sosi      : OUT t_dp_sosi;
+
+    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 := c_mem_miso_rst
+  );
+END dp_block_validate_bsn_at_sync;
+
+ARCHITECTURE rtl OF dp_block_validate_bsn_at_sync IS
+
+  CONSTANT c_nof_regs   : NATURAL := 3;
+  CONSTANT c_clear_adr  : NATURAL := c_nof_regs-1;
+  -- Define the actual size of the MM slave register
+  CONSTANT c_mm_reg : t_c_mem := (latency  => 1,
+                                  adr_w    => ceil_log2(c_nof_regs),
+                                  dat_w    => c_word_w,       -- Use MM bus data width = c_word_w = 32 for all MM registers
+                                  nof_dat  => c_nof_regs, -- total counter + discarded counter
+                                  init_sl  => '0');
+
+  -- Registers in st_clk domain
+  SIGNAL count_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_sync         : STD_LOGIC_VECTOR(c_word_w-1 DOWNTO 0);
+  SIGNAL cnt_sync_en      : STD_LOGIC;
+  SIGNAL cnt_discarded    : STD_LOGIC_VECTOR(c_word_w-1 DOWNTO 0);
+  SIGNAL cnt_discarded_en : STD_LOGIC;
+
+  SIGNAL out_valid        : STD_LOGIC;
+  SIGNAL bsn_ok           : STD_LOGIC;
+  SIGNAL bsn_ok_reg       : STD_LOGIC;
+  SIGNAL bsn_at_sync      : STD_LOGIC_VECTOR(g_bsn_w-1 DOWNTO 0);
+  SIGNAL bsn_at_sync_reg  : STD_LOGIC_VECTOR(g_bsn_w-1 DOWNTO 0);
+
+  SIGNAL block_sosi       : t_dp_sosi;
+  
+BEGIN
+ 
+  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
+    );
+
+  -- discarded counter
+  cnt_discarded_en <= '1' WHEN in_sosi.sync = '1' AND bsn_ok = '0' ELSE '0';
+  u_discarded_counter : ENTITY common_lib.common_counter
+  GENERIC MAP (
+    g_width => c_word_w,
+    g_clip  => TRUE
+  )
+  PORT MAP ( 
+    rst => dp_rst,
+    clk => dp_clk,
+  
+    cnt_clr => cnt_clr, 
+    cnt_en  => cnt_discarded_en,
+    count   => cnt_discarded
+  );
+
+  -- sync counter
+  u_blk_counter : ENTITY common_lib.common_counter
+  GENERIC MAP (
+    g_width => c_word_w,
+    g_clip  => TRUE
+  )
+  PORT MAP ( 
+    rst => dp_rst,
+    clk => dp_clk,
+
+    cnt_clr => cnt_clr, 
+    cnt_en  => in_sosi.sync,
+    count   => cnt_sync
+  );
+
+  -- Register mapping
+  count_reg(  c_word_w - 1 DOWNTO        0 ) <= cnt_discarded;  
+  count_reg(2*c_word_w - 1 DOWNTO c_word_w ) <= cnt_sync;  
+
+  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      => count_reg,   -- read only
+    out_reg     => OPEN       -- no write
+  );
+
+  bsn_at_sync <= bs_sosi.bsn WHEN bs_sosi.sync = '1' ELSE bsn_at_sync_reg;
+  bsn_ok      <= bsn_ok_reg WHEN in_sosi.sync = '0' ELSE '1' WHEN in_sosi.bsn = bsn_at_sync ELSE '0';
+  out_valid   <= bsn_ok WHEN TO_UINT(in_sosi.channel) = g_check_channel ELSE '1';
+
+  p_dp_clk : PROCESS(dp_rst, dp_clk)
+  BEGIN
+    IF dp_rst='1' THEN
+      bsn_ok_reg      <= '1';
+      bsn_at_sync_reg <= (OTHERS => '0');
+    ELSIF rising_edge(dp_clk) THEN
+      bsn_ok_reg      <= bsn_ok;
+      bsn_at_sync_reg <= bsn_at_sync;
+    END IF;
+  END PROCESS;
+
+  p_sosi : PROCESS(in_sosi, out_valid)
+  BEGIN
+    block_sosi       <= in_sosi;
+    block_sosi.valid <= in_sosi.valid AND out_valid;
+    block_sosi.sop   <= in_sosi.sop   AND out_valid;
+    block_sosi.eop   <= in_sosi.eop   AND out_valid;
+    block_sosi.sync  <= in_sosi.sync  AND out_valid;
+  END PROCESS;
+  
+  u_pipeline : ENTITY work.dp_pipeline
+  GENERIC MAP (
+    g_pipeline   => 1  -- 0 for wires, > 0 for registers, 
+  )
+  PORT MAP (
+    rst          => dp_rst,
+    clk          => dp_clk,
+    -- ST sink
+    snk_in       => block_sosi,
+    -- ST source
+    src_out      => out_sosi
+  );
+
+END rtl;
diff --git a/libraries/base/dp/src/vhdl/dp_block_validate_err.vhd b/libraries/base/dp/src/vhdl/dp_block_validate_err.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..8ec87e33d5e660fcffebb90920322adf73704d99
--- /dev/null
+++ b/libraries/base/dp/src/vhdl/dp_block_validate_err.vhd
@@ -0,0 +1,314 @@
+-------------------------------------------------------------------------------
+--
+-- Copyright 2021
+-- 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: R vd Walle
+-- Purpose:
+--   Validate the error field of a DP block.
+-- Description:
+--  . The dp_block_validate_err.vhd checks the in_sosi.err field at the end of a
+--    block. Therefore the block needs to be stored, before it can be validated. 
+--    The stored block is then either forwarded when the in_sosi.err = 0, or else 
+--    it is discarded. 
+--  . The dp_block_validate_err.vhd has to maintain the a total number of in_sosi 
+--    blocks counter and a number of discarded blocks counter per bit in the 
+--    in_sosi.err field. The counters can be read via the MM interface. 
+-- Remarks:
+--   . Note that a block can have more than one bit set in the err field. This can
+--     result in multiple counters increasing per block. Therefore, it should not be 
+--     assumed that the sum of the err counters is the total amount of discarded
+--     blocks.
+--   . Note that dp_fifo_fill_eop cannot handle continues stream of blocks without 
+--     a gap between blocks the dp_fifo_fill_eop needs 1 cycle to process a block.
+--     Streaming without gaps may cause the fifo to overflow. Bursts of blocks
+--     can be handled by increasing g_fifo_size.
+-------------------------------------------------------------------------------
+-- REGMAP
+-------------------------------------------------------------------------------
+--  wi                  Bits    R/W Name                                 Default                                         
+--  ====================================================================================
+--  0                   [31..0] RO  err_count_index_0                     0x0    
+--  1                   [31..0] RO  err_count_index_1                     0x0   
+--  .                    .      .   .                                     . 
+--  .                    .      .   .                                     . 
+--  .                    .      .   .                                     . 
+--  g_nof_err_counts-1  [31..0] RO  err_count_index_[g_nof_err_counts-1]  0x0           
+--  g_nof_err_counts    [31..0] RO  total_discarded_blocks                0x0           
+--  g_nof_err_counts+1  [31..0] RO  total_block_count                     0x0           
+--  g_nof_err_counts+2  [31..0] RW  clear                                 0x0 read or write to clear counters
+--  ====================================================================================
+-------------------------------------------------------------------------------
+LIBRARY IEEE, common_lib;
+USE IEEE.std_logic_1164.all;
+USE IEEE.numeric_std.all;
+USE work.dp_stream_pkg.ALL;
+USE common_lib.common_pkg.ALL;
+USE common_lib.common_mem_pkg.ALL;
+
+ENTITY dp_block_validate_err IS
+  GENERIC (
+    g_cnt_w              : NATURAL  := c_word_w; -- max is c_word_w due to mm word width
+    g_max_block_size     : POSITIVE := 250;
+    g_min_block_size     : POSITIVE := 1;
+    g_nof_err_counts     : NATURAL  := 8;
+    -- fifo generics
+    g_fifo_size          : POSITIVE := 256;
+    g_data_w             : NATURAL  := 16;
+    g_bsn_w              : NATURAL  := 1;
+    g_empty_w            : NATURAL  := 1;
+    g_channel_w          : NATURAL  := 1;
+    g_use_bsn            : BOOLEAN  := FALSE;
+    g_use_empty          : BOOLEAN  := FALSE;
+    g_use_channel        : BOOLEAN  := FALSE;
+    g_use_sync           : BOOLEAN  := FALSE;
+    g_use_complex        : BOOLEAN  := FALSE
+  );
+  PORT (
+    dp_rst       : IN  STD_LOGIC;
+    dp_clk       : IN  STD_LOGIC;
+    -- ST sink
+    snk_out      : OUT t_dp_siso := c_dp_siso_rdy;
+    snk_in       : IN  t_dp_sosi;
+    -- ST source
+    src_in       : IN  t_dp_siso := c_dp_siso_rdy;
+    src_out      : OUT t_dp_sosi;
+
+    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 := c_mem_miso_rst
+  );
+END dp_block_validate_err;
+
+ARCHITECTURE rtl OF dp_block_validate_err IS
+
+  CONSTANT c_max_cnt    : STD_LOGIC_VECTOR(g_cnt_w-1 DOWNTO 0) := (OTHERS => '1');
+  CONSTANT c_nof_err_ok : NATURAL := ceil_div(g_max_block_size, g_min_block_size);
+  CONSTANT c_nof_regs   : NATURAL := g_nof_err_counts + 3;
+  CONSTANT c_clear_adr  : NATURAL := c_nof_regs-1;
+
+  TYPE t_cnt_err_arr IS ARRAY (INTEGER RANGE <>) OF STD_LOGIC_VECTOR(g_cnt_w-1 DOWNTO 0);
+
+  -- Define the actual size of the MM slave register
+  CONSTANT c_mm_reg : t_c_mem := (latency  => 1,
+                                  adr_w    => ceil_log2(c_nof_regs),
+                                  dat_w    => c_word_w,       -- Use MM bus data width = c_word_w = 32 for all MM registers
+                                  nof_dat  => c_nof_regs,
+                                  init_sl  => '0');
+
+  -- Registers in st_clk domain
+  SIGNAL count_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_blk          : STD_LOGIC_VECTOR(g_cnt_w-1 DOWNTO 0);
+  SIGNAL cnt_discarded    : STD_LOGIC_VECTOR(g_cnt_w-1 DOWNTO 0);
+  SIGNAL cnt_discarded_en : STD_LOGIC;
+  SIGNAL cnt_err          : t_cnt_err_arr(g_nof_err_counts-1 DOWNTO 0);
+  SIGNAL cnt_err_en       : STD_LOGIC_VECTOR(g_nof_err_counts-1 DOWNTO 0);
+
+  SIGNAL err_ok          : STD_LOGIC;
+  SIGNAL err_ok_reg      : STD_LOGIC;
+  SIGNAL fifo_err_ok     : STD_LOGIC;
+  SIGNAL fifo_err_ok_val : STD_LOGIC;
+  SIGNAL out_valid       : STD_LOGIC;
+  SIGNAL out_valid_reg   : STD_LOGIC;
+
+  SIGNAL block_sosi       : t_dp_sosi;
+  SIGNAL block_siso       : t_dp_siso;
+  SIGNAL block_sosi_piped : t_dp_sosi;
+  
+BEGIN
+ 
+  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
+    );
+
+  -- block counter
+  u_blk_counter : ENTITY common_lib.common_counter
+  GENERIC MAP (
+    g_width => g_cnt_w,
+    g_clip  => TRUE
+  )
+  PORT MAP ( 
+    rst => dp_rst,
+    clk => dp_clk,
+
+    cnt_clr => cnt_clr, 
+    cnt_en  => snk_in.eop,
+    count   => cnt_blk
+  );
+
+  -- discarded block counter
+  cnt_discarded_en <= snk_in.eop WHEN TO_UINT(snk_in.err(g_nof_err_counts-1 DOWNTO 0)) > 0 ELSE '0';
+  u_discarded_counter : ENTITY common_lib.common_counter
+  GENERIC MAP (
+    g_width => g_cnt_w,
+    g_clip  => TRUE
+  )
+  PORT MAP ( 
+    rst => dp_rst,
+    clk => dp_clk,
+
+    cnt_clr => cnt_clr, 
+    cnt_en  => cnt_discarded_en,
+    count   => cnt_discarded
+  );
+
+  -- error counters
+  gen_err_counters : FOR I IN 0 TO g_nof_err_counts-1 GENERATE
+    cnt_err_en(I) <= snk_in.eop AND snk_in.err(I);
+    u_blk_counter : ENTITY common_lib.common_counter
+    GENERIC MAP (
+      g_width => g_cnt_w,
+      g_clip  => TRUE
+    )
+    PORT MAP ( 
+      rst => dp_rst,
+      clk => dp_clk,
+  
+      cnt_clr => cnt_clr, 
+      cnt_en  => cnt_err_en(I),
+      count   => cnt_err(I)
+    );
+  END GENERATE;
+
+  -- Register mapping
+  gen_reg : FOR I IN 0 TO g_nof_err_counts-1 GENERATE
+    count_reg((I + 1) * c_word_w - 1 DOWNTO I * c_word_w) <= RESIZE_UVEC(cnt_err(I), c_word_w);
+  END GENERATE;
+  count_reg((g_nof_err_counts+1) * c_word_w - 1 DOWNTO  g_nof_err_counts    * c_word_w ) <= RESIZE_UVEC(cnt_discarded, c_word_w);  
+  count_reg((g_nof_err_counts+2) * c_word_w - 1 DOWNTO (g_nof_err_counts+1) * c_word_w ) <= RESIZE_UVEC(cnt_blk,       c_word_w);  
+
+  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      => count_reg,   -- read only
+    out_reg     => OPEN       -- no write
+  );
+
+  u_fifo_fill_eop : ENTITY work.dp_fifo_fill_eop
+  GENERIC MAP (
+    g_data_w       => g_data_w,  
+    g_bsn_w        => g_bsn_w,  
+    g_empty_w      => g_empty_w,  
+    g_channel_w    => g_channel_w,  
+    g_use_bsn      => g_use_bsn,  
+    g_use_empty    => g_use_empty,  
+    g_use_channel  => g_use_channel,  
+    g_use_sync     => g_use_sync,  
+    g_use_complex  => g_use_complex,  
+    g_fifo_fill    => g_max_block_size,  
+    g_fifo_size    => g_fifo_size  
+  )
+  PORT MAP (
+    wr_rst => dp_rst,        
+    wr_clk => dp_clk,     
+    rd_rst => dp_rst,     
+    rd_clk => dp_clk,     
+    
+    -- ST sink
+    snk_out => snk_out,    
+    snk_in  => snk_in,    
+    -- ST source
+    src_in  => block_siso,    
+    src_out => block_sosi  
+  );
+
+  u_pipeline : ENTITY work.dp_pipeline
+  GENERIC MAP (
+    g_pipeline   => 1  -- 0 for wires, > 0 for registers, 
+  )
+  PORT MAP (
+    rst          => dp_rst,
+    clk          => dp_clk,
+    -- ST sink
+    snk_out      => block_siso,
+    snk_in       => block_sosi,
+    -- ST source
+    src_in       => src_in,
+    src_out      => block_sosi_piped
+  );
+
+  p_dp_clk : PROCESS(dp_rst, dp_clk)
+  BEGIN
+    IF dp_rst='1' THEN
+      err_ok_reg      <= '0';
+      out_valid_reg   <= '0';
+    ELSIF rising_edge(dp_clk) THEN
+      err_ok_reg      <= err_ok;
+      out_valid_reg   <= out_valid;
+    END IF;
+  END PROCESS;
+
+  err_ok <= NOT vector_or(snk_in.err(g_nof_err_counts-1 DOWNTO 0)) WHEN snk_in.eop = '1' ELSE err_ok_reg;
+
+  u_fifo_err_ok : ENTITY common_lib.common_fifo_sc
+  GENERIC MAP (
+    g_dat_w => 1,
+    g_nof_words => c_nof_err_ok
+  )
+  PORT MAP (
+    rst       => dp_rst,
+    clk       => dp_clk,
+    wr_dat(0) => err_ok,
+    wr_req    => snk_in.eop,
+    rd_req    => block_sosi.sop,
+    rd_dat(0) => fifo_err_ok,
+    rd_val    => fifo_err_ok_val
+  );
+
+  out_valid <= fifo_err_ok WHEN fifo_err_ok_val = '1' ELSE out_valid_reg;
+
+  p_src_out : PROCESS(block_sosi_piped, out_valid)
+  BEGIN
+    src_out       <= block_sosi_piped;
+    src_out.valid <= block_sosi_piped.valid AND out_valid;
+    src_out.sop   <= block_sosi_piped.sop   AND out_valid;
+    src_out.eop   <= block_sosi_piped.eop   AND out_valid;
+    src_out.sync  <= block_sosi_piped.sync  AND out_valid;
+  END PROCESS;
+  
+END rtl;
diff --git a/libraries/base/dp/tb/vhdl/tb_dp_block_validate_bsn_at_sync.vhd b/libraries/base/dp/tb/vhdl/tb_dp_block_validate_bsn_at_sync.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..9483cfab0d228c49774aaaadea4e3ee978b62d30
--- /dev/null
+++ b/libraries/base/dp/tb/vhdl/tb_dp_block_validate_bsn_at_sync.vhd
@@ -0,0 +1,235 @@
+-------------------------------------------------------------------------------
+--
+-- Copyright 2021
+-- 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: R vd Walle
+-- Purpose:
+-- Test bench for dp_block_validate_bsn_at_sync.
+-- Description:
+-- Verifies the output sosi of the DUT with the expected sosi. 
+-- The TB also reads the register values via MM and verifies them against the 
+-- expected values.  
+-- 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.common_lfsr_sequences_pkg.ALL;
+USE common_lib.tb_common_pkg.ALL;
+USE work.dp_stream_pkg.ALL;
+USE work.tb_dp_pkg.ALL;
+
+ENTITY tb_dp_block_validate_bsn_at_sync IS
+  GENERIC (
+    g_nof_blocks_per_sync  : NATURAL := 5;
+    g_nof_data_per_blk     : NATURAL := 6; 
+    g_bsn_init             : NATURAL := 7; -- >= g_nof_blocks_per_sync for discarded sync, < g_nof_blocks_per_sync for no discarded sync,
+    g_check_channel        : NATURAL := 8  -- channel to check, the channel field is a counter value. 
+  );
+END tb_dp_block_validate_bsn_at_sync;
+
+
+ARCHITECTURE tb OF tb_dp_block_validate_bsn_at_sync IS
+
+  ------------------------------------------------------------------------------
+  -- Clock & reset
+  ------------------------------------------------------------------------------
+  CONSTANT c_dp_clk_period  : TIME := 5 ns;
+  CONSTANT c_mm_clk_period  : TIME := 10 ns;
+
+  CONSTANT c_dut_pipeline   : NATURAL := 1;
+  CONSTANT c_gap_size       : NATURAL := 4;
+  CONSTANT c_nof_sync       : NATURAL := 5;
+  CONSTANT c_nof_blk        : NATURAL := g_nof_blocks_per_sync * c_nof_sync;
+  
+  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_end        : STD_LOGIC;
+  SIGNAL stimuli_sosi       : t_dp_sosi;
+  SIGNAL stimuli_siso       : t_dp_siso := c_dp_siso_rdy;
+  SIGNAL bs_sosi            : t_dp_sosi;
+  SIGNAL bs_siso            : t_dp_siso := c_dp_siso_rdy;
+  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;
+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: 
+  ------------------------------------------------------------------------------
+
+  -- Generate in_sosi with data frames
+  u_stimuli_in : ENTITY work.dp_stream_stimuli
+  GENERIC MAP (
+    g_sync_period => g_nof_blocks_per_sync,
+    g_nof_repeat  => c_nof_blk,
+    g_pkt_len     => g_nof_data_per_blk,
+    g_pkt_gap     => c_gap_size,
+    g_channel_init=> 0,
+    g_bsn_init    => TO_DP_BSN(0)
+  )
+  PORT MAP (
+    rst               => rst,
+    clk               => dp_clk,
+  
+    -- Generate stimuli
+    src_in            => stimuli_siso,
+    src_out           => stimuli_sosi,
+
+    -- End of stimuli
+    tb_end            => stimuli_end
+  );
+
+  -- Generate bs_sosi with data frames
+  u_stimuli_bs : ENTITY work.dp_stream_stimuli
+  GENERIC MAP (
+    g_sync_period => g_nof_blocks_per_sync,
+    g_nof_repeat  => c_nof_blk,
+    g_pkt_len     => g_nof_data_per_blk,
+    g_pkt_gap     => c_gap_size,
+    g_channel_init=> 0,
+    g_bsn_init    => TO_DP_BSN(g_bsn_init)
+  )
+  PORT MAP (
+    rst               => rst,
+    clk               => dp_clk,
+  
+    -- Generate stimuli
+    src_in            => bs_siso,
+    src_out           => bs_sosi,
+
+    -- End of stimuli
+    tb_end            => OPEN
+  );
+  ------------------------------------------------------------------------------
+  -- DUT
+  ------------------------------------------------------------------------------     
+  u_dut : ENTITY work.dp_block_validate_bsn_at_sync
+  GENERIC MAP (
+    g_check_channel => g_check_channel
+  )
+  PORT MAP (
+    dp_rst       => rst,
+    dp_clk       => dp_clk,
+
+    mm_rst       => rst,
+    mm_clk       => mm_clk,
+    -- ST sink
+    in_sosi      => stimuli_sosi,
+    bs_sosi      => bs_sosi,
+    -- ST source
+    out_sosi     => verify_sosi,
+
+    reg_mosi     => reg_mosi,
+    reg_miso     => reg_miso
+  );
+
+  
+  ------------------------------------------------------------------------------
+  -- Verification
+  ------------------------------------------------------------------------------
+  
+  u_pipeline : ENTITY work.dp_pipeline
+  GENERIC MAP (
+    g_pipeline   => c_dut_pipeline
+  )
+  PORT MAP (
+    rst         => rst,
+    clk         => dp_clk,
+    -- ST sink
+    snk_out     => OPEN,
+    snk_in      => stimuli_sosi,
+    -- ST source
+    src_in      => reference_siso,
+    src_out     => reference_sosi 
+  );
+  
+  reference_cnt_reg <= reference_cnt WHEN rising_edge(dp_clk);
+  reference_cnt     <= reference_cnt_reg + 1 WHEN reference_sosi.sync='1' ELSE reference_cnt_reg;
+  
+  p_verify : PROCESS(dp_clk)
+  VARIABLE v_valid_blk : BOOLEAN := TRUE;
+  BEGIN
+    IF rising_edge(dp_clk) THEN
+      IF reference_sosi.sop = '1' THEN
+        IF g_bsn_init >= g_nof_blocks_per_sync AND TO_UINT(reference_sosi.channel) = g_check_channel THEN
+          v_valid_blk := FALSE;
+        ELSE
+          v_valid_blk := TRUE;
+        END IF;
+      END IF;
+        
+      IF v_valid_blk THEN -- we expect a block
+        ASSERT verify_sosi  = reference_sosi   REPORT "Unexpected difference between in / out sosi" SEVERITY ERROR;
+      ELSE -- we expect no block
+        ASSERT verify_sosi.valid = '0' REPORT "Wrong, valid is not '0' which is unexpected." SEVERITY ERROR; 
+        ASSERT verify_sosi.sop   = '0' REPORT "Wrong, sop is not '0' which is unexpected." SEVERITY ERROR; 
+        ASSERT verify_sosi.eop   = '0' REPORT "Wrong, eop is not '0' which is unexpected." SEVERITY ERROR; 
+      END IF;
+    END IF;
+  END PROCESS;
+
+  p_verify_mm : PROCESS
+  BEGIN
+    proc_common_wait_until_lo_hi(dp_clk, stimuli_end);
+    proc_common_wait_some_cycles(dp_clk, c_dut_pipeline + 1);
+    proc_common_wait_some_cycles(mm_clk, 1);
+    proc_mem_mm_bus_rd(1, mm_clk, reg_miso, reg_mosi);
+    proc_mem_mm_bus_rd_latency(1, mm_clk);
+    ASSERT c_nof_sync = TO_UINT(reg_miso.rddata(c_word_w-1 DOWNTO 0)) REPORT "Wrong total sync count" SEVERITY ERROR;
+
+    proc_mem_mm_bus_rd(0, mm_clk, reg_miso, reg_mosi);
+    proc_mem_mm_bus_rd_latency(1, mm_clk);
+    IF g_bsn_init = g_nof_blocks_per_sync THEN -- should have c_nof_sync discarded sync
+      ASSERT c_nof_sync = TO_UINT(reg_miso.rddata(c_word_w-1 DOWNTO 0)) REPORT "Wrong discarded sync count" SEVERITY ERROR;
+    ELSIF g_bsn_init > g_nof_blocks_per_sync THEN -- should have c_nof_sync -1 discarded sync
+      ASSERT c_nof_sync-1 = TO_UINT(reg_miso.rddata(c_word_w-1 DOWNTO 0)) REPORT "Wrong discarded sync count" SEVERITY ERROR;
+    ELSE -- 0 discarded sync
+      ASSERT 0 = TO_UINT(reg_miso.rddata(c_word_w-1 DOWNTO 0)) REPORT "Wrong discarded sync count" SEVERITY ERROR;
+    END IF;
+    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_dp_block_validate_err.vhd b/libraries/base/dp/tb/vhdl/tb_dp_block_validate_err.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..9b0c20e901e1475494ae2798e9c98d159599e05e
--- /dev/null
+++ b/libraries/base/dp/tb/vhdl/tb_dp_block_validate_err.vhd
@@ -0,0 +1,248 @@
+-------------------------------------------------------------------------------
+--
+-- Copyright 2021
+-- 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: R vd Walle
+-- Purpose:
+-- Test bench for dp_block_validate_err.
+-- Description:
+-- Verifies the output sosi of the DUT with the expected sosi. 
+-- The TB also reads the register values via MM and verifies them against the 
+-- expected values.  
+-- 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.common_lfsr_sequences_pkg.ALL;
+USE common_lib.tb_common_pkg.ALL;
+USE work.dp_stream_pkg.ALL;
+USE work.tb_dp_pkg.ALL;
+
+ENTITY tb_dp_block_validate_err IS
+  GENERIC (
+    g_nof_blocks_per_sync  : NATURAL := 5;
+    g_nof_data_per_blk     : NATURAL := 9; 
+    g_max_block_size       : NATURAL := 9;
+    g_nof_err_counts       : NATURAL := 8;
+    g_gap_size             : NATURAL := 4;
+    g_cnt_w                : NATURAL := 3 
+  );
+END tb_dp_block_validate_err;
+
+
+ARCHITECTURE tb OF tb_dp_block_validate_err IS
+
+  ------------------------------------------------------------------------------
+  -- Clock & reset
+  ------------------------------------------------------------------------------
+  CONSTANT c_dp_clk_period  : TIME := 5 ns;
+  CONSTANT c_mm_clk_period  : TIME := 10 ns;
+
+  CONSTANT c_dut_pipeline             : NATURAL := g_nof_data_per_blk + 3;
+  CONSTANT c_nof_sync                 : NATURAL := 5;
+  CONSTANT c_nof_blk                  : NATURAL := g_nof_blocks_per_sync * c_nof_sync;
+  CONSTANT c_nof_discarded            : NATURAL := c_nof_blk - ceil_div(c_nof_blk, 2**g_nof_err_counts);
+  CONSTANT c_max_cnt                  : NATURAL := 2**g_cnt_w -1;
+  
+  CONSTANT c_mm_addr_dp_blk_cnt       : NATURAL := g_nof_err_counts+1;
+  CONSTANT c_mm_addr_dp_discarded_cnt : NATURAL := g_nof_err_counts;
+  CONSTANT c_exp_blk_cnt              : NATURAL := sel_a_b(c_nof_blk < c_max_cnt, c_nof_blk, c_max_cnt);
+  CONSTANT c_exp_discarded_cnt        : NATURAL := sel_a_b(c_nof_discarded < c_max_cnt, c_nof_discarded, c_max_cnt);
+  
+  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_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;
+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: 
+  ------------------------------------------------------------------------------
+
+  -- 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_nof_sync,
+    g_pkt_len     => g_nof_data_per_blk,
+    g_pkt_gap     => g_gap_size,
+    g_err_init    => 0,
+    g_err_incr    => 1
+  )
+  PORT MAP (
+    rst               => rst,
+    clk               => dp_clk,
+  
+    -- Generate stimuli
+    src_in            => stimuli_siso,
+    src_out           => stimuli_sosi,
+
+    -- End of stimuli
+    tb_end            => stimuli_end
+  );
+
+  ------------------------------------------------------------------------------
+  -- DUT
+  ------------------------------------------------------------------------------     
+  u_dut : ENTITY work.dp_block_validate_err
+  GENERIC MAP (
+    g_cnt_w           => g_cnt_w,
+    g_max_block_size  => g_max_block_size,
+    g_nof_err_counts  => g_nof_err_counts,
+    g_data_w          => c_word_w,
+    g_bsn_w           => c_dp_stream_bsn_w,
+    g_empty_w         => c_dp_stream_empty_w,
+    g_channel_w       => c_dp_stream_channel_w,
+    g_use_bsn         => TRUE, 
+    g_use_empty       => TRUE, 
+    g_use_channel     => TRUE, 
+    g_use_sync        => TRUE 
+  )
+  PORT MAP (
+    dp_rst       => rst,
+    dp_clk       => dp_clk,
+
+    mm_rst       => rst,
+    mm_clk       => mm_clk,
+    -- ST sink
+    snk_out      => stimuli_siso,
+    snk_in       => stimuli_sosi,
+    -- ST source
+    src_in       => verify_siso,
+    src_out      => verify_sosi,
+
+    reg_mosi     => reg_mosi,
+    reg_miso     => reg_miso
+  );
+
+  
+  ------------------------------------------------------------------------------
+  -- Verification
+  ------------------------------------------------------------------------------
+  
+  u_pipeline : ENTITY work.dp_pipeline
+  GENERIC MAP (
+    g_pipeline   => c_dut_pipeline
+  )
+  PORT MAP (
+    rst         => rst,
+    clk         => dp_clk,
+    -- ST sink
+    snk_out     => OPEN,
+    snk_in      => stimuli_sosi,
+    -- ST source
+    src_in      => reference_siso,
+    src_out     => reference_sosi 
+  );
+  
+  reference_cnt_reg <= reference_cnt WHEN rising_edge(dp_clk);
+  reference_cnt     <= 0           WHEN reference_sosi.eop='1' AND ((reference_cnt_reg+1) MOD 2**g_nof_err_counts) = 0 ELSE
+             reference_cnt_reg + 1 WHEN reference_sosi.eop='1' ELSE
+             reference_cnt_reg;
+  
+  p_verify : PROCESS(dp_clk)
+  BEGIN
+    IF rising_edge(dp_clk) THEN
+      IF reference_cnt_reg = 0 THEN -- no errors so we expect a block
+        ASSERT verify_sosi.valid   = reference_sosi.valid   REPORT "Unexpected difference between in / out sosi" SEVERITY ERROR;
+        ASSERT verify_sosi.sop     = reference_sosi.sop     REPORT "Unexpected difference between in / out sosi" SEVERITY ERROR;
+        ASSERT verify_sosi.eop     = reference_sosi.eop     REPORT "Unexpected difference between in / out sosi" SEVERITY ERROR;
+        ASSERT verify_sosi.data    = reference_sosi.data    REPORT "Unexpected difference between in / out sosi" SEVERITY ERROR;
+        ASSERT verify_sosi.channel = reference_sosi.channel REPORT "Unexpected difference between in / out sosi" SEVERITY ERROR;
+        ASSERT verify_sosi.bsn     = reference_sosi.bsn     REPORT "Unexpected difference between in / out sosi" SEVERITY ERROR;
+        ASSERT verify_sosi.empty   = reference_sosi.empty   REPORT "Unexpected difference between in / out sosi" SEVERITY ERROR;
+        ASSERT verify_sosi.sync    = reference_sosi.sync    REPORT "Unexpected difference between in / out sosi" SEVERITY ERROR;
+      ELSE -- we expect no block as there are errors
+        ASSERT verify_sosi.valid = '0' REPORT "Wrong, valid is not '0' which is unexpected." SEVERITY ERROR; 
+        ASSERT verify_sosi.sop   = '0' REPORT "Wrong, sop is not '0' which is unexpected." SEVERITY ERROR; 
+        ASSERT verify_sosi.eop   = '0' REPORT "Wrong, eop is not '0' which is unexpected." SEVERITY ERROR; 
+      END IF;
+    END IF;
+  END PROCESS;
+
+  p_verify_mm : PROCESS
+    VARIABLE v_X : INTEGER := 0; -- variable to hold 2**I * ((c_nof_blk-1) / 2**(I+1))
+    VARIABLE v_Y : INTEGER := 0; -- variable to hold (c_nof_blk-1) + 1 - (2 * v_X) - 2**I
+    -- v_N is a variable to hold the expected cnt number for the error counter registers = v_X + v_Y for v_Y > 0, else = v_x.
+    -- this can be calculated as the dp error field is a counter up to c_nof_blk - 1.
+    VARIABLE v_N : INTEGER := 0;
+  BEGIN
+    proc_common_wait_until_lo_hi(dp_clk, stimuli_end);
+    proc_common_wait_some_cycles(dp_clk, c_dut_pipeline + 1);
+    proc_common_wait_until_lo_hi(mm_clk, mm_clk);
+    proc_mem_mm_bus_rd(c_mm_addr_dp_discarded_cnt, mm_clk, reg_miso, reg_mosi);
+    proc_mem_mm_bus_rd_latency(1, mm_clk);
+    ASSERT c_exp_discarded_cnt = TO_UINT(reg_miso.rddata(c_word_w-1 DOWNTO 0)) REPORT "Wrong total discarded block count" SEVERITY ERROR;
+    proc_mem_mm_bus_rd(c_mm_addr_dp_blk_cnt, mm_clk, reg_miso, reg_mosi);
+    proc_mem_mm_bus_rd_latency(1, mm_clk);
+    ASSERT c_exp_blk_cnt = TO_UINT(reg_miso.rddata(c_word_w-1 DOWNTO 0)) REPORT "Wrong total block count" SEVERITY ERROR;
+    FOR I IN 0 TO g_nof_err_counts-1 LOOP
+      v_X := 2**I * ((c_nof_blk-1) / 2**(I+1));
+      v_Y := c_nof_blk - 2*v_X - 2**I;
+      IF v_Y < 0 THEN -- v_N = v_X + v_Y only holds for v_Y > 0.
+        v_N := v_X;
+      ELSE
+        v_N := v_X + v_Y;
+      END IF;
+
+      IF v_N > c_max_cnt THEN
+        v_N := c_max_cnt; -- the DUT clips the counters
+      END IF;
+
+      proc_mem_mm_bus_rd(I, mm_clk, reg_miso, reg_mosi);
+      proc_mem_mm_bus_rd_latency(1, mm_clk);
+      ASSERT v_N = TO_UINT(reg_miso.rddata(c_word_w-1 DOWNTO 0)) REPORT "Wrong error count" SEVERITY ERROR;
+    END LOOP;
+    proc_common_wait_some_cycles(dp_clk, 10);
+    tb_end <= '1';
+    WAIT;
+  END PROCESS;
+  
+  tb_end <= '0', stimuli_end AFTER (1 + 10*c_dut_pipeline)*c_dp_clk_period;
+  
+END tb;
diff --git a/libraries/base/dp/tb/vhdl/tb_tb_dp_block_validate_bsn_at_sync.vhd b/libraries/base/dp/tb/vhdl/tb_tb_dp_block_validate_bsn_at_sync.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..6828a0964eebc0d01f5d017ed4866020a4ce2b1d
--- /dev/null
+++ b/libraries/base/dp/tb/vhdl/tb_tb_dp_block_validate_bsn_at_sync.vhd
@@ -0,0 +1,55 @@
+-------------------------------------------------------------------------------
+--
+-- Copyright 2021
+-- 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: R vd Walle
+-- Purpose:
+-- Verify multiple variations of tb_dp_block_validate_bsn_at_sync
+-- Usage:
+-- > as 3
+-- > run -all
+
+LIBRARY IEEE;
+USE IEEE.std_logic_1164.ALL;
+
+ENTITY tb_tb_dp_block_validate_bsn_at_sync IS
+END tb_tb_dp_block_validate_bsn_at_sync;
+
+
+ARCHITECTURE tb OF tb_tb_dp_block_validate_bsn_at_sync IS
+
+  SIGNAL tb_end : STD_LOGIC := '0';  -- declare tb_end to avoid 'No objects found' error on 'when -label tb_end'
+  
+  CONSTANT c_blk_per_sync   : NATURAL := 5;
+  CONSTANT c_data_per_blk   : NATURAL := 9;
+
+BEGIN
+--    g_nof_blocks_per_sync  : NATURAL := 5;
+--    g_nof_data_per_blk     : NATURAL := 6; 
+--    g_bsn_init             : NATURAL := 7; -- >= g_nof_blocks_per_sync for discarded sync, < g_nof_blocks_per_sync for no discarded sync,
+--    g_check_channel        : NATURAL := 8  -- channel to check, the channel field is a counter value. 
+
+  u_smaller    : ENTITY work.tb_dp_block_validate_bsn_at_sync GENERIC MAP(c_blk_per_sync, c_data_per_blk, 0,   8); -- g_bsn_init < g_nof_blocks_per_sync
+  u_equal      : ENTITY work.tb_dp_block_validate_bsn_at_sync GENERIC MAP(c_blk_per_sync, c_data_per_blk, 5,   8); -- g_bsn_init = g_nof_blocks_per_sync
+  u_larger     : ENTITY work.tb_dp_block_validate_bsn_at_sync GENERIC MAP(c_blk_per_sync, c_data_per_blk, 8,   8); -- g_bsn_init > g_nof_blocks_per_sync
+  u_ch_on_sync : ENTITY work.tb_dp_block_validate_bsn_at_sync GENERIC MAP(c_blk_per_sync, c_data_per_blk, 5,  10); -- g_check_channel MOD c_blk_per_sync = 0,
+  u_no_ch      : ENTITY work.tb_dp_block_validate_bsn_at_sync GENERIC MAP(c_blk_per_sync, c_data_per_blk, 8, 500); -- channel will never reach 500
+  
+END tb;
diff --git a/libraries/base/dp/tb/vhdl/tb_tb_dp_block_validate_err.vhd b/libraries/base/dp/tb/vhdl/tb_tb_dp_block_validate_err.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..800a23d1ea1485892223e9a5d6db79e97dedf032
--- /dev/null
+++ b/libraries/base/dp/tb/vhdl/tb_tb_dp_block_validate_err.vhd
@@ -0,0 +1,61 @@
+-------------------------------------------------------------------------------
+--
+-- Copyright 2021
+-- 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: R vd Walle
+-- Purpose:
+-- Verify multiple variations of tb_dp_block_validate_err
+-- Usage:
+-- > as 3
+-- > run -all
+
+LIBRARY IEEE;
+USE IEEE.std_logic_1164.ALL;
+
+ENTITY tb_tb_dp_block_validate_err IS
+END tb_tb_dp_block_validate_err;
+
+
+ARCHITECTURE tb OF tb_tb_dp_block_validate_err IS
+
+  SIGNAL tb_end : STD_LOGIC := '0';  -- declare tb_end to avoid 'No objects found' error on 'when -label tb_end'
+  
+  CONSTANT c_blk_per_sync   : NATURAL := 5;
+  CONSTANT c_data_per_blk   : NATURAL := 9;
+  CONSTANT c_max_block_size : NATURAL := 9;
+  CONSTANT c_nof_err_counts : NATURAL := 5;
+
+BEGIN
+--    g_nof_blocks_per_sync  : NATURAL := 5;
+--    g_nof_data_per_blk     : NATURAL := 9; 
+--    g_max_block_size       : NATURAL := 9;
+--    g_nof_err_counts       : NATURAL := 8;
+--    g_gap_size             : NATURAL := 4;
+--    g_cnt_w                : NATURAL := 3 
+
+  u_normal      : ENTITY work.tb_dp_block_validate_err GENERIC MAP(c_blk_per_sync, c_data_per_blk, c_max_block_size, c_nof_err_counts, 4,   3); 
+  u_clip        : ENTITY work.tb_dp_block_validate_err GENERIC MAP(c_blk_per_sync, c_data_per_blk, c_max_block_size, c_nof_err_counts, 4,   3); 
+  u_small_cnt_w : ENTITY work.tb_dp_block_validate_err GENERIC MAP(c_blk_per_sync, c_data_per_blk, c_max_block_size, c_nof_err_counts, 4,   1); 
+  u_large_cnt_w : ENTITY work.tb_dp_block_validate_err GENERIC MAP(c_blk_per_sync, c_data_per_blk, c_max_block_size, c_nof_err_counts, 4,   30); 
+  u_small_gap   : ENTITY work.tb_dp_block_validate_err GENERIC MAP(c_blk_per_sync, c_data_per_blk, c_max_block_size, c_nof_err_counts, 1,   16); 
+  u_large_gap   : ENTITY work.tb_dp_block_validate_err GENERIC MAP(c_blk_per_sync, c_data_per_blk, c_max_block_size, c_nof_err_counts, 100, 16); 
+  u_low_nof_cnt : ENTITY work.tb_dp_block_validate_err GENERIC MAP(c_blk_per_sync, c_data_per_blk, c_max_block_size, 1,                1,   16); 
+  
+END tb;