diff --git a/libraries/base/dp/src/vhdl/dp_stream_pkg.vhd b/libraries/base/dp/src/vhdl/dp_stream_pkg.vhd
index e1fc62ec2221605273d8b325d3f8f50bea656594..2f0b97c6a1ad3b83ca518b53007a9de1c13117a3 100644
--- a/libraries/base/dp/src/vhdl/dp_stream_pkg.vhd
+++ b/libraries/base/dp/src/vhdl/dp_stream_pkg.vhd
@@ -397,6 +397,10 @@ PACKAGE dp_stream_pkg Is
   -- Deconcatenate data and complex re,im fields from SOSI into SOSI array
   FUNCTION func_dp_stream_deconcat(snk_in      : t_dp_sosi; nof_streams, data_w : NATURAL) RETURN t_dp_sosi_arr; -- Deconcat SOSI data
   FUNCTION func_dp_stream_deconcat(src_out_arr : t_dp_siso_arr) RETURN t_dp_siso; -- Wire SISO_ARR(0) to single SISO 
+
+  -- Return TRUE when the sosi.data of both streams matches (and is valid)
+  FUNCTION func_dp_data_match(snk_in_a, snk_in_b: t_dp_sosi; data_w: NATURAL) RETURN BOOLEAN;
+  FUNCTION func_dp_data_match(snk_in_a, snk_in_b, snk_in_c: t_dp_sosi; data_w: NATURAL) RETURN BOOLEAN; 
   
 END dp_stream_pkg;
 
@@ -1519,5 +1523,25 @@ PACKAGE BODY dp_stream_pkg IS
     RETURN src_out_arr(0);
   END;
 
+  -- Return TRUE when the sosi.data of both streams matches (and is valid)
+  FUNCTION func_dp_data_match(snk_in_a, snk_in_b: t_dp_sosi; data_w : NATURAL) RETURN BOOLEAN IS
+    VARIABLE result : BOOLEAN;
+  BEGIN
+    result := FALSE;
+    IF snk_in_a.valid='1' AND snk_in_b.valid='1' THEN
+      IF snk_in_a.data(data_w-1 DOWNTO 0) = snk_in_b.data(data_w-1 DOWNTO 0) THEN
+        result := TRUE;
+      END IF;
+    END IF;
+    RETURN result;
+  END;
+
+  -- Return TRUE when the sosi.data of all streams matches (and is valid)
+  FUNCTION func_dp_data_match(snk_in_a, snk_in_b, snk_in_c: t_dp_sosi; data_w : NATURAL) RETURN BOOLEAN IS
+  BEGIN
+    RETURN func_dp_data_match(snk_in_a, snk_in_b, data_w) AND func_dp_data_match(snk_in_b, snk_in_c, data_w);
+  END;
+
+
 END dp_stream_pkg;
 
diff --git a/libraries/dsp/st/src/vhdl/st_histogram.vhd b/libraries/dsp/st/src/vhdl/st_histogram.vhd
index 53cb63abfb3e46298ade0117a9a70a15624d0dd7..d4b03cbe954934f1663eb49f95474e5d67025f0c 100644
--- a/libraries/dsp/st/src/vhdl/st_histogram.vhd
+++ b/libraries/dsp/st/src/vhdl/st_histogram.vhd
@@ -137,7 +137,7 @@ ARCHITECTURE rtl OF st_histogram IS
   -- snk_in_reg_arr
   -------------------------------------------------------------------------------
   CONSTANT c_ram_rd_wr_latency : NATURAL := 3; -- RAM read,incr,write cycle latency
-  CONSTANT c_shiftreg_depth    : NATURAL := c_ram_rd_wr_latency+1;
+  CONSTANT c_shiftreg_depth    : NATURAL := c_ram_rd_wr_latency;
 
   SIGNAL snk_in_reg_arr     : t_dp_sosi_arr(c_shiftreg_depth DOWNTO 0);
   SIGNAL nxt_snk_in_reg_arr : t_dp_sosi_arr(c_shiftreg_depth DOWNTO 0);
@@ -237,19 +237,15 @@ BEGIN
   -- . With a RAM read->write latency of 3 cycles (c_ram_rd_wr_latency), we need 
   --   a shift register of 4 words (0,1,2,3) deep to prevent simultaneous 
   --   read/writes on the RAM.
-  --   . Element 3 is only and output register
+  --   . Element 3 is only an output register, elements 0,1,2 are compared for
+  --     matching data.
   -- . A sequence of duplicate data could cross a sync period:
-  --   . We need to stop&restart counting duplicates on a sync, don't count
-  --     across sync periods to ensure exactly correct bin values in each sync 
-  --     interval
-  --     . We can still get a read on cycle n and a write on cycle n+2 on the 
-  --       same address, but that does not matter as the read,write will be on
-  --       different RAM blocks (1 RAM block per sync period).
-  --     . snk_in_reg_arr(0).sync='1' : Don't compare with older snk_in_reg_arr(1)
-  --       and (2)
-  --     . snk_in_reg_arr(1).sync='1' : Don't compare with older (2)
-  --     . snk_in_reg_arr(2).sync='1' : OK to compare with both (1) and (0)
-  -- . Input : snk_in
+  --   . Don't count across sync periods to ensure exactly correct bin values
+  --     in each sync interval.
+  --   . We can still get a read on cycle n and a write on cycle n+2 on the 
+  --     same address, but that does not matter as the read,write will be on
+  --     different RAM blocks (1 RAM block per sync period).
+  -- . Input : snk_in, snk_in_data
   -- . Output: snk_in_reg
   -------------------------------------------------------------------------------
   p_nxt_snk_in_reg_arr: PROCESS(snk_in, snk_in_data, snk_in_reg_arr) IS
