OpenCores
URL https://opencores.org/ocsvn/dp_components/dp_components/trunk

Subversion Repositories dp_components

[/] [dp_components/] [trunk/] [dp_xonoff.vhd] - Rev 4

Compare with Previous | Blame | View Log

-------------------------------------------------------------------------------
--
-- Copyright 2020
-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/>
-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
-- 
-- 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
-- 
--     http://www.apache.org/licenses/LICENSE-2.0
-- 
-- 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.
--
-------------------------------------------------------------------------------
 
-- Purpose: Add flow XON-XOFF control by flushing frames
-- Description:
-- . The in_siso.ready = out_siso.ready so passed on unchanged, to support
--   detailed output to input flow control per cycle. The in_siso.xon is
--   always '1', because the out_siso.xon is taken care of in this
--   dp_xonoff.vhd by flushing any in_sosi data when out_siso.xon = '0'.
--
-- . When g_bypass=TRUE then the in and out are wired and the component is void.
-- . When g_bypass=FALSE then:
--     The output is ON when flush='0'.
--     The output is OFF when flush='1'.
--     The transition from OFF to ON occurs after an in_sosi.eop so between frames
--     The transition from ON to OFF occurs after an in_sosi.eop so between frames
--     Thanks to frm_busy it is also possible to switch between frames, so it
--     is not necessary that first an eop occurs, before the xon can change. 
--     The possibility to switch xon at an eop is needed to be able to switch
--     xon in case there are no gaps between the frames.
-- . The primary control is via out_siso.xon, however there is an option to override
--   the out_siso.xon control and force the output to off by using force_xoff.
-- Remark:
-- . The output controls are not registered.
-- . The xon timing is not cycle critical therefor register flush to ease
--   timing closure
-- . Originally based on rad_frame_onoff from LOFAR RSP firmware
 
LIBRARY IEEE, dp_pkg_lib;
USE IEEE.std_logic_1164.ALL;
USE dp_pkg_lib.dp_stream_pkg.ALL;
 
ENTITY dp_xonoff IS
  GENERIC (
    g_bypass : BOOLEAN := FALSE
  );
  PORT (
    rst           : IN  STD_LOGIC;
    clk           : IN  STD_LOGIC;
    -- Frame in
    in_siso       : OUT t_dp_siso;
    in_sosi       : IN  t_dp_sosi;
    -- Frame out
    out_siso      : IN  t_dp_siso;  -- flush control via out_siso.xon
    out_sosi      : OUT t_dp_sosi;
    -- Optional override to force XOFF ('1' = enable override)
    force_xoff    : IN  STD_LOGIC := '0'
  );
END dp_xonoff;
 
 
ARCHITECTURE rtl OF dp_xonoff IS
 
  SIGNAL frm_busy     : STD_LOGIC;
  SIGNAL frm_busy_reg : STD_LOGIC;
 
  SIGNAL flush      : STD_LOGIC;
  SIGNAL nxt_flush  : STD_LOGIC;
 
  SIGNAL out_en     : STD_LOGIC;
  SIGNAL nxt_out_en : STD_LOGIC;
 
BEGIN
 
  gen_bypass : IF g_bypass=TRUE GENERATE
    in_siso  <= out_siso;
    out_sosi <= in_sosi;
  END GENERATE;
 
  no_bypass : IF g_bypass=FALSE GENERATE
    in_siso.ready <= out_siso.ready;  -- pass on ready for detailed flow control per cycle
    in_siso.xon <= '1';               -- upstream can remain on, because flush will handle out_siso.xon
    nxt_flush <= NOT out_siso.xon OR force_xoff; -- use xon for flow control at frame level
 
    p_clk: PROCESS(clk, rst)
    BEGIN
      IF rst='1' THEN
        frm_busy_reg <= '0';
        flush        <= '0';
        out_en       <= '1';
      ELSIF rising_edge(clk) THEN
        frm_busy_reg <= frm_busy;
        flush        <= nxt_flush;     -- pipeline register flush to ease timing closure
        out_en       <= nxt_out_en;    -- state register out_en because it can only change between frames
      END IF;
    END PROCESS;
 
    -- Detect in_sosi frame busy, frm_busy is '1' from sop including sop, until eop excluding eop
    p_frm_busy : PROCESS(in_sosi, in_sosi, frm_busy_reg)
    BEGIN
      frm_busy <= frm_busy_reg;
      IF in_sosi.sop='1' THEN
        frm_busy <= '1';
      ELSIF in_sosi.eop='1' THEN
        frm_busy <= '0';
      END IF;
    END PROCESS;
 
    p_out_en : PROCESS(flush, out_en, frm_busy)
    BEGIN
      nxt_out_en <= out_en;
      IF frm_busy='0' THEN
        IF flush='1' THEN
          nxt_out_en <= '0';
        ELSE
          nxt_out_en <= '1';
        END IF;
      END IF;    
    END PROCESS;
 
    p_out_sosi : PROCESS(in_sosi, out_en)
    BEGIN
      -- Pass on sosi data via wires
      out_sosi       <= in_sosi;
 
      -- XON/XOFF flow control via sosi control
      out_sosi.sync  <= in_sosi.sync  AND out_en;
      out_sosi.valid <= in_sosi.valid AND out_en;
      out_sosi.sop   <= in_sosi.sop   AND out_en;
      out_sosi.eop   <= in_sosi.eop   AND out_en;
    END PROCESS;
  END GENERATE;
 
END ARCHITECTURE;
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.