Newer
Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
--------------------------------------------------------------------------------
--
-- 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;