Skip to content
Snippets Groups Projects
Commit c0937440 authored by Reinier van der Walle's avatar Reinier van der Walle
Browse files

Updated dp_fifo_fill_eop

Implemented new eop mechanism according to L2SDP-28
parent 34e09755
No related branches found
No related tags found
1 merge request!11Resolve L2SDP-28
--------------------------------------------------------------------------------
-------------------------------------------------------------------------------
--
-- Copyright (C) 2019
-- Copyright 2020
-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.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.
-- Licensed under the Apache License, Version 2.0 (the "License");
-- you may not use this file except in compliance with the License.
-- You may obtain a copy of the License at
--
-- 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.
-- http://www.apache.org/licenses/LICENSE-2.0
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
-- Unless required by applicable law or agreed to in writing, software
-- distributed under the License is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-- See the License for the specific language governing permissions and
-- limitations under the License.
--
--------------------------------------------------------------------------------
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
-- Author: R. van der Walle
-- Purpose:
-- The FIFO starts outputting data when the output is ready and it has been
-- filled with more than g_fifo_fill words or an eop signal has been received.
-- Given a fixed frame length, this is useful when the in_val is throttled while
-- the out_val should not be inactive valid between out_sop to out_eop.
-- This is necessary for frame transport over a PHY link without separate data
-- valid signal.
-- This is useful when the in_val is throttled while the out_val should not be
-- inactive valid between out_sop to out_eop. This is necessary for frame
-- transport over a PHY link without separate data valid signal.
-- Description:
-- Modified version of dp_fifo_fill_core. In addition to a frame being available
-- after the fifo has been filled sufficiently, a frame is also available when
-- the in_eop has been received earlier than the specified g_fifo_fill. For
-- more details, please consult the description of dp_fill_fifo_core.
-------------------------------------------------------------------------------
LIBRARY IEEE, common_lib, technology_lib;
USE IEEE.std_logic_1164.ALL;
......@@ -82,7 +84,6 @@ ENTITY dp_fifo_fill_eop IS
);
END dp_fifo_fill_eop;
ARCHITECTURE rtl OF dp_fifo_fill_eop IS
CONSTANT c_fifo_rl : NATURAL := sel_a_b(g_fifo_fill=0, 1, g_fifo_rl);
......@@ -100,6 +101,8 @@ ARCHITECTURE rtl OF dp_fifo_fill_eop IS
CONSTANT s_output : STD_LOGIC_VECTOR(1 DOWNTO 0) := "10";
CONSTANT s_xoff : STD_LOGIC_VECTOR(1 DOWNTO 0) := "11";
CONSTANT c_nof_spulse : NATURAL := 3;
SIGNAL state : STD_LOGIC_VECTOR(1 DOWNTO 0); -- t_state
SIGNAL nxt_state : STD_LOGIC_VECTOR(1 DOWNTO 0); -- t_state
......@@ -120,9 +123,17 @@ ARCHITECTURE rtl OF dp_fifo_fill_eop IS
SIGNAL hold_src_in : t_dp_siso;
SIGNAL pend_src_out : t_dp_sosi;
SIGNAL received_eop : BOOLEAN := FALSE;
SIGNAL nxt_received_eop : BOOLEAN := FALSE;
SIGNAL crossed_domain_snk_in_eop : STD_LOGIC := '0';
SIGNAL reg_wr_eop_cnt : STD_LOGIC_VECTOR(c_word_w-1 DOWNTO 0);
SIGNAL reg_rd_eop_cnt : STD_LOGIC_VECTOR(c_word_w-1 DOWNTO 0);
SIGNAL wr_eop_done : STD_LOGIC;
SIGNAL wr_eop_new : STD_LOGIC;
SIGNAL prev_snk_in_eop : STD_LOGIC;
SIGNAL rd_eop_new : STD_LOGIC;
SIGNAL wr_eop_busy : STD_LOGIC;
SIGNAL wr_eop_cnt : NATURAL := 0;
SIGNAL rd_eop_cnt : NATURAL := 0;
SIGNAL eop_cnt : INTEGER := 0;
SIGNAL nxt_eop_cnt : INTEGER := 0;
BEGIN
-- Output monitor FIFO filling
......@@ -136,7 +147,6 @@ BEGIN
rd_fill_ctrl <= rd_fill_32b(c_fifo_size_w-1 DOWNTO 0);
gen_dp_fifo_sc : IF g_use_dual_clock=FALSE GENERATE
crossed_domain_snk_in_eop <= snk_in.eop;
u_dp_fifo_sc : ENTITY work.dp_fifo_sc
GENERIC MAP (
g_technology => g_technology,
......@@ -172,19 +182,27 @@ BEGIN
);
wr_fifo_usedw <= rd_fifo_usedw;
-- No need to transfer eop counter across clock domains
rd_eop_cnt <= wr_eop_cnt;
rd_eop_new <= '1';
p_sc: PROCESS(wr_clk, wr_rst)
BEGIN
IF wr_rst='1' THEN
wr_eop_cnt <= 0;
ELSIF rising_edge(wr_clk) THEN
IF snk_in.eop = '1' THEN
wr_eop_cnt <= 1;
ELSE
wr_eop_cnt <= 0;
END IF;
END IF;
END PROCESS;
END GENERATE;
gen_dp_fifo_dc : IF g_use_dual_clock=TRUE GENERATE
u_common_spulse : ENTITY common_lib.common_spulse
PORT MAP (
in_rst => wr_rst,
in_clk => wr_clk,
in_pulse => snk_in.eop,
out_rst => rd_rst,
out_clk => rd_clk,
out_pulse => crossed_domain_snk_in_eop
);
u_dp_fifo_dc : ENTITY work.dp_fifo_dc
GENERIC MAP (
g_technology => g_technology,
......@@ -221,6 +239,52 @@ BEGIN
src_in => rd_siso, -- for RL = 0 rd_siso.ready acts as read acknowledge, -- for RL = 1 rd_siso.ready acts as read request
src_out => rd_sosi
);
-- Transfer eop counter across clock domains
reg_wr_eop_cnt <= TO_UVEC(wr_eop_cnt, c_word_w);
rd_eop_cnt <= TO_UINT(reg_rd_eop_cnt);
u_common_reg_cross_domain : ENTITY common_lib.common_reg_cross_domain
PORT MAP (
in_rst => wr_rst,
in_clk => wr_clk,
in_dat => reg_wr_eop_cnt,
in_new => wr_eop_new,
in_done => wr_eop_done,
out_rst => rd_rst,
out_clk => rd_clk,
out_dat => reg_rd_eop_cnt,
out_new => rd_eop_new
);
p_dc: PROCESS(wr_clk, wr_rst)
VARIABLE v_wr_eop_cnt: NATURAL;
BEGIN
IF wr_rst='1' THEN
wr_eop_busy <= '0';
wr_eop_cnt <= 0;
wr_eop_new <= '0';
ELSIF rising_edge(wr_clk) THEN
v_wr_eop_cnt := wr_eop_cnt;
IF wr_eop_done = '1' THEN
wr_eop_busy <= '0';
END IF;
IF wr_eop_busy = '0' THEN
wr_eop_busy <= '1';
wr_eop_new <= '1';
END IF;
IF wr_eop_new = '1' THEN
wr_eop_new <= '0';
v_wr_eop_cnt := 0;
END IF;
IF snk_in.eop = '1' THEN
v_wr_eop_cnt := v_wr_eop_cnt + 1;
END IF;
wr_eop_cnt <= v_wr_eop_cnt;
END IF;
END PROCESS;
END GENERATE;
no_fill : IF g_fifo_fill=0 GENERATE
......@@ -238,26 +302,20 @@ BEGIN
xon_reg <= '0';
state <= s_idle;
i_src_out <= c_dp_sosi_rst;
received_eop <= FALSE;
ELSIF rising_edge(rd_clk) THEN
xon_reg <= nxt_xon_reg;
state <= nxt_state;
i_src_out <= nxt_src_out;
IF crossed_domain_snk_in_eop = '1' THEN
received_eop <= TRUE;
ELSE
received_eop <= nxt_received_eop;
END IF;
eop_cnt <= nxt_eop_cnt;
END IF;
END PROCESS;
nxt_xon_reg <= src_in.xon; -- register xon to easy timing closure
gen_rl_0 : IF g_fifo_rl=0 GENERATE
p_state : PROCESS(state, rd_sosi, src_in, xon_reg, rd_fifo_usedw, rd_fill_ctrl, received_eop)
p_state : PROCESS(state, rd_sosi, src_in, xon_reg, rd_fifo_usedw, rd_fill_ctrl, rd_eop_cnt, eop_cnt, rd_eop_new)
BEGIN
nxt_state <= state;
nxt_received_eop <= received_eop;
rd_siso <= src_in; -- default acknowledge (RL=1) this input when output is ready
-- The output register stage increase RL=0 to 1, so it matches RL = 1 for src_in.ready
......@@ -267,6 +325,10 @@ BEGIN
nxt_src_out.eop <= '0';
nxt_src_out.sync <= '0';
IF rd_eop_new = '1' THEN
nxt_eop_cnt <= eop_cnt + rd_eop_cnt;
END IF;
CASE state IS
WHEN s_idle =>
IF xon_reg='0' THEN
......@@ -285,14 +347,18 @@ BEGIN
nxt_state <= s_xoff;
ELSE
-- stop reading until the FIFO has been filled sufficiently
IF UNSIGNED(rd_fifo_usedw)<UNSIGNED(rd_fill_ctrl) AND NOT received_eop THEN
IF UNSIGNED(rd_fifo_usedw)<UNSIGNED(rd_fill_ctrl) AND eop_cnt <= 0 THEN
rd_siso <= c_dp_siso_hold; -- stop the input, hold the pend_src_out.sop
ELSE
-- if the output is ready, then start outputting the frame
IF src_in.ready='1' THEN
nxt_src_out <= rd_sosi; -- output sop that is still at FIFO output (RL=0)
nxt_received_eop <= FALSE;
nxt_state <= s_output;
IF rd_eop_new = '1' THEN
nxt_eop_cnt <= eop_cnt + rd_eop_cnt - 1;
ELSE
nxt_eop_cnt <= eop_cnt -1;
END IF;
END IF;
END IF;
END IF;
......@@ -335,10 +401,9 @@ BEGIN
src_out_reg => i_src_out
);
p_state : PROCESS(state, src_in, xon_reg, pend_src_out, rd_fifo_usedw, rd_fill_ctrl, received_eop)
p_state : PROCESS(state, src_in, xon_reg, pend_src_out, rd_fifo_usedw, rd_fill_ctrl, rd_eop_cnt, eop_cnt, rd_eop_new)
BEGIN
nxt_state <= state;
nxt_received_eop <= received_eop;
hold_src_in <= src_in; -- default request (RL=1) new input when output is ready
......@@ -349,6 +414,10 @@ BEGIN
nxt_src_out.eop <= '0';
nxt_src_out.sync <= '0';
IF rd_eop_new = '1' THEN
nxt_eop_cnt <= eop_cnt + rd_eop_cnt;
END IF;
CASE state IS
WHEN s_idle =>
IF xon_reg='0' THEN
......@@ -367,14 +436,18 @@ BEGIN
nxt_state <= s_xoff;
ELSE
-- stop reading until the FIFO has been filled sufficiently
IF UNSIGNED(rd_fifo_usedw)<UNSIGNED(rd_fill_ctrl) AND NOT received_eop THEN
IF UNSIGNED(rd_fifo_usedw)<UNSIGNED(rd_fill_ctrl) AND eop_cnt <= 0 THEN
hold_src_in <= c_dp_siso_hold; -- stop the input, hold the pend_src_out.sop
ELSE
-- if the output is ready, then start outputting the input frame
IF src_in.ready='1' THEN
nxt_src_out <= pend_src_out; -- output sop that is still pending in dp_hold_input
nxt_received_eop <= FALSE;
nxt_state <= s_output;
IF rd_eop_new = '1' THEN
nxt_eop_cnt <= eop_cnt + rd_eop_cnt - 1;
ELSE
nxt_eop_cnt <= eop_cnt -1;
END IF;
END IF;
END IF;
END IF;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment