diff --git a/libraries/base/dp/src/vhdl/dp_fifo_fill_eop.vhd b/libraries/base/dp/src/vhdl/dp_fifo_fill_eop.vhd
index c8e3d4e667ff1a49202863cf048f982bb954f2f3..b4b591c923ec32c6ddbfbcdb67deae31d4f2fcae 100644
--- a/libraries/base/dp/src/vhdl/dp_fifo_fill_eop.vhd
+++ b/libraries/base/dp/src/vhdl/dp_fifo_fill_eop.vhd
@@ -1,36 +1,38 @@
---------------------------------------------------------------------------------
+-------------------------------------------------------------------------------
 --
--- Copyright (C) 2019
+-- Copyright 2020
 -- 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.
 --
--- This program is free software: you can redistribute it and/or modify
--- it under the terms of the GNU General Public License as published by
--- the Free Software Foundation, either version 3 of the License, or
--- (at your option) any later version.
---
--- This program is distributed in the hope that it will be useful,
--- but WITHOUT ANY WARRANTY; without even the implied warranty of
--- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
--- GNU General Public License for more details.
---
--- You should have received a copy of the GNU General Public License
--- along with this program.  If not, see <http://www.gnu.org/licenses/>.
---
---------------------------------------------------------------------------------
+-------------------------------------------------------------------------------
+
+-------------------------------------------------------------------------------
+-- Author: R. van der Walle
 
 -- Purpose:
 --   The FIFO starts outputting data when the output is ready and it has been
 --   filled with more than g_fifo_fill words or an eop signal has been received. 
---   Given a fixed frame length, this is useful when the in_val is throttled while 
---   the out_val should not be inactive valid between out_sop to out_eop. 
---   This is necessary for frame transport over a PHY link without separate data 
---   valid signal.
+--   This is useful when the in_val is throttled while the out_val should not be 
+--   inactive valid between out_sop to out_eop. This is necessary for frame 
+--   transport over a PHY link without separate data valid signal.
 -- Description:
 --   Modified version of dp_fifo_fill_core. In addition to a frame being available
 --   after the fifo has been filled sufficiently, a frame is also available when
 --   the in_eop has been received earlier than the specified g_fifo_fill. For
 --   more details, please consult the description of dp_fill_fifo_core.
+-------------------------------------------------------------------------------
 
 LIBRARY IEEE, common_lib, technology_lib;
 USE IEEE.std_logic_1164.ALL;
@@ -82,7 +84,6 @@ ENTITY dp_fifo_fill_eop IS
   );
 END dp_fifo_fill_eop;
 
-
 ARCHITECTURE rtl OF dp_fifo_fill_eop IS
 
   CONSTANT c_fifo_rl          : NATURAL := sel_a_b(g_fifo_fill=0, 1, g_fifo_rl);
@@ -99,6 +100,8 @@ ARCHITECTURE rtl OF dp_fifo_fill_eop IS
   CONSTANT s_fill    : STD_LOGIC_VECTOR(1 DOWNTO 0) := "01";
   CONSTANT s_output  : STD_LOGIC_VECTOR(1 DOWNTO 0) := "10";
   CONSTANT s_xoff    : STD_LOGIC_VECTOR(1 DOWNTO 0) := "11";
+
+  CONSTANT c_nof_spulse : NATURAL := 3;
   
   SIGNAL state       : STD_LOGIC_VECTOR(1 DOWNTO 0);  -- t_state
   SIGNAL nxt_state   : STD_LOGIC_VECTOR(1 DOWNTO 0);  -- t_state
@@ -120,9 +123,17 @@ ARCHITECTURE rtl OF dp_fifo_fill_eop IS
   SIGNAL hold_src_in  : t_dp_siso;
   SIGNAL pend_src_out : t_dp_sosi;
  
-  SIGNAL received_eop : BOOLEAN := FALSE;
-  SIGNAL nxt_received_eop : BOOLEAN := FALSE;
-  SIGNAL crossed_domain_snk_in_eop : STD_LOGIC := '0';
+  SIGNAL reg_wr_eop_cnt   : STD_LOGIC_VECTOR(c_word_w-1 DOWNTO 0); 
+  SIGNAL reg_rd_eop_cnt   : STD_LOGIC_VECTOR(c_word_w-1 DOWNTO 0); 
+  SIGNAL wr_eop_done      : STD_LOGIC; 
+  SIGNAL wr_eop_new       : STD_LOGIC; 
+  SIGNAL prev_snk_in_eop  : STD_LOGIC; 
+  SIGNAL rd_eop_new       : STD_LOGIC; 
+  SIGNAL wr_eop_busy      : STD_LOGIC;
+  SIGNAL wr_eop_cnt       : NATURAL := 0;
+  SIGNAL rd_eop_cnt       : NATURAL := 0;
+  SIGNAL eop_cnt          : INTEGER := 0;
+  SIGNAL nxt_eop_cnt      : INTEGER := 0;
 BEGIN
 
   -- Output monitor FIFO filling
