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

Subversion Repositories funbase_ip_library

[/] [funbase_ip_library/] [trunk/] [TUT/] [ip.hwp.communication/] [fh_ring/] [1.0/] [vhd/] [ring_router.vhd] - Blame information for rev 145

Details | Compare with Previous | View Log

Line No. Rev Author Line
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;

powered by: WebSVN 2.1.0

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