From b6b1546909b8bb39e863b959a6660d7f1e35158a Mon Sep 17 00:00:00 2001
From: Erik Kooistra <kooistra@astron.nl>
Date: Thu, 9 Jul 2015 13:48:37 +0000
Subject: [PATCH] Ported dp_flush to RadioHDL.

---
 libraries/base/dp/hdllib.cfg            |   2 +-
 libraries/base/dp/src/vhdl/dp_flush.vhd | 214 ++++++++++++++++++++++++
 2 files changed, 215 insertions(+), 1 deletion(-)
 create mode 100644 libraries/base/dp/src/vhdl/dp_flush.vhd

diff --git a/libraries/base/dp/hdllib.cfg b/libraries/base/dp/hdllib.cfg
index ccbb6e1acf..2400de0e18 100644
--- a/libraries/base/dp/hdllib.cfg
+++ b/libraries/base/dp/hdllib.cfg
@@ -17,7 +17,7 @@ synth_files =
     src/vhdl/dp_frame_busy.vhd
     src/vhdl/dp_frame_busy_arr.vhd
     src/vhdl/dp_xonoff.vhd
-    $UNB/Firmware/modules/dp/src/vhdl/dp_flush.vhd
+    src/vhdl/dp_flush.vhd
     $UNB/Firmware/modules/dp/src/vhdl/dp_latency_increase.vhd
     $UNB/Firmware/modules/dp/src/vhdl/dp_latency_adapter.vhd
     src/vhdl/dp_latency_fifo.vhd