@@ -136,7 +147,6 @@ BEGIN
   rd_fill_ctrl <= rd_fill_32b(c_fifo_size_w-1 DOWNTO 0);
 
   gen_dp_fifo_sc : IF g_use_dual_clock=FALSE GENERATE
-    crossed_domain_snk_in_eop <= snk_in.eop;
     u_dp_fifo_sc : ENTITY work.dp_fifo_sc
     GENERIC MAP (
       g_technology     => g_technology,
@@ -172,19 +182,27 @@ BEGIN
     );
     
     wr_fifo_usedw <= rd_fifo_usedw;
+
+    -- No need to transfer eop counter across clock domains
+    rd_eop_cnt     <= wr_eop_cnt;
+    rd_eop_new     <= '1';
+    p_sc: PROCESS(wr_clk, wr_rst)
+    BEGIN
+      IF wr_rst='1' THEN
+        wr_eop_cnt <= 0;
+      ELSIF rising_edge(wr_clk) THEN
+        IF snk_in.eop = '1' THEN
+          wr_eop_cnt <= 1;
+        ELSE
+          wr_eop_cnt <= 0;
+        END IF; 
+      END IF;
+    END PROCESS; 
+
+
   END GENERATE;
   
   gen_dp_fifo_dc : IF g_use_dual_clock=TRUE GENERATE  
-    u_common_spulse : ENTITY common_lib.common_spulse
-    PORT MAP (
-      in_rst  => wr_rst,
-      in_clk  => wr_clk,
-      in_pulse  => snk_in.eop,
-      out_rst => rd_rst,
-      out_clk => rd_clk,
-      out_pulse => crossed_domain_snk_in_eop
-    );
-
     u_dp_fifo_dc : ENTITY work.dp_fifo_dc
     GENERIC MAP (
       g_technology     => g_technology,
@@ -221,6 +239,52 @@ BEGIN
       src_in      => rd_siso,  -- for RL = 0 rd_siso.ready acts as read acknowledge, -- for RL = 1 rd_siso.ready acts as read request
       src_out     => rd_sosi
     );
+
+    -- Transfer eop counter across clock domains
+    reg_wr_eop_cnt <= TO_UVEC(wr_eop_cnt, c_word_w);
+    rd_eop_cnt <= TO_UINT(reg_rd_eop_cnt);
+    u_common_reg_cross_domain : ENTITY common_lib.common_reg_cross_domain
+    PORT MAP (
+      in_rst  => wr_rst,
+      in_clk  => wr_clk,
+      in_dat  => reg_wr_eop_cnt,
+      in_new  => wr_eop_new,
+      in_done => wr_eop_done,
+      out_rst => rd_rst,
+      out_clk => rd_clk,
+      out_dat => reg_rd_eop_cnt,
+      out_new => rd_eop_new
+    );
+
+    p_dc: PROCESS(wr_clk, wr_rst)
+    VARIABLE v_wr_eop_cnt: NATURAL;
+    BEGIN
+      IF wr_rst='1' THEN
+        wr_eop_busy <= '0';
+        wr_eop_cnt <= 0;
+        wr_eop_new <= '0'; 
+      ELSIF rising_edge(wr_clk) THEN
+        v_wr_eop_cnt := wr_eop_cnt;
+        IF wr_eop_done = '1' THEN
+          wr_eop_busy <= '0';
+        END IF;
+
+        IF wr_eop_busy = '0' THEN
+          wr_eop_busy <= '1';
+          wr_eop_new <= '1'; 
+        END IF; 
+
+        IF wr_eop_new = '1' THEN
+          wr_eop_new <= '0';
+          v_wr_eop_cnt := 0;
+        END IF;
+
+        IF snk_in.eop = '1' THEN
+          v_wr_eop_cnt := v_wr_eop_cnt + 1;
+        END IF;
+        wr_eop_cnt <= v_wr_eop_cnt;
+      END IF;
+    END PROCESS;  
   END GENERATE;
     
   no_fill : IF g_fifo_fill=0 GENERATE
@@ -231,33 +295,27 @@ BEGIN
   gen_fill : IF g_fifo_fill>0 GENERATE
  
     src_out <= i_src_out;
-    
+     
     p_rd_clk: PROCESS(rd_clk, rd_rst)
     BEGIN
       IF rd_rst='1' THEN
         xon_reg   <= '0';
         state     <= s_idle;
         i_src_out <= c_dp_sosi_rst;
-        received_eop <= FALSE;
       ELSIF rising_edge(rd_clk) THEN
         xon_reg   <= nxt_xon_reg;
         state     <= nxt_state;
         i_src_out <= nxt_src_out;
