1 |
145 |
lanttu |
-------------------------------------------------------------------------------
|
2 |
|
|
-- File : ring_router.vhdl
|
3 |
|
|
-- Description : Routes packets in Ring network.
|
4 |
|
|
-- Four io channels,
|
5 |
|
|
-- i.e. two to neighbor routers, one for opposite neighbor
|
6 |
|
|
-- and one for processing element.
|
7 |
|
|
--
|
8 |
|
|
-- Neighbor connections have identifiers: fwd, rev, and diag
|
9 |
|
|
-- referring to direction in ring
|
10 |
|
|
--
|
11 |
|
|
-- All output channels have one fifo buffer.
|
12 |
|
|
-- Routers are identified with three-part address
|
13 |
|
|
-- two-part ring id (direction and distance from center ring)
|
14 |
|
|
-- router id within the ring
|
15 |
|
|
--
|
16 |
|
|
-- Size of packet (including address) is the same as fifo_depth_g
|
17 |
|
|
--
|
18 |
|
|
--
|
19 |
|
|
-- Author : Jussi Nieminen after Erno Salminen's Octagon router
|
20 |
|
|
-- Date : 10.04.2006
|
21 |
|
|
-- Modified : 12.02.2009 JN Forked from the Octagon router.
|
22 |
|
|
|
23 |
|
|
-------------------------------------------------------------------------------
|
24 |
|
|
|
25 |
|
|
-------------------------------------------------------------------------------
|
26 |
|
|
-- Copyright (c) 2011 Tampere University of Technology
|
27 |
|
|
-------------------------------------------------------------------------------
|
28 |
|
|
-- This file is part of Transaction Generator.
|
29 |
|
|
--
|
30 |
|
|
-- Transaction Generator is free software: you can redistribute it and/or
|
31 |
|
|
-- modify it under the terms of the Lesser GNU General Public License as
|
32 |
|
|
-- published by the Free Software Foundation, either version 3 of the License,
|
33 |
|
|
-- or (at your option) any later version.
|
34 |
|
|
--
|
35 |
|
|
-- Transaction Generator is distributed in the hope that it will be useful,
|
36 |
|
|
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
37 |
|
|
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
38 |
|
|
-- Lesser GNU General Public License for more details.
|
39 |
|
|
--
|
40 |
|
|
-- You should have received a copy of the Lesser GNU General Public License
|
41 |
|
|
-- along with Transaction Generator. If not, see
|
42 |
|
|
-- <http://www.gnu.org/licenses/>.
|
43 |
|
|
-------------------------------------------------------------------------------
|
44 |
|
|
|
45 |
|
|
|
46 |
|
|
library ieee;
|
47 |
|
|
use ieee.std_logic_1164.all;
|
48 |
|
|
use ieee.std_logic_arith.all;
|
49 |
|
|
use ieee.std_logic_unsigned.all;
|
50 |
|
|
|
51 |
|
|
|
52 |
|
|
entity ring_router is
|
53 |
|
|
|
54 |
|
|
generic (
|
55 |
|
|
nbr_of_routers_g : integer := 8;
|
56 |
|
|
data_width_g : integer := 0;
|
57 |
|
|
dateline_en_g : integer := 0;
|
58 |
|
|
stfwd_en_g : integer := 1;
|
59 |
|
|
pkt_len_g : integer;
|
60 |
|
|
len_flit_en_g : integer := 0;
|
61 |
|
|
oaddr_flit_en_g : integer := 0;
|
62 |
|
|
fifo_depth_g : integer;
|
63 |
|
|
router_id_g : integer := 0;
|
64 |
|
|
diag_en_g : integer := 1;
|
65 |
|
|
net_freq_g : integer;
|
66 |
|
|
ip_freq_g : integer;
|
67 |
|
|
sim_dbg_ena_g : integer := 0
|
68 |
|
|
);
|
69 |
|
|
port (
|
70 |
|
|
clk_net : in std_logic;
|
71 |
|
|
clk_ip : in std_logic;
|
72 |
|
|
rst_n : in std_logic;
|
73 |
|
|
|
74 |
|
|
data_fwd_in : in std_logic_vector (data_width_g-1 downto 0);
|
75 |
|
|
re_fwd_out : out std_logic;
|
76 |
|
|
empty_fwd_in : in std_logic;
|
77 |
|
|
full_fwd_in : in std_logic;
|
78 |
|
|
|
79 |
|
|
data_rev_in : in std_logic_vector (data_width_g-1 downto 0);
|
80 |
|
|
re_rev_out : out std_logic;
|
81 |
|
|
empty_rev_in : in std_logic;
|
82 |
|
|
full_rev_in : in std_logic;
|
83 |
|
|
|
84 |
|
|
-- diag ports enabled with generic
|
85 |
|
|
data_diag_in : in std_logic_vector (data_width_g-1 downto 0);
|
86 |
|
|
re_diag_out : out std_logic;
|
87 |
|
|
empty_diag_in : in std_logic;
|
88 |
|
|
full_diag_in : in std_logic;
|
89 |
|
|
|
90 |
|
|
data_ip_tx_in : in std_logic_vector (data_width_g-1 downto 0);
|
91 |
|
|
we_ip_tx_in : in std_logic;
|
92 |
|
|
empty_ip_tx_out : out std_logic;
|
93 |
|
|
full_ip_tx_out : out std_logic;
|
94 |
|
|
|
95 |
|
|
data_fwd_out : out std_logic_vector (data_width_g-1 downto 0);
|
96 |
|
|
re_fwd_in : in std_logic;
|
97 |
|
|
empty_fwd_out : out std_logic;
|
98 |
|
|
full_fwd_out : out std_logic;
|
99 |
|
|
|
100 |
|
|
data_rev_out : out std_logic_vector (data_width_g-1 downto 0);
|
101 |
|
|
re_rev_in : in std_logic;
|
102 |
|
|
empty_rev_out : out std_logic;
|
103 |
|
|
full_rev_out : out std_logic;
|
104 |
|
|
|
105 |
|
|
-- diag ports enabled with generic
|
106 |
|
|
data_diag_out : out std_logic_vector (data_width_g-1 downto 0);
|
107 |
|
|
re_diag_in : in std_logic;
|
108 |
|
|
empty_diag_out : out std_logic;
|
109 |
|
|
full_diag_out : out std_logic;
|
110 |
|
|
|
111 |
|
|
data_ip_rx_out : out std_logic_vector (data_width_g-1 downto 0);
|
112 |
|
|
re_ip_rx_in : in std_logic;
|
113 |
|
|
full_ip_rx_out : out std_logic;
|
114 |
|
|
empty_ip_rx_out : out std_logic
|
115 |
|
|
);
|
116 |
|
|
|
117 |
|
|
end ring_router;
|
118 |
|
|
|
119 |
|
|
|
120 |
|
|
|
121 |
|
|
architecture rtl of ring_router is
|
122 |
|
|
|
123 |
|
|
|
124 |
|
|
-- Set dbg_level=0 for synthesis
|
125 |
|
|
constant dbg_level_c : integer range 0 to 3 := 0;
|
126 |
|
|
|
127 |
|
|
type dbg_value_arr is array (0 to 1) of std_logic;
|
128 |
|
|
constant dbg_value_c : dbg_value_arr := ('0', 'Z');
|
129 |
|
|
|
130 |
|
|
|
131 |
|
|
-- this should be made generic later..?
|
132 |
|
|
constant addr_width_c : integer := 15;
|
133 |
|
|
|
134 |
|
|
-- There are always at least 3 bidir ports: IP, clockwise, counterclkwise
|
135 |
|
|
-- Possibly also; diagonal port
|
136 |
|
|
constant n_ports_c : integer range 0 to 5 := 3 + diag_en_g;
|
137 |
|
|
signal n_ports_dbgr : integer := n_ports_c;
|
138 |
|
|
|
139 |
|
|
-- Constants for accessing arrays (e.g. state_regs)
|
140 |
|
|
constant ip_c : integer := 0;
|
141 |
|
|
constant fwd_c : integer := 1;
|
142 |
|
|
constant rev_c : integer := 2;
|
143 |
|
|
constant diag_c : integer := 3;
|
144 |
|
|
constant no_dir_c : integer := n_ports_c; -- Illegal index
|
145 |
|
|
|
146 |
|
|
component multiclk_fifo
|
147 |
|
|
generic (
|
148 |
|
|
re_freq_g : integer;
|
149 |
|
|
we_freq_g : integer;
|
150 |
|
|
depth_g : integer;
|
151 |
|
|
data_width_g : integer);
|
152 |
|
|
port (
|
153 |
|
|
clk_re : in std_logic;
|
154 |
|
|
clk_we : in std_logic;
|
155 |
|
|
rst_n : in std_logic;
|
156 |
|
|
data_in : in std_logic_vector (data_width_g-1 downto 0);
|
157 |
|
|
we_in : in std_logic;
|
158 |
|
|
full_out : out std_logic;
|
159 |
|
|
one_p_out : out std_logic;
|
160 |
|
|
re_in : in std_logic;
|
161 |
|
|
data_out : out std_logic_vector (data_width_g-1 downto 0);
|
162 |
|
|
empty_out : out std_logic;
|
163 |
|
|
one_d_out : out std_logic);
|
164 |
|
|
end component;
|
165 |
|
|
|
166 |
|
|
component fifo
|
167 |
|
|
generic (
|
168 |
|
|
data_width_g : integer := 0;
|
169 |
|
|
depth_g : integer := 0);
|
170 |
|
|
port (
|
171 |
|
|
clk : in std_logic;
|
172 |
|
|
rst_n : in std_logic;
|
173 |
|
|
data_in : in std_logic_vector (data_width_g-1 downto 0);
|
174 |
|
|
we_in : in std_logic;
|
175 |
|
|
one_p_out : out std_logic;
|
176 |
|
|
full_out : out std_logic;
|
177 |
|
|
data_out : out std_logic_vector (data_width_g-1 downto 0);
|
178 |
|
|
re_in : in std_logic;
|
179 |
|
|
empty_out : out std_logic;
|
180 |
|
|
one_d_out : out std_logic
|
181 |
|
|
);
|
182 |
|
|
end component; --fifo;
|
183 |
|
|
|
184 |
|
|
|
185 |
|
|
-- Function that decides shortest to reach target within the ring
|
186 |
|
|
function router_func (
|
187 |
|
|
constant dst_addr : integer; --std_logic_vector ( 3-1 downto 0);
|
188 |
|
|
constant own_addr : integer)
|
189 |
|
|
return integer is
|
190 |
|
|
variable rel_addr_v : integer range -nbr_of_routers_g+1 to nbr_of_routers_g;
|
191 |
|
|
begin -- router_func
|
192 |
|
|
|
193 |
|
|
-- address relative to this router, target's distance from
|
194 |
|
|
-- this router when going forward
|
195 |
|
|
-- (e.g. nbr_of_routers - 1 means target is the next router backwards)
|
196 |
|
|
rel_addr_v := (dst_addr - own_addr);
|
197 |
|
|
if rel_addr_v < 0 then
|
198 |
|
|
rel_addr_v := rel_addr_v + nbr_of_routers_g;
|
199 |
|
|
end if;
|
200 |
|
|
|
201 |
|
|
if (rel_addr_v = 0) then
|
202 |
|
|
-- right dst
|
203 |
|
|
return ip_c;
|
204 |
|
|
|
205 |
|
|
elsif (rel_addr_v <= nbr_of_routers_g / 4) then
|
206 |
|
|
return fwd_c;
|
207 |
|
|
|
208 |
|
|
elsif (rel_addr_v >= nbr_of_routers_g - nbr_of_routers_g / 4) then
|
209 |
|
|
return rev_c;
|
210 |
|
|
|
211 |
|
|
else
|
212 |
|
|
if diag_en_g = 1 then
|
213 |
|
|
return diag_c;
|
214 |
|
|
elsif rel_addr_v > nbr_of_routers_g / 2 then
|
215 |
|
|
return rev_c;
|
216 |
|
|
else
|
217 |
|
|
return fwd_c;
|
218 |
|
|
end if;
|
219 |
|
|
end if;
|
220 |
|
|
|
221 |
|
|
end router_func;
|
222 |
|
|
|
223 |
|
|
|
224 |
|
|
|
225 |
|
|
-- Internal types and signals. Thse are mapped to router's inputs
|
226 |
|
|
-- Arrays are easier to handle than names with direction identification
|
227 |
|
|
-- (e.g. data_arr(i) vs. data_fwd)
|
228 |
|
|
type data_arr_type is array (n_ports_c-1 downto 0) of std_logic_vector (data_width_g-1 downto 0);
|
229 |
|
|
type ctrl_arr_type is array (n_ports_c-1 downto 0) of std_logic;
|
230 |
|
|
type source_type is array (n_ports_c-1 downto 0) of integer range 0 to 5;
|
231 |
|
|
type counter_arr_type is array (n_ports_c-1 downto 0) of integer range 0 to pkt_len_g; --fifo_depth_g;
|
232 |
|
|
type channel_arr_type is array (n_ports_c-1 downto 0) of integer range 0 to 1;
|
233 |
|
|
|
234 |
|
|
|
235 |
|
|
signal Incoming_data : data_arr_type;
|
236 |
|
|
signal Incoming_empty : ctrl_arr_type;
|
237 |
|
|
signal Incoming_full : ctrl_arr_type;
|
238 |
|
|
signal send_counter_r : counter_arr_type;
|
239 |
|
|
signal pkt_len_arr_r : counter_arr_type;
|
240 |
|
|
|
241 |
|
|
-- From fifos. Mapped directly to outputs pins
|
242 |
|
|
signal data_from_fifo : data_arr_type;
|
243 |
|
|
signal full_from_fifo : ctrl_arr_type;
|
244 |
|
|
signal empty_from_fifo : ctrl_arr_type; -- this goes also to ctrl
|
245 |
|
|
|
246 |
|
|
-- signals to and from fwd and rev fifos
|
247 |
|
|
signal data_from_fwd0 : std_logic_vector( data_width_g - 1 downto 0 );
|
248 |
|
|
signal data_from_fwd1 : std_logic_vector( data_width_g - 1 downto 0 );
|
249 |
|
|
signal data_from_rev0 : std_logic_vector( data_width_g - 1 downto 0 );
|
250 |
|
|
signal data_from_rev1 : std_logic_vector( data_width_g - 1 downto 0 );
|
251 |
|
|
signal full_from_fwd0 : std_logic;
|
252 |
|
|
signal full_from_fwd1 : std_logic;
|
253 |
|
|
signal full_from_rev0 : std_logic;
|
254 |
|
|
signal full_from_rev1 : std_logic;
|
255 |
|
|
signal empty_from_fwd0 : std_logic;
|
256 |
|
|
signal empty_from_fwd1 : std_logic;
|
257 |
|
|
signal empty_from_rev0 : std_logic;
|
258 |
|
|
signal empty_from_rev1 : std_logic;
|
259 |
|
|
signal empty_from_fwd : std_logic;
|
260 |
|
|
signal empty_from_rev : std_logic;
|
261 |
|
|
signal we_fwd0 : std_logic;
|
262 |
|
|
signal we_fwd1 : std_logic;
|
263 |
|
|
signal we_rev0 : std_logic;
|
264 |
|
|
signal we_rev1 : std_logic;
|
265 |
|
|
signal re_fwd0 : std_logic;
|
266 |
|
|
signal re_fwd1 : std_logic;
|
267 |
|
|
signal re_rev0 : std_logic;
|
268 |
|
|
signal re_rev1 : std_logic;
|
269 |
|
|
|
270 |
|
|
-- controlling outputs from fwd and rev
|
271 |
|
|
signal fwd_pkt_counter_r : integer;
|
272 |
|
|
signal rev_pkt_counter_r : integer;
|
273 |
|
|
signal fwd_chan_sel_r : std_logic;
|
274 |
|
|
signal rev_chan_sel_r : std_logic;
|
275 |
|
|
|
276 |
|
|
signal fwd_pkt_len_r : integer;
|
277 |
|
|
signal rev_pkt_len_r : integer;
|
278 |
|
|
|
279 |
|
|
-- From ctrl
|
280 |
|
|
signal data_ctrl_fifo_r : data_arr_type;
|
281 |
|
|
signal we_ctrl_fifo_r : ctrl_arr_type;
|
282 |
|
|
signal re_r : ctrl_arr_type;
|
283 |
|
|
|
284 |
|
|
-- 2006/10/23 Try wormhole, combinatorial enable signals
|
285 |
|
|
signal re_tmp : ctrl_arr_type;
|
286 |
|
|
signal we_tmp : ctrl_arr_type;
|
287 |
|
|
|
288 |
|
|
signal data_reg_valid_r : ctrl_arr_type; -- 2006/10/26
|
289 |
|
|
signal data_ctrl_fifo_dbg : data_arr_type;
|
290 |
|
|
|
291 |
|
|
|
292 |
|
|
-- State registers
|
293 |
|
|
signal State_writing_r : std_logic_vector (n_ports_c-1 downto 0); -- 0=ip,1=
|
294 |
|
|
signal State_reading_r : std_logic_vector (n_ports_c-1 downto 0); -- 0=ip,1=
|
295 |
|
|
|
296 |
|
|
-- state_src_r(i) tells which port the source for output port i
|
297 |
|
|
signal state_src_r : source_type; -- 0=ip,1=
|
298 |
|
|
|
299 |
|
|
-- state_dst_r(i) tells which port the destination for input port i
|
300 |
|
|
signal state_dst_r : source_type;
|
301 |
|
|
|
302 |
|
|
-- state_channel_r(i) tells which channel to use for output i
|
303 |
|
|
signal state_channel_r : channel_arr_type;
|
304 |
|
|
|
305 |
|
|
|
306 |
|
|
-- Marks which input is checked on current cycle
|
307 |
|
|
--signal curr_src_r : integer range 0 to n_ports_c-1;
|
308 |
|
|
|
309 |
|
|
-- Decoded address in input port pointed by curr_src_r, _not_ a register!
|
310 |
|
|
--signal curr_dst : integer range 0 to n_ports_c;
|
311 |
|
|
-- new type 2006/10/23, ES
|
312 |
|
|
type dst_arr_type is array (n_ports_c-1 downto 0) of integer range 0 to n_ports_c;
|
313 |
|
|
signal curr_dst : dst_arr_type;
|
314 |
|
|
signal curr_dst_resolved : dst_arr_type;
|
315 |
|
|
signal n_req_dbgr : dst_arr_type;
|
316 |
|
|
signal curr_channel : channel_arr_type;
|
317 |
|
|
|
318 |
|
|
|
319 |
|
|
|
320 |
|
|
type addr_arr_type is array (n_ports_c-1 downto 0) of integer;
|
321 |
|
|
|
322 |
|
|
signal router_addr : addr_arr_type;
|
323 |
|
|
|
324 |
|
|
|
325 |
|
|
signal start_idx_r : integer range 0 to n_ports_c-1; -- 28.11 for round-robin resolution
|
326 |
|
|
|
327 |
|
|
-- this should be generic...
|
328 |
|
|
constant len_width_c : integer := 8;
|
329 |
|
|
|
330 |
|
|
-----------------------------------------------------------------------------
|
331 |
|
|
begin -- rtl
|
332 |
|
|
-----------------------------------------------------------------------------
|
333 |
|
|
|
334 |
|
|
|
335 |
|
|
-- Concurrent assignments
|
336 |
|
|
-- Connect fifo status signals to outputs
|
337 |
|
|
empty_fwd_out <= empty_from_fwd;
|
338 |
|
|
empty_rev_out <= empty_from_rev;
|
339 |
|
|
empty_ip_rx_out <= empty_from_fifo (ip_c); -- from ip_rx_fifo
|
340 |
|
|
|
341 |
|
|
full_fwd_out <= full_from_fifo (fwd_c);
|
342 |
|
|
full_rev_out <= full_from_fifo (rev_c);
|
343 |
|
|
full_ip_rx_out <= full_from_fifo (ip_c); -- from ip_rx_fifo
|
344 |
|
|
|
345 |
|
|
-- Separate arrays signals into outputs
|
346 |
|
|
re_fwd_out <= re_tmp (fwd_c); -- 2006/10/23 re_r (fwd_c);
|
347 |
|
|
re_rev_out <= re_tmp (rev_c); -- 2006/10/23 re_r (rev_c);
|
348 |
|
|
|
349 |
|
|
|
350 |
|
|
-- Collect inputs into array
|
351 |
|
|
Incoming_data (fwd_c) <= data_fwd_in;
|
352 |
|
|
Incoming_data (rev_c) <= data_rev_in;
|
353 |
|
|
-- incoming_data/empty/full (ip_c) comes directly from rx-fifo
|
354 |
|
|
|
355 |
|
|
Incoming_empty (fwd_c) <= empty_fwd_in;
|
356 |
|
|
Incoming_empty (rev_c) <= empty_rev_in;
|
357 |
|
|
empty_ip_tx_out <= Incoming_empty (ip_c); -- from ip_tx_fifo
|
358 |
|
|
|
359 |
|
|
Incoming_full (fwd_c) <= full_fwd_in;
|
360 |
|
|
Incoming_full (rev_c) <= full_rev_in;
|
361 |
|
|
full_ip_tx_out <= Incoming_full (ip_c); -- from ip_tx_fifo
|
362 |
|
|
|
363 |
|
|
|
364 |
|
|
|
365 |
|
|
connect_diag_signals : if diag_en_g = 1 generate
|
366 |
|
|
data_diag_out <= data_from_fifo (diag_c); -- when (dbg_level_c = 0 or empty_from_fifo (fwd_c) = '0') else (others => 'Z');
|
367 |
|
|
empty_diag_out <= empty_from_fifo (diag_c);
|
368 |
|
|
full_diag_out <= full_from_fifo (diag_c);
|
369 |
|
|
re_diag_out <= re_tmp (diag_c); -- 2006/10/23 re_r (diag_c);
|
370 |
|
|
Incoming_data (diag_c) <= data_diag_in;
|
371 |
|
|
Incoming_empty (diag_c) <= empty_diag_in;
|
372 |
|
|
Incoming_full (diag_c) <= full_diag_in;
|
373 |
|
|
end generate connect_diag_signals;
|
374 |
|
|
|
375 |
|
|
not_map_diag_fifo : if diag_en_g = 0 generate
|
376 |
|
|
data_diag_out <= (others => dbg_value_c(sim_dbg_ena_g)); --(others => 'Z');
|
377 |
|
|
empty_diag_out <= '1';
|
378 |
|
|
full_diag_out <= '1';
|
379 |
|
|
re_diag_out <= '0';
|
380 |
|
|
end generate not_map_diag_fifo;
|
381 |
|
|
|
382 |
|
|
|
383 |
|
|
|
384 |
|
|
-- Debug
|
385 |
|
|
-- Easier to trace if outputs are 'Z' when output fifo is empty
|
386 |
|
|
-- (Comment out the "when part" for synthesis
|
387 |
|
|
-- e.g."data_fwd_out <= data_from_fifo (fwd_c); -- when data_from_fifo and so on")
|
388 |
|
|
-- Done with if-generate, 08.06.2006 es
|
389 |
|
|
|
390 |
|
|
-- dbg_tristate_off: if dbg_level_c = 0 generate
|
391 |
|
|
-- data_fwd_out <= data_from_fifo (fwd_c);
|
392 |
|
|
-- data_rev_out <= data_from_fifo (rev_c);
|
393 |
|
|
-- data_ip_rx_out <= data_from_fifo (ip_c);
|
394 |
|
|
-- end generate dbg_tristate_off;
|
395 |
|
|
|
396 |
|
|
-- dbg_tristate_on : if dbg_level_c > 0 generate
|
397 |
|
|
data_fwd_out <= data_from_fifo (fwd_c); -- when (dbg_level_c = 0 or empty_from_fifo (fwd_c) = '0') else (others => 'Z');
|
398 |
|
|
data_rev_out <= data_from_fifo (rev_c); -- when (dbg_level_c = 0 or empty_from_fifo (fwd_c) = '0') else (others => 'Z');
|
399 |
|
|
data_ip_rx_out <= data_from_fifo (ip_c); -- when (dbg_level_c = 0 or empty_from_fifo (fwd_c) = '0') else (others => '0');
|
400 |
|
|
-- end generate dbg_tristate_on;
|
401 |
|
|
|
402 |
|
|
|
403 |
|
|
|
404 |
|
|
-----------------------------------------------------------------------------
|
405 |
|
|
-- Component mappings
|
406 |
|
|
-----------------------------------------------------------------------------
|
407 |
|
|
|
408 |
|
|
-- Fifo data outputs are connected to router's outputs (via intermediate signal, though)
|
409 |
|
|
|
410 |
|
|
-- 4 FIFOS are always included to outports
|
411 |
|
|
-- Data going to ip, multiclk
|
412 |
|
|
Ip_fifo_rx : multiclk_fifo
|
413 |
|
|
generic map (
|
414 |
|
|
re_freq_g => ip_freq_g,
|
415 |
|
|
we_freq_g => net_freq_g,
|
416 |
|
|
data_width_g => data_width_g,
|
417 |
|
|
depth_g => fifo_depth_g
|
418 |
|
|
)
|
419 |
|
|
port map (
|
420 |
|
|
clk_re => clk_ip,
|
421 |
|
|
clk_we => clk_net,
|
422 |
|
|
rst_n => rst_n,
|
423 |
|
|
data_in => data_ctrl_fifo_r (ip_c),
|
424 |
|
|
we_in => we_tmp (ip_c),
|
425 |
|
|
full_out => full_from_fifo (ip_c),
|
426 |
|
|
data_out => data_from_fifo (ip_c),
|
427 |
|
|
re_in => re_ip_rx_in, -- router input
|
428 |
|
|
empty_out => empty_from_fifo (ip_c) --,
|
429 |
|
|
);
|
430 |
|
|
|
431 |
|
|
-- Data coming from ip, multiclk
|
432 |
|
|
Ip_fifo_tx : multiclk_fifo
|
433 |
|
|
generic map (
|
434 |
|
|
re_freq_g => net_freq_g,
|
435 |
|
|
we_freq_g => ip_freq_g,
|
436 |
|
|
data_width_g => data_width_g,
|
437 |
|
|
depth_g => fifo_depth_g
|
438 |
|
|
)
|
439 |
|
|
port map (
|
440 |
|
|
clk_re => clk_net,
|
441 |
|
|
clk_we => clk_ip,
|
442 |
|
|
rst_n => rst_n,
|
443 |
|
|
-- Fifo inputs come straight router inputs (=from ip)
|
444 |
|
|
data_in => data_ip_tx_in,
|
445 |
|
|
full_out => Incoming_full (ip_c),
|
446 |
|
|
we_in => we_ip_Tx_in,
|
447 |
|
|
|
448 |
|
|
-- Fifo outputs go ctrl logic
|
449 |
|
|
data_out => Incoming_data (ip_c),
|
450 |
|
|
empty_out => Incoming_empty (ip_c),
|
451 |
|
|
re_in => re_tmp (ip_c) --re_r (ip_c)
|
452 |
|
|
);
|
453 |
|
|
|
454 |
|
|
|
455 |
|
|
-- two forward fifos to enable two channels
|
456 |
|
|
fwd_fifo_0 : fifo
|
457 |
|
|
generic map (
|
458 |
|
|
data_width_g => data_width_g,
|
459 |
|
|
depth_g => fifo_depth_g
|
460 |
|
|
)
|
461 |
|
|
port map (
|
462 |
|
|
clk => clk_net,
|
463 |
|
|
rst_n => rst_n,
|
464 |
|
|
data_in => data_ctrl_fifo_r (fwd_c),
|
465 |
|
|
we_in => we_fwd0,
|
466 |
|
|
full_out => full_from_fwd0,
|
467 |
|
|
data_out => data_from_fwd0,
|
468 |
|
|
re_in => re_fwd0, -- router input
|
469 |
|
|
empty_out => empty_from_fwd0
|
470 |
|
|
);
|
471 |
|
|
|
472 |
|
|
fwd_fifo_1 : fifo
|
473 |
|
|
generic map (
|
474 |
|
|
data_width_g => data_width_g,
|
475 |
|
|
depth_g => fifo_depth_g
|
476 |
|
|
)
|
477 |
|
|
port map (
|
478 |
|
|
clk => clk_net,
|
479 |
|
|
rst_n => rst_n,
|
480 |
|
|
data_in => data_ctrl_fifo_r (fwd_c),
|
481 |
|
|
we_in => we_fwd1,
|
482 |
|
|
full_out => full_from_fwd1,
|
483 |
|
|
data_out => data_from_fwd1,
|
484 |
|
|
re_in => re_fwd1, -- router input
|
485 |
|
|
empty_out => empty_from_fwd1
|
486 |
|
|
);
|
487 |
|
|
|
488 |
|
|
-- two rev fifos
|
489 |
|
|
rev_fifo_0 : fifo
|
490 |
|
|
generic map (
|
491 |
|
|
data_width_g => data_width_g,
|
492 |
|
|
depth_g => fifo_depth_g
|
493 |
|
|
)
|
494 |
|
|
port map (
|
495 |
|
|
clk => clk_net,
|
496 |
|
|
rst_n => rst_n,
|
497 |
|
|
data_in => data_ctrl_fifo_r (rev_c),
|
498 |
|
|
we_in => we_rev0,
|
499 |
|
|
full_out => full_from_rev0,
|
500 |
|
|
data_out => data_from_rev0,
|
501 |
|
|
re_in => re_rev0,
|
502 |
|
|
empty_out => empty_from_rev0
|
503 |
|
|
);
|
504 |
|
|
|
505 |
|
|
rev_fifo_1 : fifo
|
506 |
|
|
generic map (
|
507 |
|
|
data_width_g => data_width_g,
|
508 |
|
|
depth_g => fifo_depth_g
|
509 |
|
|
)
|
510 |
|
|
port map (
|
511 |
|
|
clk => clk_net,
|
512 |
|
|
rst_n => rst_n,
|
513 |
|
|
data_in => data_ctrl_fifo_r (rev_c),
|
514 |
|
|
we_in => we_rev1,
|
515 |
|
|
full_out => full_from_rev1,
|
516 |
|
|
data_out => data_from_rev1,
|
517 |
|
|
re_in => re_rev1,
|
518 |
|
|
empty_out => empty_from_rev1
|
519 |
|
|
);
|
520 |
|
|
|
521 |
|
|
-- 2 Optional fifos
|
522 |
|
|
map_diag_fifo : if diag_en_g = 1 generate
|
523 |
|
|
diag_fifo : fifo
|
524 |
|
|
generic map (
|
525 |
|
|
data_width_g => data_width_g,
|
526 |
|
|
depth_g => fifo_depth_g
|
527 |
|
|
)
|
528 |
|
|
port map (
|
529 |
|
|
clk => clk_net,
|
530 |
|
|
rst_n => rst_n,
|
531 |
|
|
data_in => data_ctrl_fifo_r (diag_c),
|
532 |
|
|
we_in => we_tmp (diag_c),
|
533 |
|
|
full_out => full_from_fifo (diag_c),
|
534 |
|
|
data_out => data_from_fifo (diag_c),
|
535 |
|
|
re_in => re_diag_in, -- router input
|
536 |
|
|
empty_out => empty_from_fifo (diag_c)
|
537 |
|
|
);
|
538 |
|
|
end generate map_diag_fifo;
|
539 |
|
|
|
540 |
|
|
|
541 |
|
|
-----------------------------------------------------------------------------
|
542 |
|
|
read_en_tmp : process (we_ctrl_fifo_r, re_r,
|
543 |
|
|
data_reg_valid_r,
|
544 |
|
|
state_src_r, state_dst_r,
|
545 |
|
|
full_from_fifo,
|
546 |
|
|
Incoming_empty --,
|
547 |
|
|
--send_counter_r
|
548 |
|
|
)
|
549 |
|
|
|
550 |
|
|
begin -- process read_en_tmp
|
551 |
|
|
for i in 0 to n_ports_c-1 loop
|
552 |
|
|
|
553 |
|
|
-- i viittaa kohteeseen (fifo)
|
554 |
|
|
if state_src_r (i) = no_dir_c then
|
555 |
|
|
we_tmp (i) <= '0';
|
556 |
|
|
|
557 |
|
|
else
|
558 |
|
|
we_tmp (i) <= we_ctrl_fifo_r (i)
|
559 |
|
|
and data_reg_valid_r (i)
|
560 |
|
|
and (not (full_from_fifo (i)));
|
561 |
|
|
end if;
|
562 |
|
|
|
563 |
|
|
-- i viittaa lähteeseen (=input_port)
|
564 |
|
|
if state_dst_r (i) = no_dir_c then
|
565 |
|
|
-- sisääntulossa i ei ole järkevää dataa
|
566 |
|
|
re_tmp (i) <= '0';
|
567 |
|
|
else
|
568 |
|
|
-- ei lueta sisääntulosta i ellei
|
569 |
|
|
-- a) tilakone ole lukemass sieltä (re_r pitää olla 1)
|
570 |
|
|
-- b) sisääntulossa on validia dataa (empty pitää olla 0)
|
571 |
|
|
-- c) kohde ei ole varattu
|
572 |
|
|
re_tmp (i) <= re_r (i)
|
573 |
|
|
and (not Incoming_empty (i))
|
574 |
|
|
and (not full_from_fifo (state_dst_r (i)));
|
575 |
|
|
end if;
|
576 |
|
|
|
577 |
|
|
end loop; -- i
|
578 |
|
|
end process read_en_tmp;
|
579 |
|
|
|
580 |
|
|
|
581 |
|
|
-----------------------------------------------------------------------------
|
582 |
|
|
-- select right fifo according to channel
|
583 |
|
|
select_channels: process (we_tmp, state_channel_r,
|
584 |
|
|
data_from_fwd0, data_from_fwd1,
|
585 |
|
|
data_from_rev0, data_from_rev1,
|
586 |
|
|
empty_from_fwd0, empty_from_fwd1,
|
587 |
|
|
empty_from_rev0, empty_from_rev1,
|
588 |
|
|
full_from_fwd0, full_from_fwd1,
|
589 |
|
|
full_from_rev0, full_from_rev1,
|
590 |
|
|
re_fwd_in, re_rev_in,
|
591 |
|
|
fwd_chan_sel_r, rev_chan_sel_r)
|
592 |
|
|
begin -- process select_channels
|
593 |
|
|
|
594 |
|
|
|
595 |
|
|
-- decide which fifo will get the data:
|
596 |
|
|
-- if there's channel 1 data coming, we have to direct out
|
597 |
|
|
-- signals from the fifo 1
|
598 |
|
|
if state_channel_r(fwd_c) = 1 then
|
599 |
|
|
we_fwd1 <= we_tmp(fwd_c);
|
600 |
|
|
we_fwd0 <= '0';
|
601 |
|
|
empty_from_fifo(fwd_c) <= empty_from_fwd1;
|
602 |
|
|
full_from_fifo(fwd_c) <= full_from_fwd1;
|
603 |
|
|
else
|
604 |
|
|
we_fwd0 <= we_tmp(fwd_c);
|
605 |
|
|
we_fwd1 <= '0';
|
606 |
|
|
empty_from_fifo(fwd_c) <= empty_from_fwd0;
|
607 |
|
|
full_from_fifo(fwd_c) <= full_from_fwd0;
|
608 |
|
|
end if;
|
609 |
|
|
|
610 |
|
|
if state_channel_r(rev_c) = 1 then
|
611 |
|
|
we_rev1 <= we_tmp(rev_c);
|
612 |
|
|
we_rev0 <= '0';
|
613 |
|
|
full_from_fifo(rev_c) <= full_from_rev1;
|
614 |
|
|
empty_from_fifo(rev_c) <= empty_from_rev1;
|
615 |
|
|
else
|
616 |
|
|
we_rev0 <= we_tmp(rev_c);
|
617 |
|
|
we_rev1 <= '0';
|
618 |
|
|
full_from_fifo(rev_c) <= full_from_rev0;
|
619 |
|
|
empty_from_fifo(rev_c) <= empty_from_rev0;
|
620 |
|
|
end if;
|
621 |
|
|
|
622 |
|
|
|
623 |
|
|
|
624 |
|
|
-- decide from which fifo the data goes out
|
625 |
|
|
if fwd_chan_sel_r = '1' then
|
626 |
|
|
data_from_fifo(fwd_c) <= data_from_fwd1;
|
627 |
|
|
re_fwd1 <= re_fwd_in;
|
628 |
|
|
re_fwd0 <= '0';
|
629 |
|
|
empty_from_fwd <= empty_from_fwd1;
|
630 |
|
|
else
|
631 |
|
|
data_from_fifo(fwd_c) <= data_from_fwd0;
|
632 |
|
|
re_fwd0 <= re_fwd_in;
|
633 |
|
|
re_fwd1 <= '0';
|
634 |
|
|
empty_from_fwd <= empty_from_fwd0;
|
635 |
|
|
end if;
|
636 |
|
|
|
637 |
|
|
-- same for the rev fifo
|
638 |
|
|
if rev_chan_sel_r = '1' then
|
639 |
|
|
data_from_fifo(rev_c) <= data_from_rev1;
|
640 |
|
|
re_rev1 <= re_rev_in;
|
641 |
|
|
re_rev0 <= '0';
|
642 |
|
|
empty_from_rev <= empty_from_rev1;
|
643 |
|
|
else
|
644 |
|
|
data_from_fifo(rev_c) <= data_from_rev0;
|
645 |
|
|
re_rev0 <= re_rev_in;
|
646 |
|
|
re_rev1 <= '0';
|
647 |
|
|
empty_from_rev <= empty_from_rev0;
|
648 |
|
|
end if;
|
649 |
|
|
|
650 |
|
|
|
651 |
|
|
end process select_channels;
|
652 |
|
|
|
653 |
|
|
|
654 |
|
|
|
655 |
|
|
|
656 |
|
|
------------------------------------------------------------------------------
|
657 |
|
|
-- Parallel routing (all ports prt cycle)
|
658 |
|
|
------------------------------------------------------------------------------
|
659 |
|
|
-- !!! without postponed Incoming_data is not updated
|
660 |
|
|
-- before this process and overflow occurs on
|
661 |
|
|
-- router_addr !!! 11.9.2006 HP
|
662 |
|
|
-- PROC
|
663 |
|
|
-- Check where the incoming packet is heading
|
664 |
|
|
-- Input ports are handled one per clock cycle
|
665 |
|
|
Check_dst : postponed
|
666 |
|
|
process (State_reading_r,
|
667 |
|
|
router_addr,
|
668 |
|
|
Incoming_data,
|
669 |
|
|
Incoming_empty,
|
670 |
|
|
Incoming_full)
|
671 |
|
|
|
672 |
|
|
variable resolved_dest_v : integer range 0 to n_ports_c - 1;
|
673 |
|
|
variable incoming_channel_v : std_logic;
|
674 |
|
|
|
675 |
|
|
begin -- process Check_dst
|
676 |
|
|
|
677 |
|
|
-- 1) if (No read operation yet on the curr source port)
|
678 |
|
|
-- and (Complete packet coming from curr src port) -- store_and-forward
|
679 |
|
|
-- and (there is data (=addr) on curr src port) -- cut-through
|
680 |
|
|
--
|
681 |
|
|
-- 2) if (packet is going to right direction from center ring)
|
682 |
|
|
-- 3) if (target column) => data goes to ip
|
683 |
|
|
-- 3) elsif (toward west)
|
684 |
|
|
-- 3) else (toward east)
|
685 |
|
|
--
|
686 |
|
|
-- 2) else wrong direction
|
687 |
|
|
-- away from center
|
688 |
|
|
-- towards center
|
689 |
|
|
-- 1) else => no packet arriving on curr src port
|
690 |
|
|
|
691 |
|
|
for src_i in 0 to n_ports_c-1 loop
|
692 |
|
|
|
693 |
|
|
router_addr (src_i) <= no_dir_c; --0;
|
694 |
|
|
|
695 |
|
|
if State_reading_r (src_i) = '0'
|
696 |
|
|
and ((Incoming_full (src_i) = '1' and stfwd_en_g = 1)
|
697 |
|
|
or
|
698 |
|
|
(Incoming_empty (src_i) = '0'and stfwd_en_g = 0))
|
699 |
|
|
then -- 1)
|
700 |
|
|
|
701 |
|
|
router_addr(src_i) <= conv_integer (unsigned (Incoming_data (src_i) (addr_width_c - 1 downto 0)));
|
702 |
|
|
|
703 |
|
|
incoming_channel_v := Incoming_data(src_i)(addr_width_c);
|
704 |
|
|
|
705 |
|
|
resolved_dest_v := router_func (router_addr(src_i), router_id_g);
|
706 |
|
|
curr_dst (src_i) <= resolved_dest_v;
|
707 |
|
|
|
708 |
|
|
-- channel handling:
|
709 |
|
|
-- if packet is going to fwd or rev directions and it's either coming
|
710 |
|
|
-- trough channel 1 or this is the one router with datelines around it,
|
711 |
|
|
-- we put the packet to channel 1
|
712 |
|
|
if (resolved_dest_v = fwd_c or resolved_dest_v = rev_c)
|
713 |
|
|
and (dateline_en_g = 1 or incoming_channel_v = '1')
|
714 |
|
|
then
|
715 |
|
|
curr_channel(src_i) <= 1;
|
716 |
|
|
else
|
717 |
|
|
curr_channel(src_i) <= 0;
|
718 |
|
|
end if;
|
719 |
|
|
|
720 |
|
|
|
721 |
|
|
else --1)
|
722 |
|
|
-- No packet on curr src port or read operation already started
|
723 |
|
|
curr_dst (src_i) <= no_dir_c;
|
724 |
|
|
curr_channel (src_i) <= 0;
|
725 |
|
|
end if; -- State_reading_r
|
726 |
|
|
|
727 |
|
|
end loop; -- i
|
728 |
|
|
|
729 |
|
|
end process Check_dst;
|
730 |
|
|
|
731 |
|
|
|
732 |
|
|
-----------------------------------------------------------------------------
|
733 |
|
|
resolve_conflicts : process (curr_dst, start_idx_r)
|
734 |
|
|
variable hi_port_v : integer range 0 to n_ports_c;
|
735 |
|
|
variable lo_port_v : integer range 0 to n_ports_c;
|
736 |
|
|
begin -- process resolve_conflicts
|
737 |
|
|
|
738 |
|
|
curr_dst_resolved <= curr_dst;
|
739 |
|
|
|
740 |
|
|
-- 1) Go through all destination ports
|
741 |
|
|
-- 2) Use start_idx_r to separate high and low priotities
|
742 |
|
|
-- 3) Give turn to inport with smallest id in high side, and if there's no
|
743 |
|
|
-- requests there, inport with smallest id in low side
|
744 |
|
|
for dst_i in 0 to n_ports_c-1 loop
|
745 |
|
|
hi_port_v := no_dir_c;
|
746 |
|
|
lo_port_v := no_dir_c;
|
747 |
|
|
|
748 |
|
|
for src_i in 0 to n_ports_c-1 loop
|
749 |
|
|
|
750 |
|
|
if curr_dst(src_i) = dst_i then
|
751 |
|
|
-- src_i wants to send to dst_i
|
752 |
|
|
|
753 |
|
|
if src_i > start_idx_r-1 then
|
754 |
|
|
-- this is hi priority side
|
755 |
|
|
if hi_port_v /= no_dir_c then
|
756 |
|
|
curr_dst_resolved(src_i) <= no_dir_c;
|
757 |
|
|
else
|
758 |
|
|
hi_port_v := src_i;
|
759 |
|
|
end if;
|
760 |
|
|
|
761 |
|
|
else
|
762 |
|
|
-- low priority side
|
763 |
|
|
|
764 |
|
|
if lo_port_v /= no_dir_c then
|
765 |
|
|
curr_dst_resolved(src_i) <= no_dir_c;
|
766 |
|
|
else
|
767 |
|
|
lo_port_v := src_i;
|
768 |
|
|
end if;
|
769 |
|
|
|
770 |
|
|
end if;
|
771 |
|
|
end if;
|
772 |
|
|
end loop; -- src_i
|
773 |
|
|
|
774 |
|
|
if hi_port_v /= no_dir_c and lo_port_v /= no_dir_c then
|
775 |
|
|
curr_dst_resolved(lo_port_v) <= no_dir_c;
|
776 |
|
|
end if;
|
777 |
|
|
|
778 |
|
|
end loop; -- dst_i
|
779 |
|
|
|
780 |
|
|
end process resolve_conflicts;
|
781 |
|
|
|
782 |
|
|
|
783 |
|
|
-----------------------------------------------------------------------------
|
784 |
|
|
incr_start_idx : process (clk_net, rst_n)
|
785 |
|
|
begin -- process incr_start_idx
|
786 |
|
|
if rst_n = '0' then -- asynchronous reset (active low)
|
787 |
|
|
start_idx_r <= 0;
|
788 |
|
|
elsif clk_net'event and clk_net = '1' then -- rising clock edge
|
789 |
|
|
if start_idx_r = n_ports_c-1 then
|
790 |
|
|
start_idx_r <= 0;
|
791 |
|
|
else
|
792 |
|
|
start_idx_r <= start_idx_r +1;
|
793 |
|
|
end if;
|
794 |
|
|
end if;
|
795 |
|
|
end process incr_start_idx;
|
796 |
|
|
|
797 |
|
|
|
798 |
|
|
-------------------------------------------------------------------------------
|
799 |
|
|
data_dbg : for i in 0 to n_ports_c-1 generate
|
800 |
|
|
data_ctrl_fifo_dbg (i) <= data_ctrl_fifo_r (i) when data_reg_valid_r (i) = '1'
|
801 |
|
|
else (others => dbg_value_c(sim_dbg_ena_g)); --(others => 'Z');
|
802 |
|
|
end generate data_dbg;
|
803 |
|
|
|
804 |
|
|
-----------------------------------------------------------------------------
|
805 |
|
|
-- enable channel 1
|
806 |
|
|
out_channel: process (clk_net, rst_n)
|
807 |
|
|
begin -- process out_channel
|
808 |
|
|
if rst_n = '0' then -- asynchronous reset (active low)
|
809 |
|
|
fwd_chan_sel_r <= '0';
|
810 |
|
|
rev_chan_sel_r <= '0';
|
811 |
|
|
fwd_pkt_counter_r <= 0;
|
812 |
|
|
rev_pkt_counter_r <= 0;
|
813 |
|
|
fwd_pkt_len_r <= 0;
|
814 |
|
|
rev_pkt_len_r <= 0;
|
815 |
|
|
|
816 |
|
|
elsif clk_net'event and clk_net = '1' then -- rising clock edge
|
817 |
|
|
|
818 |
|
|
-- get the pkt length
|
819 |
|
|
if state_src_r(fwd_c) /= no_dir_c then
|
820 |
|
|
fwd_pkt_len_r <= pkt_len_arr_r(state_src_r(fwd_c));
|
821 |
|
|
end if;
|
822 |
|
|
|
823 |
|
|
-- if read enable is up, receiving router is reading a flit
|
824 |
|
|
if re_fwd_in = '1' then
|
825 |
|
|
|
826 |
|
|
-- last flit about to be read?
|
827 |
|
|
if fwd_pkt_counter_r = fwd_pkt_len_r - 1 then
|
828 |
|
|
fwd_pkt_counter_r <= 0;
|
829 |
|
|
else
|
830 |
|
|
fwd_pkt_counter_r <= fwd_pkt_counter_r + 1;
|
831 |
|
|
end if;
|
832 |
|
|
|
833 |
|
|
end if;
|
834 |
|
|
|
835 |
|
|
|
836 |
|
|
-- if no packet is yet being sent or if one packet has
|
837 |
|
|
-- just been completed, we can change the fifos
|
838 |
|
|
if (fwd_pkt_counter_r = 0 and re_fwd_in = '0')
|
839 |
|
|
or (fwd_pkt_counter_r = fwd_pkt_len_r - 1 and re_fwd_in = '1')
|
840 |
|
|
then
|
841 |
|
|
|
842 |
|
|
-- if fifo1 not empty, switch to it
|
843 |
|
|
if empty_from_fwd1 = '0' then
|
844 |
|
|
fwd_chan_sel_r <= '1';
|
845 |
|
|
else
|
846 |
|
|
-- falling back to channel 0
|
847 |
|
|
fwd_chan_sel_r <= '0';
|
848 |
|
|
end if;
|
849 |
|
|
|
850 |
|
|
end if;
|
851 |
|
|
|
852 |
|
|
|
853 |
|
|
-- same for the rev
|
854 |
|
|
if state_src_r(rev_c) /= no_dir_c then
|
855 |
|
|
rev_pkt_len_r <= pkt_len_arr_r(state_src_r(rev_c));
|
856 |
|
|
end if;
|
857 |
|
|
|
858 |
|
|
if re_rev_in = '1' then
|
859 |
|
|
|
860 |
|
|
if rev_pkt_counter_r = rev_pkt_len_r - 1 then
|
861 |
|
|
rev_pkt_counter_r <= 0;
|
862 |
|
|
else
|
863 |
|
|
rev_pkt_counter_r <= rev_pkt_counter_r + 1;
|
864 |
|
|
end if;
|
865 |
|
|
end if;
|
866 |
|
|
|
867 |
|
|
if (rev_pkt_counter_r = 0 and re_rev_in = '0') or
|
868 |
|
|
(rev_pkt_counter_r = rev_pkt_len_r - 1 and re_rev_in = '1')
|
869 |
|
|
then
|
870 |
|
|
-- if fifo1 not empty, switch to it
|
871 |
|
|
if empty_from_rev1 = '0' then
|
872 |
|
|
rev_chan_sel_r <= '1';
|
873 |
|
|
else
|
874 |
|
|
-- falling back to channel 0
|
875 |
|
|
rev_chan_sel_r <= '0';
|
876 |
|
|
end if;
|
877 |
|
|
end if;
|
878 |
|
|
|
879 |
|
|
end if;
|
880 |
|
|
end process out_channel;
|
881 |
|
|
|
882 |
|
|
-----------------------------------------------------------------------------
|
883 |
|
|
Main_control : process (clk_net, rst_n)
|
884 |
|
|
begin -- process Main_control
|
885 |
|
|
if rst_n = '0' then -- asynchronous reset (active low)
|
886 |
|
|
for i in 0 to n_ports_c-1 loop
|
887 |
|
|
data_ctrl_fifo_r (i) <= (others => '0'); --'0');
|
888 |
|
|
send_counter_r (i) <= 0;
|
889 |
|
|
pkt_len_arr_r(i) <= pkt_len_g;
|
890 |
|
|
end loop; -- i
|
891 |
|
|
|
892 |
|
|
we_ctrl_fifo_r <= (others => '0');
|
893 |
|
|
re_r <= (others => '0');
|
894 |
|
|
State_writing_r <= (others => '0');
|
895 |
|
|
State_reading_r <= (others => '0');
|
896 |
|
|
state_src_r <= (others => no_dir_c);
|
897 |
|
|
state_dst_r <= (others => no_dir_c);
|
898 |
|
|
state_channel_r <= (others => 0);
|
899 |
|
|
|
900 |
|
|
data_reg_valid_r <= (others => '1');
|
901 |
|
|
|
902 |
|
|
if stfwd_en_g = 1 then
|
903 |
|
|
assert fifo_depth_g = pkt_len_g report "Store-and-forward assumes fifo_depth equal to packet_length" severity failure;
|
904 |
|
|
end if;
|
905 |
|
|
|
906 |
|
|
elsif clk_net'event and clk_net = '1' then -- rising clock edge
|
907 |
|
|
|
908 |
|
|
|
909 |
|
|
for i in 0 to n_ports_c-1 loop
|
910 |
|
|
-- Handle all directions
|
911 |
|
|
|
912 |
|
|
|
913 |
|
|
-- From now on, loop variable i refers to source port
|
914 |
|
|
|
915 |
|
|
if State_reading_r (i) = '1' then
|
916 |
|
|
-- Already reading from direction i
|
917 |
|
|
|
918 |
|
|
-- Use counters to enable cut-through switching.
|
919 |
|
|
-- The same thing works also with store-and-forward switching
|
920 |
|
|
if send_counter_r (i) = pkt_len_arr_r(i)
|
921 |
|
|
then
|
922 |
|
|
-- stop
|
923 |
|
|
|
924 |
|
|
if full_from_fifo (state_dst_r (i)) = '0' then
|
925 |
|
|
|
926 |
|
|
we_ctrl_fifo_r (state_dst_r (i)) <= '0';
|
927 |
|
|
re_r (i) <= '0';
|
928 |
|
|
|
929 |
|
|
State_writing_r (state_dst_r (i)) <= '0';
|
930 |
|
|
State_reading_r (i) <= '0';
|
931 |
|
|
state_src_r (state_dst_r (i)) <= no_dir_c;
|
932 |
|
|
state_dst_r (i) <= no_dir_c;
|
933 |
|
|
--assert false report "Tx to north fifo completed" severity note;
|
934 |
|
|
state_channel_r(state_dst_r(i)) <= 0;
|
935 |
|
|
|
936 |
|
|
send_counter_r (i) <= 0;
|
937 |
|
|
data_ctrl_fifo_r (state_dst_r (i)) <= (others => dbg_value_c(sim_dbg_ena_g));
|
938 |
|
|
data_reg_valid_r (state_dst_r (i)) <= '0';
|
939 |
|
|
|
940 |
|
|
pkt_len_arr_r(i) <= pkt_len_g;
|
941 |
|
|
|
942 |
|
|
--assert state_dst_r(i)/=4 report "Stop" severity note;
|
943 |
|
|
else
|
944 |
|
|
--assert state_dst_r(i)/=4 report "Wait until last data fits into fifo" severity note;
|
945 |
|
|
end if;
|
946 |
|
|
|
947 |
|
|
else
|
948 |
|
|
-- Packet transfer not yet complete
|
949 |
|
|
-- Continue transfer
|
950 |
|
|
we_ctrl_fifo_r (state_dst_r (i)) <= '1';
|
951 |
|
|
|
952 |
|
|
State_writing_r (state_dst_r (i)) <= State_writing_r (state_dst_r (i));
|
953 |
|
|
State_reading_r (i) <= State_reading_r (i);
|
954 |
|
|
state_src_r (state_dst_r (i)) <= state_src_r (state_dst_r (i));
|
955 |
|
|
state_dst_r (i) <= state_dst_r (i);
|
956 |
|
|
state_channel_r (state_dst_r(i)) <= state_channel_r (state_dst_r (i));
|
957 |
|
|
--assert false report "Tx to north fifo in progress" severity note;
|
958 |
|
|
|
959 |
|
|
|
960 |
|
|
-- i = source
|
961 |
|
|
if data_reg_valid_r (state_dst_r(i)) = '0' then
|
962 |
|
|
-- data_reg empty
|
963 |
|
|
|
964 |
|
|
if re_tmp (i) = '1' then
|
965 |
|
|
data_reg_valid_r (state_dst_r(i)) <= '1'; -- read new value
|
966 |
|
|
send_counter_r (i) <= send_counter_r (i) +1;
|
967 |
|
|
data_ctrl_fifo_r (state_dst_r (i)) <= Incoming_data (i);
|
968 |
|
|
|
969 |
|
|
else
|
970 |
|
|
data_reg_valid_r (state_dst_r(i)) <= '0'; -- stay empty
|
971 |
|
|
end if;
|
972 |
|
|
|
973 |
|
|
else
|
974 |
|
|
-- data_reg full
|
975 |
|
|
|
976 |
|
|
if full_from_fifo (state_dst_r (i)) = '0' then
|
977 |
|
|
-- write old to fifo
|
978 |
|
|
if re_tmp (i) = '1' then
|
979 |
|
|
data_reg_valid_r (state_dst_r(i)) <= '1'; -- write old, read new value
|
980 |
|
|
send_counter_r (i) <= send_counter_r (i) +1;
|
981 |
|
|
data_ctrl_fifo_r (state_dst_r (i)) <= Incoming_data (i);
|
982 |
|
|
else
|
983 |
|
|
data_reg_valid_r (state_dst_r(i)) <= '0'; -- write old, now empty
|
984 |
|
|
end if;
|
985 |
|
|
|
986 |
|
|
else
|
987 |
|
|
-- cannot write old
|
988 |
|
|
data_reg_valid_r (state_dst_r(i)) <= '1';
|
989 |
|
|
assert re_tmp (i) = '0' report "reading not allowed now" severity error;
|
990 |
|
|
end if;
|
991 |
|
|
|
992 |
|
|
end if;
|
993 |
|
|
|
994 |
|
|
-- if address hasn't been read, put in the channel bit
|
995 |
|
|
if send_counter_r(i) = 0 then
|
996 |
|
|
if state_channel_r(state_dst_r(i)) = 1 then
|
997 |
|
|
data_ctrl_fifo_r(state_dst_r(i))(addr_width_c) <= '1';
|
998 |
|
|
else
|
999 |
|
|
data_ctrl_fifo_r(state_dst_r(i))(addr_width_c) <= '0';
|
1000 |
|
|
end if;
|
1001 |
|
|
end if;
|
1002 |
|
|
|
1003 |
|
|
|
1004 |
|
|
-- Reading the pkt length
|
1005 |
|
|
if len_flit_en_g = 0 and re_tmp(i) = '1' and send_counter_r(i) = 0 then
|
1006 |
|
|
-- +1 at the end: address flit
|
1007 |
|
|
pkt_len_arr_r(i) <= conv_integer( unsigned( Incoming_data(i)(data_width_g-1 downto data_width_g-len_width_c))) + 1;
|
1008 |
|
|
elsif len_flit_en_g = 1 and re_tmp(i) = '1' and send_counter_r(i) = 1 then
|
1009 |
|
|
-- +2: address and len flits
|
1010 |
|
|
pkt_len_arr_r(i) <= conv_integer( unsigned( Incoming_data(i) )) + 2;
|
1011 |
|
|
end if;
|
1012 |
|
|
|
1013 |
|
|
|
1014 |
|
|
-- Stop reading little bit earlier than writing stops
|
1015 |
|
|
if send_counter_r (i) = pkt_len_arr_r(i) - 1
|
1016 |
|
|
and Incoming_empty (i) = '0' -- 2006/10/24
|
1017 |
|
|
and full_from_fifo (state_dst_r(i)) = '0'
|
1018 |
|
|
then
|
1019 |
|
|
re_r (i) <= '0';
|
1020 |
|
|
else
|
1021 |
|
|
re_r (i) <= '1';
|
1022 |
|
|
end if;
|
1023 |
|
|
|
1024 |
|
|
|
1025 |
|
|
end if;
|
1026 |
|
|
|
1027 |
|
|
else
|
1028 |
|
|
-- Not yet reading from direction i
|
1029 |
|
|
|
1030 |
|
|
-- Direction i has to be current source,
|
1031 |
|
|
-- there must be valid address on port i
|
1032 |
|
|
-- and target fifo has to be empty (i.e. it is not full or reserved)
|
1033 |
|
|
-- also state_channel must match the curr_channel so that
|
1034 |
|
|
-- empty_from_fifo signal comes from the right fifo
|
1035 |
|
|
if -- curr_src_r = i and
|
1036 |
|
|
curr_dst_resolved (i) /= no_dir_c
|
1037 |
|
|
and empty_from_fifo (curr_dst_resolved (i)) = '1'
|
1038 |
|
|
and State_writing_r (curr_dst_resolved (i)) = '0'
|
1039 |
|
|
and curr_channel(i) = state_channel_r(curr_dst_resolved(i))
|
1040 |
|
|
then
|
1041 |
|
|
-- Start reading
|
1042 |
|
|
|
1043 |
|
|
we_ctrl_fifo_r (curr_dst_resolved (i)) <= '0';
|
1044 |
|
|
-- WE not yet '1' because RE is just being asserted to one
|
1045 |
|
|
-- Otherwise, the first data (i.e.) would be written twice and the
|
1046 |
|
|
-- last data would be discarded
|
1047 |
|
|
State_writing_r (curr_dst_resolved (i)) <= '1';
|
1048 |
|
|
|
1049 |
|
|
re_r (i) <= '1';
|
1050 |
|
|
State_reading_r (i) <= '1';
|
1051 |
|
|
state_src_r (curr_dst_resolved (i)) <= i;
|
1052 |
|
|
state_dst_r (i) <= curr_dst_resolved (i);
|
1053 |
|
|
|
1054 |
|
|
send_counter_r (i) <= send_counter_r (i); --??
|
1055 |
|
|
data_ctrl_fifo_r (curr_dst_resolved (i)) <= Incoming_data (i);
|
1056 |
|
|
|
1057 |
|
|
-- if writing address, include the current channel bit
|
1058 |
|
|
if state_channel_r(curr_dst_resolved(i)) = 1 then
|
1059 |
|
|
data_ctrl_fifo_r(curr_dst_resolved(i))(addr_width_c) <= '1';
|
1060 |
|
|
else
|
1061 |
|
|
data_ctrl_fifo_r(curr_dst_resolved(i))(addr_width_c) <= '0';
|
1062 |
|
|
end if;
|
1063 |
|
|
|
1064 |
|
|
|
1065 |
|
|
data_reg_valid_r (curr_dst_resolved (i)) <= '1';
|
1066 |
|
|
|
1067 |
|
|
--else
|
1068 |
|
|
-- Can't start reading from current source
|
1069 |
|
|
-- Do nothing
|
1070 |
|
|
|
1071 |
|
|
end if; --State_reading_r = i
|
1072 |
|
|
|
1073 |
|
|
-- set the channel register when address is valid
|
1074 |
|
|
if curr_dst_resolved(i) /= no_dir_c
|
1075 |
|
|
and State_writing_r(curr_dst_resolved(i)) = '0'
|
1076 |
|
|
then
|
1077 |
|
|
state_channel_r(curr_dst_resolved(i)) <= curr_channel(i);
|
1078 |
|
|
end if;
|
1079 |
|
|
|
1080 |
|
|
end if; --State_reading_r(i)=1
|
1081 |
|
|
|
1082 |
|
|
end loop; -- i
|
1083 |
|
|
|
1084 |
|
|
end if; --Rst_n/Clk'event
|
1085 |
|
|
end process Main_control;
|
1086 |
|
|
|
1087 |
|
|
end rtl;
|