diff --git a/libraries/base/dp/src/vhdl/dp_flush.vhd b/libraries/base/dp/src/vhdl/dp_flush.vhd
new file mode 100644
index 0000000000..064e63e24d
--- /dev/null
+++ b/libraries/base/dp/src/vhdl/dp_flush.vhd
@@ -0,0 +1,214 @@
+-------------------------------------------------------------------------------
+--
+-- Copyright (C) 2011
+-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/>
+-- JIVE (Joint Institute for VLBI in Europe) <http://www.jive.nl/>
+-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
+--
+-- 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/>.
+--
+-------------------------------------------------------------------------------
+
+LIBRARY IEEE, common_lib;
+USE IEEE.std_logic_1164.ALL;
+USE IEEE.numeric_std.ALL;
+USE common_lib.common_pkg.ALL;
+USE work.dp_stream_pkg.ALL;
+
+-- Purpose: Flush snk_in when src_in will be not ready for a long time.
+-- Description:
+--   Provide a stream with an alternative sink when its normal end sink may
+--   be not ready for such a long time that it affects the stream (e.g. fifo's
+--   fill up too much, gaps occur). This component, when enabled, keeps the 
+--   input stream streaming by simply being always ready and discarding the
+--   data (not forwarding the stream to its source output). When disabled, it
+--   does not interfere with the stream in any way.
+--
+--   Four flush modes:
+--   * Streaming mode (both g_framed_xon and g_framed_xoff are FALSE)
+--     When flush_en goes low the output is disabled immediately, but when 
+--     flush_en goes high the output is enabled only after taking account of
+--     the g_ready_latency to avoid that flushed data gets output as valid
+--     data too early.
+--   * Framed mode (both g_framed_xon and g_framed_xoff are TRUE)
+--     When flush_en goes low then the output is disabled at the next
+--     snk_in.sop, to ensure that an ongoing frame does not loose its tail.
+--     When flush_en goes high then the output is enabled at the next
+--     snk_in.sop to ensure that an ongoig frame is not passed on without its
+--     head.
+--   * Only g_framed_xon=TRUE
+--     The output is disabled immediately, but enabled only at a snk_in.sop.
+--   * Only g_framed_xoff=TRUE
+--     The output is disabled at a snk_in.sop, but enabled based on the RL.
+-- Remark:
+-- . This dp_flush supports XON/XOFF control via MM flush_en as well as via the
+--   downstream src_in.xon.
+-- . The snk_out.xon is always '1' so the upsteam components can be always on,
+--   because if necessary this component does flush 
+-- . If g_use_framed_channel = TRUE then the framed xon or xoff also requires
+--   that the channel matches g_framed_channel. Otherwise the g_framed_channel
+--   number is ignored and any sop will affect framed xon or xoff. Use the
+--   actual needed width for g_framed_channel_w to ease timing closure.
+
+
+ENTITY dp_flush IS
+  GENERIC (
+    g_ready_latency      : NATURAL := 1;  -- >= 0
+    g_framed_xon         : BOOLEAN := TRUE;
+    g_framed_xoff        : BOOLEAN := FALSE;
+    g_use_framed_channel : BOOLEAN := FALSE;
+    g_framed_channel_w   : NATURAL := c_dp_stream_channel_w;
+    g_framed_channel     : NATURAL := 0
+  );
+  PORT (
+    rst          : IN  STD_LOGIC;
+    clk          : IN  STD_LOGIC;
+    -- ST sink
+    snk_in       : IN  t_dp_sosi;
+    snk_out      : OUT t_dp_siso;
+    -- ST source
+    src_in       : IN  t_dp_siso;
+    src_out      : OUT t_dp_sosi;
+    -- Enable flush
+    flush_en     : IN  STD_LOGIC := '0'
+  );
+END dp_flush;
+
+
+ARCHITECTURE rtl OF dp_flush IS
+  
+  SIGNAL flush_dly    : STD_LOGIC_VECTOR(0 TO g_ready_latency);  -- use 0 TO high for delay lines, rather than high DOWNTO 0
+  SIGNAL snk_flush    : STD_LOGIC;
+  SIGNAL snk_flush_hi : STD_LOGIC;
+  SIGNAL snk_flush_lo : STD_LOGIC;  
+  SIGNAL src_en       : STD_LOGIC;
+  SIGNAL src_en_hi    : STD_LOGIC;
+  SIGNAL src_en_lo    : STD_LOGIC;  
+  
+BEGIN
+
+  -- Combine MM control flush_en and streaming control src_in.xon
+  flush_dly(0) <= flush_en OR NOT src_in.xon;  -- use flush_dly(0) combinatorially, so that flush_dly supports all g_ready_latency >= 0
+  p_clk : PROCESS(rst, clk)
+  BEGIN
+    IF rst='1' THEN
+      flush_dly(1 TO g_ready_latency) <= (OTHERS=>'0');
+    ELSIF rising_edge(clk) THEN
+      flush_dly(1 TO g_ready_latency) <= flush_dly(0 TO g_ready_latency-1);
+    END IF;
+  END PROCESS;
+  
+  -- Set snk_out.xon
+  snk_out.xon   <= '1';  -- the upsteam components can be always on, because if necessary this component does flush 
+  
+  -- Apply snk_flush to the snk_out.ready
+  snk_out.ready <= src_in.ready OR snk_flush;
+  
+  -- Apply src_en to the src_out control fields  
+  p_src_out : PROCESS(snk_in, src_en)
+  BEGIN
+    src_out       <= snk_in;                    -- default sosi
+    src_out.valid <= snk_in.valid AND src_en;   -- overrule sosi control
+    src_out.sop   <= snk_in.sop   AND src_en;
+    src_out.eop   <= snk_in.eop   AND src_en;
+    src_out.sync  <= snk_in.sync  AND src_en;
+  END PROCESS;
+
+  p_src_en : PROCESS(snk_in, flush_dly)
+    VARIABLE v_hi : STD_LOGIC;
+    VARIABLE v_lo : STD_LOGIC;
+  BEGIN
+    -- for src_en there is no difference for RL = 0 or RL > 0
+    -- default for streaming XON/XOFF control
+    v_lo :=     flush_dly(0);                 -- active flush disables the output immediately
+    v_hi := NOT flush_dly(g_ready_latency);   -- inactive flush must account g_ready_latency before enabling the output again
+    -- account for sop in case of framed XON or framed XOFF control
+    IF g_framed_xoff=TRUE THEN
+      v_lo := v_lo AND snk_in.sop;            -- wait for sop to disable the output, to ensure that the output does not get disabled during a frame
+      IF g_use_framed_channel = TRUE AND UNSIGNED(snk_in.channel(g_framed_channel_w-1 DOWNTO 0))/=g_framed_channel THEN
+        v_lo := '0';
+      END IF;
+    END IF;  
+    IF g_framed_xon=TRUE THEN
+      v_hi := v_hi AND snk_in.sop;            -- wait for sop to enable  the output, to ensure that the output does not get enabled  during a frame
+      IF g_use_framed_channel = TRUE AND UNSIGNED(snk_in.channel(g_framed_channel_w-1 DOWNTO 0))/=g_framed_channel THEN
+        v_hi := '0';
+      END IF;
+    END IF;
+    src_en_lo <= v_lo;
+    src_en_hi <= v_hi;
+  END PROCESS;
+  
+  u_src_en : ENTITY common_lib.common_switch
+  GENERIC MAP (
+    g_rst_level    => '1',
+    g_priority_lo  => TRUE,
+    g_or_high      => TRUE,
+    g_and_low      => TRUE
+  )
+  PORT MAP (
+    rst         => rst,
+    clk         => clk,
+    switch_high => src_en_hi,
+    switch_low  => src_en_lo,
+    out_level   => src_en
+  );
+  
+  p_snk_flush : PROCESS(snk_in, flush_dly)
+    VARIABLE v_hi : STD_LOGIC;
+    VARIABLE v_lo : STD_LOGIC;
+  BEGIN
+    -- for snk_flush there is a difference between RL = 0 and RL > 0, because for RL = 0 it must keep on flushing until there is a valid or even until there is a sop
+    -- default for streaming XON/XOFF control
+    v_hi :=     flush_dly(0);
+    v_lo := NOT flush_dly(0);  -- equivalent snk_flush <= flush_dly(0)
+    IF g_ready_latency=0 THEN
+      v_lo := v_lo AND snk_in.valid;  -- keep on flushing until their is a valid, then stop flushing to let src_in.ready take over the acknowledge flow control
+    END IF;
+    -- account for sop in case of framed XON or framed XOFF control
+    IF g_framed_xoff=TRUE THEN
+      v_hi := v_hi AND snk_in.sop;  -- wait for sop before start flushing the input, to ensure that src_in.ready controls snk_out.ready during the ongoing frame
+      IF g_use_framed_channel = TRUE AND UNSIGNED(snk_in.channel(g_framed_channel_w-1 DOWNTO 0))/=g_framed_channel THEN
+        v_hi := '0';
+      END IF;
+    END IF;  
+    IF g_framed_xon=TRUE THEN
+      IF g_ready_latency=0 THEN
+        v_lo := v_lo AND snk_in.sop;  -- keep on flushing until their is a sop
+        IF g_use_framed_channel = TRUE AND UNSIGNED(snk_in.channel(g_framed_channel_w-1 DOWNTO 0))/=g_framed_channel THEN
+          v_lo := '0';
+        END IF;
+      END IF;
+    END IF;
+    snk_flush_hi <= v_hi;
+    snk_flush_lo <= v_lo;
+  END PROCESS;
+        
+  u_snk_flush : ENTITY common_lib.common_switch
+  GENERIC MAP (
+    g_rst_level    => '1',
+    g_priority_lo  => TRUE,   -- priority does not matter
+    g_or_high      => TRUE,
+    g_and_low      => TRUE
+  )
+  PORT MAP (
+    rst         => rst,
+    clk         => clk,
+    switch_high => snk_flush_hi,
+    switch_low  => snk_flush_lo,
+    out_level   => snk_flush
+  );
+  
+END rtl;
+
-- 
GitLab