Skip to content
Snippets Groups Projects
Commit b6b15469 authored by Eric Kooistra's avatar Eric Kooistra
Browse files

Ported dp_flush to RadioHDL.

parent b9a35ced
No related branches found
No related tags found
No related merge requests found
......@@ -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
......
-------------------------------------------------------------------------------
--
-- 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;
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment