From b96563e11dc57e763e4ec470590256ed4f4c0a95 Mon Sep 17 00:00:00 2001
From: Erik Kooistra <kooistra@astron.nl>
Date: Wed, 6 May 2015 11:51:39 +0000
Subject: [PATCH] Ported dp_gap.vhd to $RADIOHDL, because now snk_out also
 passes on src_in.xon.

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

diff --git a/libraries/base/dp/hdllib.cfg b/libraries/base/dp/hdllib.cfg
index b52394c2d5..ccbb6e1acf 100644
--- a/libraries/base/dp/hdllib.cfg
+++ b/libraries/base/dp/hdllib.cfg
@@ -78,7 +78,7 @@ synth_files =
     $UNB/Firmware/modules/dp/src/vhdl/dp_packet_enc_channel_lo.vhd
     $UNB/Firmware/modules/dp/src/vhdl/dp_packet_dec.vhd
     $UNB/Firmware/modules/dp/src/vhdl/dp_packet_dec_channel_lo.vhd
-    $UNB/Firmware/modules/dp/src/vhdl/dp_gap.vhd
+    src/vhdl/dp_gap.vhd
     $UNB/Firmware/modules/dp/src/vhdl/dp_mon.vhd
     $UNB/Firmware/modules/dp/src/vhdl/dp_bsn_monitor.vhd
     $UNB/Firmware/modules/dp/src/vhdl/dp_bsn_monitor_reg.vhd
