Skip to content
Snippets Groups Projects
dp_add_flow_control.vhd 6.29 KiB
Newer Older
--------------------------------------------------------------------------------
--
-- Copyright (C) 2023
-- 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.
--
-- 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: Provide flow control
-- Description:
-- . This component can add src_in.ready flow control to a logic function
--   that no flow control.
-- - If g_use_ready = false, then src_in is ignored, so no flow control is
--   added and the dp_add_flow_control component reduces to wires.
-- - If g_use_ready = true then use flow control by src_in.ready.
--   . If g_pipeline_ready = false then dp_add_flow_control = dp_pipeline,
--     and then snk_in and src_in.ready are used combinatorially by
--     dp_pipeline.
--   . If g_pipeline_ready = true then dp_add_flow_control = dp_pipeline_ready,
--     and then the registered input snk_in_reg is used and the src_in.ready
--     is registered.
--
-- . The block diagram shows how the dp_add_flow_control is used.
--
--                            g_use_ready
--                            g_pipeline_ready
--                            g_in_latency
--                            g_out_latency
--                           _____________________
--                          | dp_add_flow_control |
--                          |                     |
--   snk_out <--------------| snk_out      src_in |<---------- src_in
--                          |                     |
--             d.src_out -->| snk_in       src_out|--> src_out
--             r.src_out -->| snk_in_reg          |
--                          |_____________________|
--
--                     ________            _______
--                    /        \          |       |
--   snk_in --------->| p_comb | --> d -->| p_reg |--> r
--                    \________/          |_______|
--                         |                  |
--                         \-----------<------/
--
-- . The logic function is implemented in combinatorial process p_comb and the
--   internal state of it is kept in a clocked process p_reg.
-- . The p_reg increases the ready latency (RL) of p_reg.src_out by 1, because
--   p_comb does not use src_in.ready. Instead p_comb drives d.src_out based
--   on the snk_in.sop, eop, valid.
--   - With g_use_ready = true and g_pipeline_ready = true use a
--     dp_pipeline_ready to restore the RL from 2 to 1 for the src_out output.
--     With the dp_pipeline_ready a few register stages are needed to store
--     src_out to be able to adapt the RL and to be able to register the
--     src_in.ready. The advantage of dp_pipeline_ready is that it register the
--     src_in.ready, so that may ease achieving timing closure.
--   - The alternative with g_use_ready = true and g_pipeline_ready = false is
--     to use a dp_pipeline the d.src_out in combination with src_in.ready, to
--     keep the RL at 1 by means of dp_pipeline. The dp_pipeline adds a
--     register to store src_out. The p_reg.src_out is kept as well, to keep
--     the internal state of the function.
-- . If the p_comb also needs to apply flow control itself, then p_comb can
--   output a ready or d.ready signal that is or-ed with the input
--   src_in.ready and then applied to the src_in input of dp_add_flow_control.
-- . The g_in_latency and g_out_latency are only used when g_use_ready = true
--   and g_pipeline_ready = true. When g_pipeline_ready = false, then the
--   assumption is that snk_in and src_out both have RL = 1.
-- Remark:
-- . Default use g_use_ready = true and g_pipeline_ready = false for solution
--   that fits both flow control or no flow control with the least logic. The
--   flow control logic may even get entirely optimized away during synthesis
--   when snk_in.ready = '1' fixed.

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;

entity dp_add_flow_control is
  generic (
    g_use_ready       : boolean := true;
    g_pipeline_ready  : boolean := false;
    g_in_latency      : natural := 1;
    g_out_latency     : natural := 1
  );
  port (
    rst         : in  std_logic;
    clk         : in  std_logic;

    snk_out     : out t_dp_siso;
    snk_in      : in  t_dp_sosi;  -- combinatorial input
    snk_in_reg  : in  t_dp_sosi;  -- registered input

    src_in      : in  t_dp_siso := c_dp_siso_rst;
    src_out     : out t_dp_sosi
  );
end dp_add_flow_control;

architecture str of dp_add_flow_control is
begin
  no_flow_control : if g_use_ready = false generate
    -- Only wires
    snk_out <= c_dp_siso_rdy;
    src_out <= snk_in_reg;
  end generate;

  use_flow_control : if g_use_ready = true generate
    gen_dp_pipeline : if g_pipeline_ready = false generate
      u_dp_pipeline : entity work.dp_pipeline
        port map (
          rst          => rst,
          clk          => clk,
          -- ST sink
          snk_out      => snk_out,
          snk_in       => snk_in,
          -- ST source
          src_in       => src_in,
          src_out      => src_out
        );
    end generate;

    gen_dp_pipeline_ready : if g_pipeline_ready = true generate
      u_dp_pipeline_ready : entity work.dp_pipeline_ready
        generic map (
          g_in_latency  => g_in_latency + 1,  -- + 1 to account of registered input
          g_out_latency => g_out_latency
        )
        port map (
          rst          => rst,
          clk          => clk,
          -- ST sink
          snk_out      => snk_out,
          snk_in       => snk_in_reg,
          -- ST source
          src_in       => src_in,
          src_out      => src_out
        );
    end generate;
  end generate;
end str;