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