@@ -260,7 +256,7 @@ BEGIN
 
     IF snk_in.valid='1' THEN
       -- The base function is a shift register
-      nxt_snk_in_reg_arr(0)      <= snk_in;
+      nxt_snk_in_reg_arr(0) <= snk_in;
       nxt_snk_in_reg_arr(0).data(c_ram_adr_w-1 DOWNTO 0) <= snk_in_data; -- Use the ranged data
       nxt_snk_in_reg_arr(1) <= snk_in_reg_arr(0);
       nxt_snk_in_reg_arr(2) <= snk_in_reg_arr(1);
@@ -269,40 +265,22 @@ BEGIN
       -- Assign a count of 1 to valid data 
       nxt_snk_in_reg_arr(0).channel <= TO_DP_CHANNEL(1);
 
-      IF snk_in_reg_arr(2).valid = '1' THEN -- Shift register 0,1,2 filled with valid data
-        -- Overwrite channel field (=count) when duplicate data is found
-        IF snk_in_reg_arr(1).data(g_data_w-1 DOWNTO 0) = snk_in_reg_arr(2).data(g_data_w-1 DOWNTO 0) THEN
-          -- 1=2
-          IF snk_in_reg_arr(1).sync = '0' THEN -- Don't count across sync periods
-            nxt_snk_in_reg_arr(2).valid   <= '0';
-            nxt_snk_in_reg_arr(2).channel <= TO_DP_CHANNEL(0);
-            nxt_snk_in_reg_arr(3).channel <= TO_DP_CHANNEL(2);
-          END IF;
-        END IF;
-        IF snk_in_reg_arr(0).data(g_data_w-1 DOWNTO 0) = snk_in_reg_arr(1).data(g_data_w-1 DOWNTO 0) THEN
-          IF snk_in_reg_arr(0).sync = '0' THEN -- Don't count across sync periods
-            IF snk_in_reg_arr(1).data(g_data_w-1 DOWNTO 0) = snk_in_reg_arr(2).data(g_data_w-1 DOWNTO 0) THEN
-              -- 0=1=2
-              IF snk_in_reg_arr(1).sync = '0' THEN -- Don't count across sync periods
-                nxt_snk_in_reg_arr(1).valid   <= '0';
-                nxt_snk_in_reg_arr(1).channel <= TO_DP_CHANNEL(0);
-                nxt_snk_in_reg_arr(2).valid   <= '0'; 
-                nxt_snk_in_reg_arr(2).channel <= TO_DP_CHANNEL(0);
-                nxt_snk_in_reg_arr(3).channel <= TO_DP_CHANNEL(3);
-              END IF;
-            ELSE
-              -- 0=1
-              -- Do nothing, otherwise we will never see 0=1=2. Instead wait until 0,1 shifted to 1,2.
-            END IF;
-          END IF;
-        ELSIF snk_in_reg_arr(0).data(g_data_w-1 DOWNTO 0) = snk_in_reg_arr(2).data(g_data_w-1 DOWNTO 0) THEN
-          -- 0=2
-          IF snk_in_reg_arr(0).sync = '0' THEN -- Don't count across sync periods
-            nxt_snk_in_reg_arr(1).valid   <= '0';
-            nxt_snk_in_reg_arr(1).channel <= TO_DP_CHANNEL(0);
-            nxt_snk_in_reg_arr(3).channel <= TO_DP_CHANNEL(2);
-          END IF;
-        END IF;
+      -- Overwrite channel field (=count) when duplicate data is found
+      -- . Check all possible matches apart from 0==1: simply wait until 0==1 shifts to 1==2.
+      IF func_dp_data_match(snk_in_reg_arr(0), snk_in_reg_arr(1), snk_in_reg_arr(2), g_data_w) AND (snk_in_reg_arr(0).sync='0' AND snk_in_reg_arr(1).sync='0') THEN
+          nxt_snk_in_reg_arr(1).valid   <= '0';
+          nxt_snk_in_reg_arr(1).channel <= TO_DP_CHANNEL(0);
+          nxt_snk_in_reg_arr(2).valid   <= '0'; 
+          nxt_snk_in_reg_arr(2).channel <= TO_DP_CHANNEL(0);
+          nxt_snk_in_reg_arr(3).channel <= TO_DP_CHANNEL(3); -- 0,1,2 match: put count=3 here
+      ELSIF func_dp_data_match(snk_in_reg_arr(1), snk_in_reg_arr(2), g_data_w) AND snk_in_reg_arr(1).sync='0' THEN
+          nxt_snk_in_reg_arr(2).valid   <= '0';
+          nxt_snk_in_reg_arr(2).channel <= TO_DP_CHANNEL(0);
+          nxt_snk_in_reg_arr(3).channel <= TO_DP_CHANNEL(2); -- 1,2 match: put count=2 here
+      ELSIF func_dp_data_match(snk_in_reg_arr(0), snk_in_reg_arr(2), g_data_w) AND (snk_in_reg_arr(0).sync='0' AND snk_in_reg_arr(1).sync='0') THEN
+          nxt_snk_in_reg_arr(1).valid   <= '0';
+          nxt_snk_in_reg_arr(1).channel <= TO_DP_CHANNEL(0);
+          nxt_snk_in_reg_arr(3).channel <= TO_DP_CHANNEL(2); -- 0,2 match: put count=2 here
       END IF;
     END IF;
   END PROCESS;