diff --git a/libraries/base/dp/src/vhdl/dp_gap.vhd b/libraries/base/dp/src/vhdl/dp_gap.vhd
new file mode 100644
index 0000000000..a98cb37ded
--- /dev/null
+++ b/libraries/base/dp/src/vhdl/dp_gap.vhd
@@ -0,0 +1,154 @@
+-------------------------------------------------------------------------------
+--
+-- Copyright (C) 2012
+-- 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/>.
+--
+-------------------------------------------------------------------------------
+
+-- Purpose: Deassert snk_out.ready to greate gaps in source output.
+--
+-- Description:
+-- . g_dat_len indicates the maximum number of valid data cycles.
+--   During the last of these valid cycles, snk_out.ready is deasserted so
+--   g_gap_len invalid cycles are produced at the source.
+-- 
+-- Remark:
+-- . If a gap of sufficient (g_gap_len) length occured by itself (without
+--   dp_gap de-asserting snk_out.ready, this gap is accounted for and
+--   dp_gap will restart counting valid cycles as soon as the first
+--   valid data work comes in.
+
+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;
+
+ENTITY dp_gap IS
+  GENERIC (
+    g_dat_len    : NATURAL := 1000000;
+    g_gap_len    : NATURAL := 5;
+    g_gap_extend : BOOLEAN := FALSE -- if TRUE, the first valid='0' cycle is extended to g_gap_len by de-assertion of snk_out.ready.
+    );                              -- This results in all gaps having a minimum length of g_gap_len.
+  PORT (
+    clk       : IN STD_LOGIC;
+    rst       : IN STD_LOGIC;
+    -- ST sink
+    snk_out   : OUT t_dp_siso;
+    snk_in    : IN  t_dp_sosi;
+    -- ST source
+    src_in    : IN  t_dp_siso;
+    src_out   : OUT t_dp_sosi
+  );
+END dp_gap;
+
+ARCHITECTURE rtl OF dp_gap IS
+
+  CONSTANT c_dat_len_w : NATURAL := ceil_log2(g_dat_len);
+  CONSTANT c_gap_len_w : NATURAL := ceil_log2(largest(g_gap_len, 1));
+
+  TYPE t_state_enum IS (s_wait_for_val, s_counting, s_force_not_rdy);
+
+  SIGNAL state         : t_state_enum;
+  SIGNAL nxt_state     : t_state_enum; 
+
+  SIGNAL clk_cnt       : STD_LOGIC_VECTOR(c_dat_len_w-1 DOWNTO 0);
+  SIGNAL nxt_clk_cnt   : STD_LOGIC_VECTOR(c_dat_len_w-1 DOWNTO 0);
+
+  SIGNAL gap_cnt       : STD_LOGIC_VECTOR(c_gap_len_w-1 DOWNTO 0);
+  SIGNAL nxt_gap_cnt   : STD_LOGIC_VECTOR(c_gap_len_w-1 DOWNTO 0);
+
+BEGIN
+
+  src_out <= snk_in;
+
+  gen_rtl : IF g_gap_len>0 GENERATE
+
+    p_clk : PROCESS(clk, rst)
+    BEGIN
+      IF rst='1' THEN
+        state               <= s_wait_for_val;  
+        clk_cnt             <= (OTHERS=>'0');
+        gap_cnt             <= (OTHERS=>'0');
+      ELSIF rising_edge(clk) THEN
+        state               <= nxt_state;
+        clk_cnt             <= nxt_clk_cnt;
+        gap_cnt             <= nxt_gap_cnt;
+      END IF;
+    END PROCESS;
+  
+    p_state : PROCESS(state, clk_cnt, gap_cnt, snk_in, src_in)
+    BEGIN  
+      nxt_state     <= state;  
+      nxt_clk_cnt   <= clk_cnt;
+      nxt_gap_cnt   <= gap_cnt;
+      snk_out       <= src_in;  -- Pass on the flow control by default
+  
+      CASE state IS
+       
+      WHEN s_wait_for_val => -- Wait for valid data to come in 
+        IF snk_in.valid = '1' THEN
+          nxt_clk_cnt <= TO_UVEC(1, c_dat_len_w);
+          nxt_gap_cnt <= (OTHERS=>'0');
+          nxt_state   <= s_counting;
+        END IF;   
+      
+      WHEN s_counting => -- Start counting cycles 
+        nxt_clk_cnt <= INCR_UVEC(clk_cnt, 1); 
+        IF clk_cnt = TO_UVEC(g_dat_len-1, c_dat_len_w) THEN -- time to force a gap  
+          nxt_state     <= s_force_not_rdy; 
+          snk_out.ready <= '0';
+          nxt_clk_cnt   <= TO_UVEC(1, c_dat_len_w); -- we already have 1 clk cycle with ready='0' here
+        END IF;
+        IF snk_in.valid = '0' THEN -- Also start counting any invalid cycles
+          IF g_gap_extend = TRUE THEN 
+            snk_out.ready <= '0'; -- Keep ready de-asserted. Gap_cnt will increment so it will be released again after g_gap_len.
+          END IF;   
+          nxt_gap_cnt <= INCR_UVEC(gap_cnt, 1);      
+        ELSE
+          nxt_gap_cnt <= (OTHERS=>'0');
+        END IF;
+        IF gap_cnt = TO_UVEC(g_gap_len-1, c_gap_len_w) AND snk_in.valid = '0' THEN -- A gap of sufficient length occured by itself (or valid='0' was extended); no need to force gap      
+        -- We've counted g_gap_len-1, plus the current gap cycle = g_gap_len 
+          nxt_gap_cnt <= (OTHERS=>'0');
+          nxt_clk_cnt <= (OTHERS=>'0');
+          nxt_state   <= s_wait_for_val;
+          IF g_gap_extend = TRUE THEN 
+            snk_out.ready <= src_in.ready; -- Release the ready signal again if it was forced down because of gap extension
+          END IF;
+        END IF;
+    
+      WHEN s_force_not_rdy => -- Force snk_out.ready to '0' for g_gap_len clk cycles
+        snk_out.ready <= '0';
+        nxt_clk_cnt <= INCR_UVEC(clk_cnt, 1);   
+        IF clk_cnt = TO_UVEC(g_gap_len-1, c_dat_len_w) THEN
+          nxt_state   <= s_wait_for_val;
+          nxt_clk_cnt <= (OTHERS=>'0');
+        END IF;
+          
+      END CASE;
+    END PROCESS;
+
+  END GENERATE;
+
+  no_rtl : IF g_gap_len=0 GENERATE  -- bypass
+    snk_out <= src_in;
+  END GENERATE;
+
+END rtl;
+
-- 
GitLab