From 8a428185dfeac5b215359623b1f231a472f40038 Mon Sep 17 00:00:00 2001
From: Eric Kooistra <kooistra@astron.nl>
Date: Mon, 8 May 2023 16:46:02 +0200
Subject: [PATCH] Add out_en as OUT. Updated description.

---
 libraries/base/dp/src/vhdl/dp_xonoff.vhd | 60 +++++++++++++++++++-----
 1 file changed, 48 insertions(+), 12 deletions(-)

diff --git a/libraries/base/dp/src/vhdl/dp_xonoff.vhd b/libraries/base/dp/src/vhdl/dp_xonoff.vhd
index 9f7f9eccfd..5f200a6e3c 100644
--- a/libraries/base/dp/src/vhdl/dp_xonoff.vhd
+++ b/libraries/base/dp/src/vhdl/dp_xonoff.vhd
@@ -21,11 +21,44 @@
 
 -- Purpose: Add flow XON-XOFF control by flushing frames
 -- Description:
--- . The in_siso.ready = out_siso.ready so passed on unchanged, to support
+--   The dp_xonoff can be applied when the upstream source keeps on producing
+--   blocks of data, because it does not listen to the in_siso.xon = '0'. The
+--   purpose of dp_xonoff.vhd is then to avoid downstream overflow, when the
+--   downstream signals out_siso.xon = '0' to indicate that it cannot accept
+--   more blocks. Therefore the dp_xonoff listens to the out_siso.xon and
+--   flushes (discards) blocks when out_siso.xon = '0'. The dp_xonoff operates
+--   per block, so it takes care that complete blocks are flushed when
+--   out_siso.xon = '0', or passed on when out_siso.xon = '1'. The
+--   in_siso.xon = '1' always, because the dp_xonoff will discard incoming
+--   blocks if they cannot be passed on. When out_siso.xon = '1', then
+--   in_siso.ready <= in_sosi.ready, so passed on. When out_siso.xon = '0',
+--   then in_siso.xon = '1' and in_siso.ready <= '1' (so in_siso =
+--   c_dp_sosi.rdy), because dp_xonoff can flush incoming blocks at maximum
+--   rate, until out_siso.xon = '1' again.
+--
+--   A dp_fifo will keep on outputing blocks when its out_siso.xon = '0',
+--   because it only passes in_siso.xon <= out_siso.xon, so it relies on its
+--   upsteam input to listen to the out_siso.xon. If there are still multiple
+--   blocks in the FIFO then these will be output. Typicaaly it is not
+--   necessary to have a dp_xonoff at the output of the dp_fifo to discard
+--   these blocks, because the dp_fifo does listen to out_siso.ready = '0',
+--   so the flow control per sample will then stop the dp_fifo from causing
+--   downstream overflow.
+--
+--   When a dp_fifo runs almost full within g_fifo_af_margin, then the
+--   in_siso.ready is made '0'. New addition is g_fifo_af_xon that defines a
+--   dp_fifo fill margin for making in_sosi.xon = '0'. If the upstream does
+--   not listen to ready flow control and xon flow control (e.g. like input
+--   from an ADC or a WG), then there may be need for an dp_xonoff at the
+--   input of the FIFO to discard input blocks.
+--
+--   The in_siso.ready = out_siso.ready so passed on unchanged, to support
 --   detailed output to input flow control per cycle. The in_siso.xon is
 --   always '1', because the out_siso.xon is taken care of in this
 --   dp_xonoff.vhd by flushing any in_sosi data when out_siso.xon = '0'.
 --
+-- . Use tb_dp_fifo_xonoff.vhd to verify dp_xonoff to avoid dp_fifo overflow.
+--
 -- . When g_bypass=TRUE then the in and out are wired and the component is void.
 -- . When g_bypass=FALSE then:
 --     The output is ON when flush='0'.
@@ -61,6 +94,7 @@ ENTITY dp_xonoff IS
     -- Frame out
     out_siso      : IN  t_dp_siso;  -- flush control via out_siso.xon
     out_sosi      : OUT t_dp_sosi;
+    out_en        : OUT STD_LOGIC;  -- for monitoring purposes in tb
     -- Optional override to force XOFF ('1' = enable override)
     force_xoff    : IN  STD_LOGIC := '0'
   );
@@ -75,18 +109,20 @@ ARCHITECTURE rtl OF dp_xonoff IS
   SIGNAL flush      : STD_LOGIC;
   SIGNAL nxt_flush  : STD_LOGIC;
   
-  SIGNAL out_en     : STD_LOGIC;
+  SIGNAL i_out_en   : STD_LOGIC;
   SIGNAL nxt_out_en : STD_LOGIC;
   
 BEGIN
 
+  out_en <= i_out_en;
+
   gen_bypass : IF g_bypass=TRUE GENERATE
     in_siso  <= out_siso;
     out_sosi <= in_sosi;
   END GENERATE;
   
   no_bypass : IF g_bypass=FALSE GENERATE
-    in_siso.ready <= out_siso.ready OR (NOT out_en);  -- pass on ready for detailed flow control per cycle only when output is enabled, otherwise ready = 1
+    in_siso.ready <= out_siso.ready OR (NOT i_out_en);  -- pass on ready for detailed flow control per cycle only when output is enabled, otherwise ready = 1
     in_siso.xon <= '1';               -- upstream can remain on, because flush will handle out_siso.xon
     nxt_flush <= NOT out_siso.xon OR force_xoff; -- use xon for flow control at frame level
   
@@ -95,11 +131,11 @@ BEGIN
       IF rst='1' THEN
         frm_busy_reg <= '0';
         flush        <= '0';
-        out_en       <= '1';
+        i_out_en     <= '1';
       ELSIF rising_edge(clk) THEN
         frm_busy_reg <= frm_busy;
         flush        <= nxt_flush;     -- pipeline register flush to ease timing closure
-        out_en       <= nxt_out_en;    -- state register out_en because it can only change between frames
+        i_out_en     <= nxt_out_en;    -- state register out_en because it can only change between frames
       END IF;
     END PROCESS;
 
@@ -114,9 +150,9 @@ BEGIN
       END IF;
     END PROCESS;
 
-    p_out_en : PROCESS(flush, out_en, frm_busy)
+    p_out_en : PROCESS(flush, i_out_en, frm_busy)
     BEGIN
-      nxt_out_en <= out_en;
+      nxt_out_en <= i_out_en;
       IF frm_busy='0' THEN
         IF flush='1' THEN
           nxt_out_en <= '0';
@@ -126,16 +162,16 @@ BEGIN
       END IF;    
     END PROCESS;
     
-    p_out_sosi : PROCESS(in_sosi, out_en)
+    p_out_sosi : PROCESS(in_sosi, i_out_en)
     BEGIN
       -- Pass on sosi data via wires
       out_sosi       <= in_sosi;
       
       -- XON/XOFF flow control via sosi control
-      out_sosi.sync  <= in_sosi.sync  AND out_en;
-      out_sosi.valid <= in_sosi.valid AND out_en;
-      out_sosi.sop   <= in_sosi.sop   AND out_en;
-      out_sosi.eop   <= in_sosi.eop   AND out_en;
+      out_sosi.sync  <= in_sosi.sync  AND i_out_en;
+      out_sosi.valid <= in_sosi.valid AND i_out_en;
+      out_sosi.sop   <= in_sosi.sop   AND i_out_en;
+      out_sosi.eop   <= in_sosi.eop   AND i_out_en;
     END PROCESS;
   END GENERATE;
   
-- 
GitLab