-        IF crossed_domain_snk_in_eop = '1' THEN
-          received_eop <= TRUE;
-        ELSE
-          received_eop <= nxt_received_eop;
-        END IF;
+        eop_cnt   <= nxt_eop_cnt;
       END IF;
     END PROCESS;
-    
+     
     nxt_xon_reg <= src_in.xon;  -- register xon to easy timing closure
       
     gen_rl_0 : IF g_fifo_rl=0 GENERATE
-      p_state : PROCESS(state, rd_sosi, src_in, xon_reg, rd_fifo_usedw, rd_fill_ctrl, received_eop)
+      p_state : PROCESS(state, rd_sosi, src_in, xon_reg, rd_fifo_usedw, rd_fill_ctrl, rd_eop_cnt, eop_cnt, rd_eop_new)
       BEGIN
         nxt_state <= state;
-        nxt_received_eop <= received_eop;
         rd_siso <= src_in;  -- default acknowledge (RL=1) this input when output is ready
         
         -- The output register stage increase RL=0 to 1, so it matches RL = 1 for src_in.ready
@@ -267,6 +325,10 @@ BEGIN
         nxt_src_out.eop   <= '0';
         nxt_src_out.sync  <= '0';
 
+        IF rd_eop_new = '1' THEN
+          nxt_eop_cnt <= eop_cnt + rd_eop_cnt;
+        END IF;
+
         CASE state IS
           WHEN s_idle =>
             IF xon_reg='0' THEN
@@ -285,14 +347,18 @@ BEGIN
               nxt_state <= s_xoff;
             ELSE
               -- stop reading until the FIFO has been filled sufficiently
-              IF UNSIGNED(rd_fifo_usedw)<UNSIGNED(rd_fill_ctrl) AND NOT received_eop THEN
+              IF UNSIGNED(rd_fifo_usedw)<UNSIGNED(rd_fill_ctrl) AND eop_cnt <= 0 THEN
                 rd_siso <= c_dp_siso_hold;  -- stop the input, hold the pend_src_out.sop
               ELSE
                 -- if the output is ready, then start outputting the frame
                 IF src_in.ready='1' THEN
                   nxt_src_out <= rd_sosi;  -- output sop that is still at FIFO output (RL=0)
-                  nxt_received_eop <= FALSE;
                   nxt_state <= s_output;
+                  IF rd_eop_new = '1' THEN
+                    nxt_eop_cnt <= eop_cnt + rd_eop_cnt - 1;
+                  ELSE
+                    nxt_eop_cnt <= eop_cnt -1;
+                  END IF;
                 END IF;
               END IF;
             END IF;
@@ -335,10 +401,9 @@ BEGIN
         src_out_reg  => i_src_out
       );
       
-      p_state : PROCESS(state, src_in, xon_reg, pend_src_out, rd_fifo_usedw, rd_fill_ctrl, received_eop)
+      p_state : PROCESS(state, src_in, xon_reg, pend_src_out, rd_fifo_usedw, rd_fill_ctrl, rd_eop_cnt, eop_cnt, rd_eop_new)
       BEGIN
         nxt_state <= state;
-        nxt_received_eop <= received_eop;
 
         hold_src_in <= src_in;  -- default request (RL=1) new input when output is ready
         
@@ -348,6 +413,10 @@ BEGIN
         nxt_src_out.sop   <= '0';
         nxt_src_out.eop   <= '0';
         nxt_src_out.sync  <= '0';
+
+        IF rd_eop_new = '1' THEN
+          nxt_eop_cnt <= eop_cnt + rd_eop_cnt;
+        END IF;
  
         CASE state IS
           WHEN s_idle =>
@@ -367,14 +436,18 @@ BEGIN
               nxt_state <= s_xoff;
             ELSE
               -- stop reading until the FIFO has been filled sufficiently
-              IF UNSIGNED(rd_fifo_usedw)<UNSIGNED(rd_fill_ctrl) AND NOT received_eop THEN
+              IF UNSIGNED(rd_fifo_usedw)<UNSIGNED(rd_fill_ctrl) AND eop_cnt <= 0 THEN
                 hold_src_in <= c_dp_siso_hold;  -- stop the input, hold the pend_src_out.sop
               ELSE
                 -- if the output is ready, then start outputting the input frame
                 IF src_in.ready='1' THEN
                   nxt_src_out <= pend_src_out;  -- output sop that is still pending in dp_hold_input
-                  nxt_received_eop <= FALSE;
                   nxt_state <= s_output;
+                  IF rd_eop_new = '1' THEN
+                    nxt_eop_cnt <= eop_cnt + rd_eop_cnt - 1;
+                  ELSE
+                    nxt_eop_cnt <= eop_cnt -1;
+                  END IF;
                 END IF;
               END IF;
             END IF;