OpenCores
URL https://opencores.org/ocsvn/an-fpga-implementation-of-low-latency-noc-based-mpsoc/an-fpga-implementation-of-low-latency-noc-based-mpsoc/trunk

Subversion Repositories an-fpga-implementation-of-low-latency-noc-based-mpsoc

[/] [an-fpga-implementation-of-low-latency-noc-based-mpsoc/] [trunk/] [mpsoc/] [rtl/] [src_noc/] [mesh_torus.sv] - Blame information for rev 56

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 54 alirezamon
`include "pronoc_def.v"
2
 
3
/**********************************************************************
4
**      File:  mesh_torus.v
5
**
6
**      Copyright (C) 2014-2017  Alireza Monemi
7
**
8
**      This file is part of ProNoC
9
**
10
**      ProNoC ( stands for Prototype Network-on-chip)  is free software:
11
**      you can redistribute it and/or modify it under the terms of the GNU
12
**      Lesser General Public License as published by the Free Software Foundation,
13
**      either version 2 of the License, or (at your option) any later version.
14
**
15
**      ProNoC is distributed in the hope that it will be useful, but WITHOUT
16
**      ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
17
**      or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General
18
**      Public License for more details.
19
**
20
**      You should have received a copy of the GNU Lesser General Public
21
**      License along with ProNoC. If not, see .
22
**
23
**
24
**      Description:
25
**
26
**
27
***************************************/
28
 
29
 
30
 
31
 
32
/*****************************************
33
 
34
pre-sel[xy]
35
    y
36
1   |   3
37
    |
38
 -------x
39
 
40
    |
41
 
42
*****************************************/
43
 
44
 
45
module  mesh_torus_vc_alloc_request_gen_adaptive #(
46
    parameter ROUTE_TYPE =  "FULL_ADAPTIVE",    // "FULL_ADAPTIVE", "PAR_ADAPTIVE"
47
    parameter V = 4,
48
    parameter DSTPw=4,
49
    parameter SSA_EN ="NO",
50
    parameter PPSw=4,
51
    parameter [V-1  :   0] ESCAP_VC_MASK = 4'b1000   // mask scape vc, valid only for full adaptive
52
 
53
)(
54
    ovc_avalable_all,
55
    dest_port_coded_all,
56
    candidate_ovc_all,
57
    ivc_request_all,
58
    ovc_is_assigned_all,
59
    masked_ovc_request_all,
60
    port_pre_sel,
61
    swap_port_presel,
62
    destport_clear_all,
63
    ivc_num_getting_ovc_grant,
64
    ssa_ivc_num_getting_ovc_grant_all,
65
    sel,
66
    reset,
67
    clk
68
 
69
);
70
    localparam  P = 5;
71
 
72
    localparam  P_1     =   P-1,
73
                PV      =   V       *   P,
74
                PVV     =   PV      *  V,
75
                VP_1    =   V       *   P_1,
76
                PVDSTPw = PV * DSTPw;
77
 
78
     localparam LOCAL   =   3'd0,
79
                EAST    =   3'd1,
80
                NORTH   =   3'd2,
81
                WEST    =   3'd3,
82
                SOUTH   =   3'd4;
83
 
84
    input   [PV-1       :   0]  ovc_avalable_all;
85
    input   [PVDSTPw-1  :   0]  dest_port_coded_all;
86
    input   [PV-1       :   0]  ivc_request_all;
87
    input   [PV-1       :   0]  ovc_is_assigned_all;
88
    output  [PVV-1      :   0]  masked_ovc_request_all;
89
    input   [PVV-1      :   0]  candidate_ovc_all;
90
    input   [PPSw-1     :   0]  port_pre_sel;
91
    output  [PV-1       :   0]  swap_port_presel;
92
    output  [PV-1       :   0]  sel;
93
    output  [PVDSTPw-1 : 0] destport_clear_all;
94
    input   [PV-1 : 0] ivc_num_getting_ovc_grant;
95
    input   [PV-1 : 0] ssa_ivc_num_getting_ovc_grant_all;
96
    input                       reset,clk;
97
 
98
 
99
    wire    [PV-1       :   0]  non_assigned_ovc_request_all;
100
    wire    [PV-1       :   0]  y_evc_forbiden,x_evc_forbiden;
101
    wire    [V-1        :   0]  ovc_avb_x_plus,ovc_avb_x_minus,ovc_avb_y_plus,ovc_avb_y_minus,ovc_avb_local;
102
    wire    [VP_1-1     :   0]  ovc_avalable_perport            [P-1    :   0];
103
    wire    [PPSw-1     :   0]  port_pre_sel_perport            [P-1    :   0];
104
    wire    [PVV-1      :   0]  candidate_ovc_x_all, candidate_ovc_y_all;
105
 
106
 
107
    assign non_assigned_ovc_request_all =   ivc_request_all & ~ovc_is_assigned_all;
108
    assign {ovc_avb_y_minus,ovc_avb_x_minus,ovc_avb_y_plus,ovc_avb_x_plus,ovc_avb_local} = ovc_avalable_all;
109
 
110
 
111
 
112
        assign ovc_avalable_perport[LOCAL]  = {ovc_avb_x_plus,ovc_avb_x_minus,ovc_avb_y_plus,ovc_avb_y_minus};
113
        assign ovc_avalable_perport[EAST]   = {ovc_avb_local,ovc_avb_x_minus,ovc_avb_y_plus,ovc_avb_y_minus};
114
        assign ovc_avalable_perport[NORTH]  = {ovc_avb_x_plus,ovc_avb_x_minus,ovc_avb_local,ovc_avb_y_minus};
115
        assign ovc_avalable_perport[WEST]   = {ovc_avb_x_plus,ovc_avb_local,ovc_avb_y_plus,ovc_avb_y_minus};
116
        assign ovc_avalable_perport[SOUTH]  = {ovc_avb_x_plus,ovc_avb_x_minus,ovc_avb_y_plus,ovc_avb_local};
117
 
118
 
119
 
120
    assign port_pre_sel_perport[LOCAL]   = port_pre_sel;
121
    assign port_pre_sel_perport[EAST]    = {2'b00,port_pre_sel[1:0]};
122
    assign port_pre_sel_perport[NORTH]   = {1'b0,port_pre_sel[2],1'b0,port_pre_sel[0]};
123
    assign port_pre_sel_perport[WEST]    = {port_pre_sel[3:2],2'b0};
124
    assign port_pre_sel_perport[SOUTH]   = {port_pre_sel[3],1'b0,port_pre_sel[1],1'b0};
125
 
126
 
127
    wire    [PV-1   :   0]  avc_unavailable;
128
    genvar i;
129
    generate
130
 
131
 
132
    for(i=0;i< PV;i=i+1) begin :all_vc_loop
133
 
134
       mesh_torus_adaptive_avb_ovc_mux #(
135
        .V(V)
136
       )
137
       the_adaptive_avb_ovc_mux
138
       (
139
        .ovc_avalable               (ovc_avalable_perport   [i/V]),
140
        .sel                        (sel                    [i]),
141
        .candidate_ovc_x            (candidate_ovc_x_all    [((i+1)*V)-1 : i*V]),
142
        .candidate_ovc_y            (candidate_ovc_y_all    [((i+1)*V)-1 : i*V]),
143
        .non_assigned_ovc_request   (non_assigned_ovc_request_all[i]),
144
        .xydir                      (dest_port_coded_all     [((i+1)*DSTPw)-1 : ((i+1)*DSTPw)-2]),
145
        .masked_ovc_request         (masked_ovc_request_all [((i+1)*V)-1 : i*V])
146
       );
147
 
148
        mesh_torus_port_selector #(
149
               .SW_LOC     (i/V),
150
               .PPSw(PPSw)
151
        )
152
        the_portsel
153
        (
154
               .port_pre_sel       (port_pre_sel_perport[i/V]),
155
               .swap_port_presel   (swap_port_presel[i]),
156
               .sel                (sel[i]),
157
               .dest_port_in       (dest_port_coded_all[((i+1)*DSTPw)-1 : i*DSTPw]),
158
               .y_evc_forbiden     (y_evc_forbiden[i]),
159
           .x_evc_forbiden     (x_evc_forbiden[i])
160
              );
161
 
162
        mesh_tori_dspt_clear_gen #(
163
                .SSA_EN(SSA_EN),
164
                .DSTPw(DSTPw),
165
                .SW_LOC(i/V)
166
        )
167
        dspt_clear_gen
168
        (
169
                .destport_clear(destport_clear_all[((i+1)*DSTPw)-1 : i*DSTPw]),
170
                .ivc_num_getting_ovc_grant(ivc_num_getting_ovc_grant[i]),
171
                .sel(sel[i]),
172
                .ssa_ivc_num_getting_ovc_grant(ssa_ivc_num_getting_ovc_grant_all[i])
173
        );
174
 
175
 
176
            /* verilator lint_off WIDTH */
177
        if(ROUTE_TYPE ==  "FULL_ADAPTIVE") begin: full_adpt
178
        /* verilator lint_on WIDTH */
179
            assign candidate_ovc_y_all[((i+1)*V)-1 : i*V] =  (y_evc_forbiden[i]) ? candidate_ovc_all[((i+1)*V)-1 : i*V] & (~ESCAP_VC_MASK) :  candidate_ovc_all[((i+1)*V)-1 : i*V];
180
            assign candidate_ovc_x_all[((i+1)*V)-1 : i*V] =  (x_evc_forbiden[i]) ? candidate_ovc_all[((i+1)*V)-1 : i*V] & (~ESCAP_VC_MASK) :  candidate_ovc_all[((i+1)*V)-1 : i*V];
181
            assign avc_unavailable[i] = (masked_ovc_request_all [((i+1)*V)-1 : i*V] & ~ESCAP_VC_MASK) == {V{1'b0}};
182
 
183
 
184
            mesh_torus_swap_port_presel_gen #(
185
                .V(V),
186
                .ESCAP_VC_MASK(ESCAP_VC_MASK),
187
                .VC_NUM(i)
188
            )
189
            the_swap_port_presel
190
            (
191
                .avc_unavailable(avc_unavailable[i]),
192
                .y_evc_forbiden(y_evc_forbiden[i]),
193
                .x_evc_forbiden(x_evc_forbiden[i]),
194
                .non_assigned_ovc_request(non_assigned_ovc_request_all[i]),
195
                .sel(sel[i]),
196
                .clk(clk),
197
                .reset(reset),
198
                .swap_port_presel(swap_port_presel[i])
199
            );
200
 
201
 
202
        end else begin : partial_adpt
203
            assign candidate_ovc_y_all[((i+1)*V)-1 : i*V] =   candidate_ovc_all [((i+1)*V)-1 : i*V];
204
            assign candidate_ovc_x_all[((i+1)*V)-1 : i*V] =   candidate_ovc_all [((i+1)*V)-1 : i*V];
205
            assign swap_port_presel[i]=1'b0;
206
            assign avc_unavailable[i]=1'b0;
207
 
208
        end// ROUTE_TYPE
209
    end//for
210
 
211
endgenerate
212
endmodule
213
 
214
 
215
 
216
module mesh_tori_dspt_clear_gen #(
217
    parameter SSA_EN="YES",
218
    parameter DSTPw =4,
219
    parameter SW_LOC=0
220
 
221
)(
222
    destport_clear,
223
    ivc_num_getting_ovc_grant,
224
    sel,
225
    ssa_ivc_num_getting_ovc_grant
226
 
227
);
228
 
229
    output [DSTPw-1 : 0] destport_clear;
230
    input ivc_num_getting_ovc_grant;
231
    input sel;
232
    input ssa_ivc_num_getting_ovc_grant;
233
 
234
 localparam
235
    LOCAL   =   3'd0,
236
    EAST    =   3'd1,
237
    WEST    =   3'd3;
238
 
239
generate
240
    /* verilator lint_off WIDTH */
241
    if ( SSA_EN=="YES" ) begin :predict_if
242
    /* verilator lint_on WIDTH */
243
        if (SW_LOC == LOCAL ) begin :local_if
244
            assign destport_clear= (ivc_num_getting_ovc_grant)?{2'b00,sel,~sel} :{DSTPw{1'b0}};
245
        end else if (SW_LOC == EAST || SW_LOC == WEST ) begin :xdir_if
246
            assign destport_clear = (ivc_num_getting_ovc_grant)? {2'b00,sel,~sel} :
247
                                                                   (ssa_ivc_num_getting_ovc_grant)? 4'b0001: //clear b
248
                                                                   4'b0000;
249
        end else begin : ydir_if
250
             assign destport_clear = (ivc_num_getting_ovc_grant)? {2'b00,sel,~sel} :
251
                                                                    (ssa_ivc_num_getting_ovc_grant)? 4'b0010: //clear a
252
                                                                    4'b0000;
253
        end
254
        end else begin :nopredict_if
255
              assign destport_clear = (ivc_num_getting_ovc_grant )? {2'b00,sel,~sel} :{DSTPw{1'b0}};
256
        end//   nopredict_if
257
endgenerate
258
endmodule
259
 
260
 
261
 
262
module   mesh_torus_mask_non_assignable_destport #(
263
    parameter TOPOLOGY="MESH",
264
    parameter ROUTE_NAME="XY",
265
    parameter SW_LOC=0,
266
    parameter P=5,
267
    parameter SELF_LOOP_EN="NO"
268
)
269
(
270
   odd_column,// use only for odd even routing
271
   dest_port_in,
272
   dest_port_out
273
);
274
 
275
    localparam P_1 = (SELF_LOOP_EN=="NO") ? P-1 : P;
276
    input  [P_1-1 : 0 ] dest_port_in;
277
    output [P_1-1 : 0 ] dest_port_out;
278
    input odd_column;
279
 
280
    wire  [P-2 : 0] dest_port_in_tmp,dest_port_out_tmp;
281
 
282
    generate
283
    if(SELF_LOOP_EN == "NO") begin :nslp
284
        assign dest_port_in_tmp = dest_port_in;
285
        assign dest_port_out = dest_port_out_tmp;
286
    end else begin :slp
287
        remove_sw_loc_one_hot #(
288
            .P(P),
289
            .SW_LOC(SW_LOC)
290
        )
291
        remove_sw_loc
292
        (
293
                .destport_in(dest_port_in),
294
                .destport_out(dest_port_in_tmp)
295
        );
296
        //currently loop-back only can happen in local ports.
297
        //Current supported routing algorithms does not results in loop-back in other ports
298
        wire sw_loc_val = (SW_LOC>0 && SW_LOC<5) ? 1'b0 : dest_port_in [SW_LOC];
299
 
300
        add_sw_loc_one_hot_val #(
301
            .P(P),
302
            .SW_LOC(SW_LOC)
303
        )add_sw_loc
304
        (
305
            .sw_loc_val(sw_loc_val),
306
            .destport_in (dest_port_out_tmp),
307
            .destport_out(dest_port_out)
308
        );
309
 
310
 
311
 
312
 
313
    end
314
    endgenerate
315
 
316
    mesh_torus_mask_non_assignable_destport_no_self_loop # (
317
        .TOPOLOGY(TOPOLOGY),
318
        .ROUTE_NAME(ROUTE_NAME),
319
        .SW_LOC(SW_LOC),
320
        .P(P)
321
    )
322
    mask_no_self_loop
323
    (
324
        .dest_port_in(dest_port_in_tmp),
325
        .dest_port_out(dest_port_out_tmp),
326
        .odd_column(odd_column)
327
    );
328
 
329
 
330
endmodule
331
 
332
module   mesh_torus_mask_non_assignable_destport_no_self_loop #(
333
    parameter TOPOLOGY="MESH",
334
    parameter ROUTE_NAME="XY",
335
    parameter SW_LOC=0,
336
    parameter P=5
337
)
338
(
339
   odd_column,// use only for odd even routing
340
   dest_port_in,
341
   dest_port_out
342
);
343
 
344
localparam
345
    EAST    =       1,
346
    NORTH   =       2,
347
    WEST    =       3,
348
    SOUTH   =       4;
349
 
350
//port number in north port
351
localparam
352
    N_LOCAL   =       0,
353
    N_EAST    =       1,
354
    N_WEST    =       2,
355
    N_SOUTH   =       3;
356
 
357
 // port number in south port
358
 localparam
359
    S_LOCAL   =       0,
360
    S_EAST    =       1,
361
    S_NORTH   =       2,
362
    S_WEST    =       3;
363
 
364
 // port number in east port
365
 localparam
366
    E_LOCAL   =       0,
367
    E_NORTH   =       1,
368
    E_WEST    =       2,
369
    E_SOUTH   =       3;
370
 
371
   // port number in east port
372
 localparam
373
    W_LOCAL   =       0,
374
    W_EAST    =       1,
375
    W_NORTH   =       2,
376
    W_SOUTH   =       3;
377
 
378
 
379
    localparam P_1 = P-1;
380
    input [P_1-1  : 0 ] dest_port_in;
381
    output [P_1-1 : 0 ] dest_port_out;
382
    input odd_column;
383
 
384
 
385
    generate
386
    if(P>5)begin :p5
387
            assign dest_port_out[P_1-1:4] = dest_port_in[P_1-1:4]; //other local ports
388
            end
389
 
390
 
391
    /* verilator lint_off WIDTH */
392
    if (TOPOLOGY == "RING" || TOPOLOGY == "LINE") begin : oneD // A port can send packets to all other ports in these topologies
393
    /* verilator lint_on WIDTH */
394
        assign  dest_port_out = dest_port_in;
395
    end else begin : towD
396
    /*XY*/
397
        /* verilator lint_off WIDTH */
398
        if ( ROUTE_NAME == "XY" || ROUTE_NAME  == "TRANC_XY") begin :xy
399
        /* verilator lint_on WIDTH */
400
            if (SW_LOC == NORTH  ) begin : nort_p // The port located in y axsis does not send packets to x dimension
401
                assign dest_port_out[N_LOCAL]= dest_port_in[N_LOCAL];
402
                assign dest_port_out[N_EAST]= 1'b0; // mask east port
403
                assign dest_port_out[N_WEST]= 1'b0; // mask west port
404
                assign dest_port_out[N_SOUTH]= dest_port_in[N_SOUTH];
405
            end else if ( SW_LOC == SOUTH) begin : south_p
406
                assign dest_port_out[S_LOCAL]= dest_port_in[S_LOCAL];
407
                assign dest_port_out[S_EAST]= 1'b0; // mask east port
408
                assign dest_port_out[S_NORTH]= dest_port_in[S_NORTH];
409
                assign dest_port_out[S_WEST]= 1'b0; // mask west port
410
            end else begin : non_vertical
411
                 assign  dest_port_out[3:0] = dest_port_in[3:0];
412
            end
413
    /*WEST-FIRST*/
414
        /* verilator lint_off WIDTH */
415
        end else  if ( ROUTE_NAME == "WEST_FIRST" || ROUTE_NAME  == "TRANC_WEST_FIRST") begin :west_first
416
        /* verilator lint_on WIDTH */
417
         // SW &  NW are forbidden
418
            if (SW_LOC == NORTH  ) begin : nort_p // north port does not send packets to the west port.
419
                assign dest_port_out[N_LOCAL]= dest_port_in[N_LOCAL];
420
                assign dest_port_out[N_EAST]= dest_port_in[N_EAST];
421
                assign dest_port_out[N_WEST]= 1'b0; // mask west port
422
                assign dest_port_out[N_SOUTH]= dest_port_in[N_SOUTH];
423
            end else if ( SW_LOC == SOUTH) begin : south_p // south port does not sends packet to west
424
                assign dest_port_out[S_LOCAL]= dest_port_in[S_LOCAL];
425
                assign dest_port_out[S_EAST]= dest_port_in[S_EAST];
426
                assign dest_port_out[S_NORTH]= dest_port_in[S_NORTH];
427
                assign dest_port_out[S_WEST]= 1'b0; // mask west port
428
            end else begin : non_vertical
429
                 assign  dest_port_out[3:0] = dest_port_in[3:0];
430
            end
431
    /*NORTH_LAST*/
432
        /* verilator lint_off WIDTH */
433
        end else  if ( ROUTE_NAME == "NORTH_LAST" || ROUTE_NAME  == "TRANC_NORTH_LAST") begin :north_last
434
        /* verilator lint_on WIDTH */
435
            //NE & NW are forbidden
436
            if (SW_LOC == SOUTH  ) begin : south_p // north port does not send packets to the east nor to the west port.
437
                assign dest_port_out[S_LOCAL]= dest_port_in[S_LOCAL];
438
                assign dest_port_out[S_EAST]= 1'b0; // mask east port
439
                assign dest_port_out[S_WEST]= 1'b0; // mask west port
440
                assign dest_port_out[S_NORTH]= dest_port_in[S_NORTH];
441
            end else begin : other_p
442
                 assign  dest_port_out[3:0] = dest_port_in[3:0];
443
            end
444
    /*NEGETIVE_FIRST*/
445
        /* verilator lint_off WIDTH */
446
        end else  if ( ROUTE_NAME == "NEGETIVE_FIRST" || ROUTE_NAME  == "TRANC_NEGETIVE_FIRST") begin :negetive_first
447
        /* verilator lint_on WIDTH */
448
          //ES & NW is forbiden
449
            if (SW_LOC == SOUTH  ) begin : south_p // south port does not send packets to the west port. NW is forbiden
450
                assign dest_port_out[S_LOCAL]= dest_port_in[S_LOCAL];
451
                assign dest_port_out[S_EAST]= dest_port_in[S_EAST];
452
                assign dest_port_out[S_WEST]= 1'b0; // mask west port
453
                assign dest_port_out[S_NORTH]= dest_port_in[S_NORTH];
454
            end else if ( SW_LOC == WEST) begin : west_p // west port does not sends packet to south. ES is forbiden
455
                assign dest_port_out[W_LOCAL]= dest_port_in[W_LOCAL];
456
                assign dest_port_out[W_NORTH]= dest_port_in[W_NORTH];
457
                assign dest_port_out[W_EAST] = dest_port_in[W_EAST];
458
                assign dest_port_out[W_SOUTH]= 1'b0; //mask south port
459
            end else begin : other_p
460
                 assign  dest_port_out[3:0] = dest_port_in[3:0];
461
            end
462
    /*ODD_EVEN*/
463
        /* verilator lint_off WIDTH */
464
        end else  if ( ROUTE_NAME == "ODD_EVEN" ) begin : odd_even
465
        /* verilator lint_on WIDTH */
466
        //Odd column : NW and SW turns are not allowed
467
        //Even column: EN and ES turns are not allowed
468
 
469
           if (SW_LOC == NORTH  ) begin : nort_p // north port does not send packets to the west port in odd columns. SW is forbiden
470
                assign dest_port_out[N_LOCAL]= dest_port_in[N_LOCAL];
471
                assign dest_port_out[N_EAST]= dest_port_in[N_EAST];
472
                assign dest_port_out[N_WEST]= (odd_column)? 1'b0: dest_port_in[N_WEST];  // mask west port in odd columns
473
                assign dest_port_out[N_SOUTH]= dest_port_in[N_SOUTH];
474
             end else if (SW_LOC == SOUTH) begin : south_p // south port does not sends packet to west in odd columns. NW is forbiden
475
                assign dest_port_out[S_LOCAL]= dest_port_in[S_LOCAL];
476
                assign dest_port_out[S_EAST]= dest_port_in[S_EAST];
477
                assign dest_port_out[S_NORTH]= dest_port_in[S_NORTH];
478
                assign dest_port_out[S_WEST]= (odd_column)? 1'b0: dest_port_in[S_WEST];  // mask west port   in odd columns
479
 
480
 
481
           end else if (SW_LOC == WEST) begin : west_p // WEST port does not sends packet to north and south ports in even columns
482
            //ES & EN forbiden
483
                assign dest_port_out[W_LOCAL]= dest_port_in[W_LOCAL];
484
                assign dest_port_out[W_NORTH]= (odd_column)?   dest_port_in[W_NORTH] : 1'b0; //mask north in even columns
485
                assign dest_port_out[W_EAST] = dest_port_in[W_EAST];
486
                assign dest_port_out[W_SOUTH]= (odd_column)? dest_port_in[W_SOUTH] : 1'b0; //mask south in even columns
487
            end else begin: other_p
488
                assign  dest_port_out[3:0] = dest_port_in[3:0];
489
            end
490
 
491
    end else begin : f_adptv
492
                assign  dest_port_out[3:0] = dest_port_in[3:0];
493
        end
494
    end
495
    endgenerate
496
endmodule
497
 
498
 
499
 
500
 
501
/**********************
502
 
503
    swap_port_presel_gen
504
 
505
**********************/
506
 
507
module   mesh_torus_swap_port_presel_gen #(
508
    parameter V = 4,
509
    parameter [V-1  :   0] ESCAP_VC_MASK = 4'b1000,   // mask scape vc, valid only for full adaptive
510
    parameter VC_NUM=0
511
 
512
)(
513
    avc_unavailable,
514
    swap_port_presel,
515
    y_evc_forbiden,
516
    x_evc_forbiden,
517
    non_assigned_ovc_request,
518
    sel,
519
    clk,
520
    reset
521
 
522
);
523
 
524
    localparam LOCAL_VC_NUM= VC_NUM % V;
525
 
526
 
527
 
528
    input    avc_unavailable;
529
    input    y_evc_forbiden,x_evc_forbiden;
530
    input    non_assigned_ovc_request,sel;
531
    input    clk,reset;
532
    output   swap_port_presel;
533
    wire     swap_reg;
534
 
535
    wire swap_port_presel_next;
536
 
537
 
538
    wire  evc_forbiden;
539
 
540
 
541
    /************************
542
 
543
        destination-port_in
544
            x:  1 EAST, 0 WEST
545
            y:  1 NORTH, 0 SOUTH
546
            ab: 00 : LOCAL, 10: xdir, 01: ydir, 11 x&y dir
547
        sel:
548
             0: xdir
549
             1: ydir
550
        port_pre_sel
551
             0: xdir
552
             1: ydir
553
 
554
************************/
555
 
556
 
557
    //For an EVC sender, if the use of EVC in destination port is restricted while the destination port has no available AVC,
558
    //the port pre selection must swap
559
 
560
 
561
   // generate
562
    // check if it is an evc sender
563
   // if(ESCAP_VC_MASK[LOCAL_VC_NUM]== 1'b0)begin
564
    //its not EVC
565
    //   assign swap_port_presel=1'b0;
566
 
567
   // end else begin // the sender is an EVC
568
 
569
       assign  evc_forbiden = (sel)? y_evc_forbiden : x_evc_forbiden;
570
       assign  swap_port_presel_next= non_assigned_ovc_request & evc_forbiden & avc_unavailable;
571
       assign swap_port_presel = swap_reg;
572
 
573
       pronoc_register #(.W(1)) reg2 (.in(swap_port_presel_next ), .out(swap_reg), .reset(reset), .clk(clk));
574
 
575
 endmodule
576
 
577
 
578
 
579
 
580
/************************
581
 
582
    adaptive_avb_ovc_mux
583
 
584
 
585
************************/
586
module  mesh_torus_adaptive_avb_ovc_mux #(
587
   parameter V= 4
588
)(
589
    ovc_avalable,
590
    sel,
591
    candidate_ovc_x,
592
    candidate_ovc_y,
593
    non_assigned_ovc_request,
594
    xydir,
595
    masked_ovc_request
596
 
597
 
598
);
599
    localparam  P       =   5;
600
    localparam  P_1     =   P-1,
601
                VP_1    =   V  *  P_1;
602
 
603
    input   [VP_1-1    :    0] ovc_avalable;
604
    input                      sel;
605
    input   [V-1       :    0] candidate_ovc_x;
606
    input   [V-1       :    0] candidate_ovc_y;
607
    input                      non_assigned_ovc_request;
608
    input   [1         :    0] xydir;
609
    output  [V-1        :   0] masked_ovc_request;
610
    wire    x,y;
611
    wire    [V-1        :   0] ovc_avb_x_plus,ovc_avb_x_minus,ovc_avb_y_plus,ovc_avb_y_minus;
612
    wire    [V-1        :   0] mux_out_x,mux_out_y;
613
    wire    [V-1        :   0] ovc_request_x,ovc_request_y,masked_ovc_request_x,masked_ovc_request_y;
614
 
615
    assign {x,y}= xydir;
616
    assign {ovc_avb_x_plus,ovc_avb_x_minus,ovc_avb_y_plus,ovc_avb_y_minus}=ovc_avalable;
617
    //first level mux
618
    //assign mux_out_x = (x)?  ovc_avb_x_plus :  ovc_avb_x_minus;
619
    //assign mux_out_y = (y)?  ovc_avb_y_plus :  ovc_avb_y_minus;
620
    assign mux_out_x = (ovc_avb_x_plus &{V{x}}) |  (ovc_avb_x_minus &{V{~x}});
621
    assign mux_out_y = (ovc_avb_y_plus &{V{y}}) |  (ovc_avb_y_minus &{V{~y}});
622
 
623
 
624
    //assign ovc_request_x = (non_assigned_ovc_request)? candidate_ovc_x : {V{1'b0}};
625
    //assign ovc_request_y = (non_assigned_ovc_request)? candidate_ovc_y : {V{1'b0}};
626
    assign ovc_request_x =  candidate_ovc_x & {V{non_assigned_ovc_request}};
627
    assign ovc_request_y =  candidate_ovc_y & {V{non_assigned_ovc_request}};
628
 
629
    //mask unavailble ovc
630
    assign masked_ovc_request_x = mux_out_x & ovc_request_x;
631
    assign masked_ovc_request_y = mux_out_y & ovc_request_y;
632
 
633
    //second mux
634
   // assign masked_ovc_request = (sel)?  masked_ovc_request_y: masked_ovc_request_x;
635
     assign masked_ovc_request =  (masked_ovc_request_y & {V{sel}})| (masked_ovc_request_x & {V{~sel}});
636
 
637
 
638
endmodule
639
 
640
 
641
 
642
 
643
 
644
/*****************************************************
645
 
646
                port_selector
647
 
648
 
649
*****************************************************/
650
 
651
 
652
module mesh_torus_port_selector #(
653
    parameter SW_LOC    = 0,
654
    parameter PPSw=4
655
)
656
(
657
    port_pre_sel,
658
    dest_port_in,
659
    swap_port_presel,
660
    sel,
661
    y_evc_forbiden,
662
    x_evc_forbiden
663
);
664
 
665
/************************
666
 
667
        destination-port_in
668
            x:  1 EAST, 0 WEST
669
            y:  1 NORTH, 0 SOUTH
670
            ab: 00 : LOCAL, 10: xdir, 01: ydir, 11 x&y dir
671
        sel:
672
             0: xdir
673
             1: ydir
674
        port_pre_sel
675
             0: xdir
676
             1: ydir
677
 
678
************************/
679
 
680
 
681
    //input           reset,clk;
682
    input   [PPSw-1:0]   port_pre_sel;
683
   // input           port_pre_sel_ld;
684
    output          sel;
685
    input   [3:0]   dest_port_in;
686
    input           swap_port_presel;
687
   // output          route_subfunc_violated;
688
    output          y_evc_forbiden, x_evc_forbiden;
689
 
690
    wire  x,y,a,b;
691
    wire [PPSw-1:0] port_pre_sel_final;
692
    //reg  [3:0] port_pre_sel_delayed , port_pre_sel_latched;
693
  //  wire o1,o2;
694
 
695
 
696
    localparam LOCAL    =       0,
697
               EAST     =       1,
698
               NORTH    =       2,
699
               WEST     =       3,
700
               SOUTH    =       4;
701
 
702
    localparam LOCAL_SEL = (SW_LOC == NORTH || SW_LOC == SOUTH )? 1'b1 : 1'b0;
703
    assign port_pre_sel_final= (swap_port_presel)? ~port_pre_sel: port_pre_sel;
704
    assign {x,y,a,b} = dest_port_in;
705
 
706
 
707
     wire sel_in,sel_pre, overwrite;
708
     wire [1:0] xy;
709
 
710
     assign xy={x,y};
711
     assign sel_pre= port_pre_sel_final[xy];
712
 
713
     assign overwrite= a&b;
714
     generate
715
        if(LOCAL_SEL)begin :local_p
716
             assign sel_in= b | ~a;
717
        end else begin :nonlocal_p
718
             assign sel_in= b ;
719
        end
720
     endgenerate
721
 
722
    assign sel= (overwrite)? sel_pre : sel_in;
723
 
724
// check if EVC is allowed to be used
725
 
726
        // Using of all EVCs located in y dimension are restricted when the packet can be sent into both x&y direction
727
        assign y_evc_forbiden = a&b;
728
 
729
        //there is no restriction in using EVCs located in x dimension
730
        assign x_evc_forbiden = 1'b0;
731
        //assign route_subfunc_violated = a&b;
732
    /* verilator lint_off WIDTH */
733
 endmodule
734
 
735
 
736
 
737
/*******************
738
    mesh_torus_adaptive_lk_dest_encoder
739
********************/
740
 
741
 
742
 
743
module  mesh_torus_adaptive_lk_dest_encoder #(
744
    parameter V=4,
745
    parameter P=5,
746
    parameter DSTPw=P-1,
747
    parameter Fw=37,
748
    parameter DST_P_MSB=11,
749
    parameter DST_P_LSB=8
750
 
751
)(
752
    sel,
753
    flit_in,
754
    dest_coded_out,
755
    vc_num_delayed,
756
    lk_dest
757
);
758
 
759
    input [V-1 : 0]  sel;
760
    output [DSTPw-1 : 0]dest_coded_out;
761
    input [V-1 : 0]  vc_num_delayed;
762
    input [DSTPw-1 : 0]  lk_dest;
763
    input [Fw-1 : 0]  flit_in;
764
 
765
    wire [1 : 0]  ab,xy;
766
    wire sel_muxed;
767
 
768
    onehot_mux_1D #(
769
        .W(1),
770
        .N(V)
771
    )
772
    sel_mux
773
    (
774
        .in(sel),
775
        .out(sel_muxed),
776
        .sel(vc_num_delayed)
777
    );
778
 
779
 
780
    //lkdestport = {lkdestport_x[1:0],lkdestport_y[1:0]};
781
    // sel: 0: xdir     1: ydir
782
    assign ab = (sel_muxed)? lk_dest[1:0] : lk_dest[3:2];
783
    //if ab==00 change x and y direction
784
    assign xy = (ab>0)? flit_in[DST_P_MSB  : DST_P_LSB+2] : ~flit_in[DST_P_MSB  : DST_P_LSB+2] ;
785
 
786
    assign dest_coded_out={xy,ab};
787
 
788
endmodule
789
 
790
 
791
module  mesh_torus_dtrmn_dest_encoder #(
792
    parameter P=5,
793
    parameter DSTPw=P-1,
794
    parameter Fw=37,
795
    parameter DST_P_MSB=11,
796
    parameter DST_P_LSB=8
797
 
798
)(
799
    flit_in,
800
    dest_coded_out,
801
    lk_dest
802
);
803
 
804
 
805
    output [DSTPw-1 : 0]dest_coded_out;
806
 
807
    input [DSTPw-1 : 0]  lk_dest;
808
    input [Fw-1 : 0]  flit_in;
809
 
810
    wire [1 : 0]  ab,xy;
811
 
812
 
813
    //lkdestport = {lkdestport_x[1:0],lkdestport_y[1:0]};
814
    // sel: 0: xdir     1: ydir
815
    assign ab =  lk_dest[1:0];
816
    //if ab==00 change x and y direction
817
    assign xy = (ab>0)? flit_in[DST_P_MSB  : DST_P_LSB+2] : ~flit_in[DST_P_MSB  : DST_P_LSB+2] ;
818
 
819
    assign dest_coded_out={xy,ab};
820
 
821
endmodule
822
 
823
 
824
/********************
825
 
826
    distance_gen
827
 
828
********************/
829
 
830
module mesh_torus_distance_gen #(
831
    parameter T1= 4,    // number of node in x axis
832
    parameter T2= 4,    // number of node in y axis
833
    parameter T3= 4,
834
    parameter EAw=4,
835
    parameter DISTw=4,
836
    parameter TOPOLOGY  = "MESH"
837
 
838
)(
839
    src_e_addr,
840
    dest_e_addr,
841
    distance
842
);
843
 
844
    function integer log2;
845
      input integer number; begin
846
         log2=(number <=1) ? 1: 0;
847
         while(2**log2
848
            log2=log2+1;
849
         end
850
      end
851
    endfunction // log2
852
 
853
 
854
    localparam
855
        Xw  =   log2(T1),   // number of node in x axis
856
        Yw  =   log2(T2);    // number of node in y axis
857
    localparam [Xw : 0] NX  = T1;
858
    localparam [Yw : 0] NY  = T2;
859
 
860
 
861
   input [EAw-1 : 0] src_e_addr;
862
   input [EAw-1 : 0] dest_e_addr;
863
   output[DISTw-1:   0]distance;
864
 
865
    wire [Xw-1 :   0]src_x,dest_x;
866
    wire [Yw-1 :   0]src_y,dest_y;
867
 
868
    mesh_tori_endp_addr_decode #(
869
        .TOPOLOGY(TOPOLOGY),
870
        .T1(T1),
871
        .T2(T2),
872
        .T3(T3),
873
        .EAw(EAw)
874
    )
875
    src_addr_decode
876
    (
877
        .e_addr(src_e_addr),
878
        .ex(src_x),
879
        .ey(src_y),
880
        .el(),
881
        .valid()
882
    );
883
 
884
     mesh_tori_endp_addr_decode #(
885
        .TOPOLOGY(TOPOLOGY),
886
        .T1(T1),
887
        .T2(T2),
888
        .T3(T3),
889
        .EAw(EAw)
890
    )
891
    dest_addr_decode
892
    (
893
        .e_addr(dest_e_addr),
894
        .ex(dest_x),
895
        .ey(dest_y),
896
        .el(),
897
        .valid()
898
    );
899
 
900
    reg [Xw-1  :   0] x_offset;
901
    reg [Yw-1  :   0] y_offset;
902
 
903
    generate
904
    /* verilator lint_off WIDTH */
905
    if( TOPOLOGY == "MESH" || TOPOLOGY == "LINE") begin : oneD
906
    /* verilator lint_on WIDTH */
907
 
908
        always @(*) begin
909
            x_offset     = (src_x> dest_x)? src_x - dest_x : dest_x - src_x;
910
            y_offset     = (src_y> dest_y)? src_y - dest_y : dest_y - src_y;
911
         end
912
 
913
 
914
 
915
    end else begin : twoD //torus ring
916
 
917
        wire tranc_x_plus,tranc_x_min,tranc_y_plus,tranc_y_min,same_x,same_y;
918
 
919
        /* verilator lint_off WIDTH */
920
        always @ (*) begin
921
            x_offset= {Xw{1'b0}};
922
            y_offset= {Yw{1'b0}};
923
 
924
            //x_offset
925
            if(same_x) x_offset= {Xw{1'b0}};
926
            else if(tranc_x_plus) begin
927
                if(dest_x   > src_x)    x_offset= dest_x-src_x;
928
                else                    x_offset= (NX-src_x)+dest_x;
929
            end
930
            else if(tranc_x_min)  begin
931
                if(dest_x   <  src_x)    x_offset= src_x-dest_x;
932
                else                     x_offset= src_x+(NX-dest_x);
933
 
934
            end
935
 
936
             //y_offset
937
            if(same_y) y_offset= {Yw{1'b0}};
938
            else if(tranc_y_plus) begin
939
                if(dest_y   > src_y)    y_offset= dest_y-src_y;
940
                else                    y_offset= (NY-src_y)+dest_y;
941
            end
942
            else if(tranc_y_min)  begin
943
                if(dest_y   <  src_y)    y_offset= src_y-dest_y;
944
                else                     y_offset= src_y+(NY-dest_y);
945
 
946
            end
947
 
948
 
949
        end
950
        /* verilator lint_on WIDTH */
951
 
952
 
953
        tranc_dir #(
954
            .NX(NX),
955
            .NY(NY)
956
        )
957
        tranc_dir
958
        (
959
            .tranc_x_plus(tranc_x_plus),
960
            .tranc_x_min(tranc_x_min),
961
            .tranc_y_plus(tranc_y_plus),
962
            .tranc_y_min(tranc_y_min),
963
            .same_x(same_x),
964
            .same_y(same_y),
965
            .current_x(src_x),
966
            .current_y(src_y),
967
            .dest_x(dest_x),
968
            .dest_y(dest_y)
969
        );
970
 
971
 
972
    end
973
    endgenerate
974
    /* verilator lint_off WIDTH */
975
    assign distance     =   x_offset+y_offset+1'b1;
976
    /* verilator lint_on WIDTH */
977
endmodule
978
 
979
 
980
module mesh_torus_ssa_check_destport #(
981
    parameter ROUTE_TYPE="DETERMINISTIC",
982
    parameter SW_LOC = 0,
983
    parameter P=5,
984
    parameter DEBUG_EN = 0,
985
    parameter DSTPw = P-1,
986
    parameter SS_PORT=0
987
)(
988
    destport_encoded, //exsited packet dest port
989
    destport_in_encoded, // incomming packet dest port
990
    ss_port_hdr_flit,
991
    ss_port_nonhdr_flit
992
//synthesis translate_off
993
//synopsys  translate_off
994
    ,clk,
995
    ivc_num_getting_sw_grant,
996
    hdr_flg
997
//synopsys  translate_on
998
//synthesis translate_on
999
 
1000
);
1001
 
1002
    input [DSTPw-1 : 0] destport_encoded, destport_in_encoded;
1003
    output ss_port_hdr_flit, ss_port_nonhdr_flit;
1004
//synthesis translate_off
1005
//synopsys  translate_off
1006
    input clk,   ivc_num_getting_sw_grant,hdr_flg;
1007
//synopsys  translate_on
1008
//synthesis translate_on
1009
 
1010
//MESH, TORUS Topology p=5
1011
    localparam   LOCAL   =   0,
1012
                 EAST    =   1,
1013
                 WEST    =   3;
1014
 
1015
 
1016
/************************
1017
        destination port is coded
1018
        destination-port_in
1019
            x:  1 EAST, 0 WEST
1020
            y:  1 NORTH, 0 SOUTH
1021
            ab: 00 : LOCAL, 10: xdir, 01: ydir, 11 x&y dir
1022
        sel:
1023
             0: xdir
1024
             1: ydir
1025
        port_pre_sel
1026
             0: xdir
1027
             1: ydir
1028
 
1029
************************/
1030
wire  a,b,aa,bb;
1031
assign {a,b} = destport_in_encoded[1:0];
1032
assign {aa,bb} = destport_encoded[1:0];
1033
 
1034
generate
1035
    if( SS_PORT == LOCAL) begin :local_p
1036
         assign ss_port_hdr_flit = 1'b0;
1037
         assign ss_port_nonhdr_flit =   1'b0;
1038
    end else if ((SS_PORT == EAST) || SS_PORT == WEST )begin :xdir
1039
         assign ss_port_hdr_flit = a;
1040
         assign ss_port_nonhdr_flit =   aa;
1041
    end else begin :ydir
1042
        assign ss_port_hdr_flit = b;
1043
        assign ss_port_nonhdr_flit =   bb;
1044
    end
1045
 
1046
//synthesis translate_off
1047
//synopsys  translate_off
1048
 
1049
if(DEBUG_EN) begin :dbg
1050
    always @(posedge clk) begin
1051
       //if(!reset)begin
1052
            if(ivc_num_getting_sw_grant & aa & bb & ~hdr_flg) begin
1053
                $display("%t: SSA ERROR: There are two output ports that a non-header flit can be sent to. %m",$time);
1054
                $finish;
1055
            end
1056
       //end
1057
    end
1058
end //dbg
1059
 
1060
//synopsys  translate_on
1061
//synthesis translate_on
1062
 
1063
 
1064
endgenerate
1065
endmodule
1066
 
1067
 
1068
module line_ring_ssa_check_destport #(
1069
    parameter ROUTE_TYPE="DETERMINISTIC",
1070
    parameter SW_LOC = 0,
1071
    parameter P=3,
1072
    parameter DEBUG_EN = 0,
1073
    parameter DSTPw = P-1,
1074
    parameter SS_PORT=0
1075
)(
1076
    destport_encoded, //exsited packet dest port
1077
    destport_in_encoded, // incomming packet dest port
1078
    ss_port_hdr_flit,
1079
    ss_port_nonhdr_flit
1080
 
1081
);
1082
 
1083
    input [DSTPw-1 : 0] destport_encoded, destport_in_encoded;
1084
    output ss_port_hdr_flit, ss_port_nonhdr_flit;
1085
 
1086
 
1087
 
1088
wire [P-1   :   0] dest_port_num,assigned_dest_port_num;
1089
 
1090
 
1091
 
1092
  line_ring_decode_dstport cnv1(
1093
        .dstport_one_hot(dest_port_num),
1094
        .dstport_encoded(destport_in_encoded)
1095
  );
1096
 
1097
   line_ring_decode_dstport cnv2(
1098
        .dstport_one_hot(assigned_dest_port_num),
1099
        .dstport_encoded(destport_encoded)
1100
   );
1101
 
1102
     assign ss_port_hdr_flit = dest_port_num [SS_PORT];
1103
 
1104
    assign ss_port_nonhdr_flit =  assigned_dest_port_num[SS_PORT];
1105
 
1106
endmodule
1107
 
1108
 
1109
/*
1110
module mesh_torus_add_ss_port #(
1111
    parameter SW_LOC=1,
1112
    parameter P=5,
1113
    parameter SELF_LOOP_EN="NO"
1114
)(
1115
    destport_in,
1116
    destport_out
1117
);
1118
     localparam
1119
        P_1     = (SELF_LOOP_EN == "NO") ? P-1 : P,
1120
        LOCAL   =   0,
1121
        EAST    =   1,
1122
        NORTH   =   2,
1123
        WEST    =   3,
1124
        SOUTH   =   4;
1125
 
1126
 
1127
     localparam  NO_SELF_LOOP  = (SELF_LOOP_EN == "NO") ? 1 : 0;
1128
     localparam  SS_PORT_P5 = (SW_LOC== EAST   )? WEST- NO_SELF_LOOP : // the sender port must be removed from destination port code
1129
                              (SW_LOC== NORTH  )? SOUTH- NO_SELF_LOOP: // the sender port must be removed from destination port code
1130
                              (SW_LOC== WEST   )? EAST  :
1131
                                                  NORTH ;
1132
 
1133
     localparam  SS_PORT_P3 =  (SELF_LOOP_EN == "NO") ? 1 :
1134
 
1135
 
1136
     localparam  SS_PORT      =   (P==5) ? SS_PORT_P5: SS_PORT_P3;
1137
 
1138
 
1139
 
1140
 
1141
    input       [P_1-1  :   0] destport_in;
1142
    output reg  [P_1-1  :   0] destport_out;
1143
 
1144
 
1145
 
1146
    always @(*)begin
1147
        destport_out=destport_in;
1148
        if( SW_LOC != LOCAL ) begin
1149
            if(destport_in=={P_1{1'b0}}) destport_out[SS_PORT]= 1'b1;
1150
        end
1151
    end
1152
 
1153
 
1154
endmodule
1155
*/
1156
 
1157
/**************
1158
 *
1159
 * ************/
1160
 
1161
  module mesh_tori_router_addr_decode #(
1162
    parameter TOPOLOGY = "MESH",
1163
    parameter T1=4,
1164
    parameter T2=4,
1165
    parameter T3=4,
1166
    parameter RAw=6
1167
)(
1168
    r_addr,
1169
    rx,
1170
    ry,
1171
    valid
1172
);
1173
 
1174
    function integer log2;
1175
      input integer number; begin
1176
         log2=(number <=1) ? 1: 0;
1177
         while(2**log2
1178
            log2=log2+1;
1179
         end
1180
      end
1181
    endfunction // log2
1182
 
1183
    localparam
1184
        NX = T1,
1185
        NY = T2,
1186
        RXw = log2(NX),    // number of node in x axis
1187 56 alirezamon
        RYw = (TOPOLOGY=="RING" || TOPOLOGY == "LINE") ? 1 : log2(NY);    // number of node in y axis
1188 54 alirezamon
 
1189
    /* verilator lint_off WIDTH */
1190
    localparam [RXw-1 : 0]    MAXX = (NX-1);
1191
    localparam [RYw-1 : 0]    MAXY = (NY-1);
1192
    /* verilator lint_on WIDTH */
1193
 
1194
 
1195
    input  [RAw-1 : 0] r_addr;
1196
    output [RXw-1 : 0] rx;
1197
    output [RYw-1 : 0] ry;
1198
    output valid;
1199
 
1200
    generate
1201
    if ((TOPOLOGY == "RING") || (TOPOLOGY == "LINE")) begin :oneD
1202
         assign rx = r_addr;
1203
         assign ry = 1'b0;
1204
    end else begin : twoD
1205
        assign {ry,rx} = r_addr;
1206
    end
1207
    endgenerate
1208
 
1209
    /* verilator lint_off CMPCONST */
1210
    assign valid = (rx<= MAXX ) & (ry <= MAXY);
1211
    /* verilator lint_on CMPCONST */
1212
endmodule
1213
 
1214
 
1215
 
1216
module mesh_tori_endp_addr_decode #(
1217
    parameter TOPOLOGY = "MESH",
1218
    parameter T1=4,
1219
    parameter T2=4,
1220
    parameter T3=4,
1221
    parameter EAw=9
1222
)(
1223
    e_addr,
1224
    ex,
1225
    ey,
1226
    el,
1227
    valid
1228
);
1229
 
1230
    function integer log2;
1231
      input integer number; begin
1232
         log2=(number <=1) ? 1: 0;
1233
         while(2**log2
1234
            log2=log2+1;
1235
         end
1236
      end
1237
    endfunction // log2
1238
 
1239
    localparam
1240
        NX = T1,
1241
        NY = T2,
1242
        NL = T3,
1243
        EXw = log2(NX),    // number of node in x axis
1244 56 alirezamon
        EYw = (TOPOLOGY=="RING" || TOPOLOGY == "LINE")? 1 : log2(NY),
1245 54 alirezamon
        ELw = log2(NL);    // number of node in y axis
1246
 
1247
    /* verilator lint_off WIDTH */
1248
    localparam [EXw-1 : 0]    MAXX = (NX-1);
1249
    localparam [EYw-1 : 0]    MAXY = (NY-1);
1250
    localparam [ELw-1 : 0]    MAXL = (NL-1);
1251
    /* verilator lint_on WIDTH */
1252
 
1253
 
1254
    input  [EAw-1 : 0] e_addr;
1255
    output [EXw-1 : 0] ex;
1256
    output [EYw-1 : 0] ey;
1257
    output [ELw-1 : 0] el;
1258
    output valid;
1259
 
1260
    generate
1261
    if ((TOPOLOGY == "RING") || (TOPOLOGY == "LINE")) begin :oneD
1262
        if(NL==1)begin:one_local
1263
             assign ex = e_addr;
1264
             assign ey = 1'b0;
1265
             assign el = 1'b0;
1266
             /* verilator lint_off CMPCONST */
1267
             assign valid = ex<= MAXX;
1268
             /* verilator lint_on CMPCONST */
1269
        end else begin: multi_local
1270
             assign {el,ex} = e_addr;
1271
             assign ey = 1'b0;
1272
             /* verilator lint_off CMPCONST */
1273
             assign valid = ((ex<= MAXX) & (el<=MAXL));
1274
             /* verilator lint_on CMPCONST */
1275
        end
1276
    end else begin : twoD
1277
        if(NL==1)begin:one_local
1278
            assign {ey,ex} = e_addr;
1279
            assign el = 1'b0;
1280
            /* verilator lint_off CMPCONST */
1281
            assign valid = (ex<= MAXX) & (ey <= MAXY);
1282
            /* verilator lint_on CMPCONST */
1283
        end else begin :multi_l
1284
            assign {el,ey,ex} = e_addr;
1285
            /* verilator lint_off CMPCONST */
1286
            assign valid = ( (ex<= MAXX) & (ey <= MAXY) & (el<=MAXL) );
1287
            /* verilator lint_on CMPCONST */
1288
        end
1289
    end
1290
    endgenerate
1291
 
1292
endmodule
1293
 
1294
 
1295
/**************
1296
    mesh_tori_addr_encoder
1297
    most probably it is only needed for simulation purposes
1298
***************/
1299
 
1300
module  mesh_tori_addr_encoder #(
1301
    parameter   NX=2,
1302
    parameter   NY=2,
1303
    parameter   NL=2,
1304
    parameter   NE=16,
1305
    parameter   EAw=4,
1306
    parameter   TOPOLOGY="MESH"
1307
)(
1308
    id,
1309
    code
1310
);
1311
 
1312
    function integer log2;
1313
      input integer number; begin
1314
         log2=(number <=1) ? 1: 0;
1315
         while(2**log2
1316
            log2=log2+1;
1317
         end
1318
      end
1319
    endfunction // log2
1320
 
1321
 
1322
 
1323
    function integer addrencode;
1324
        input integer in,nx,nxw,nl,nyw;
1325
        integer  y, x, l;begin
1326
            addrencode=0;
1327
            y = ((in/nl) / nx );
1328
            x = ((in/nl) % nx );
1329
            l = (in % nl);
1330
            addrencode =(nl==1)?   (y<
1331
        end
1332
    endfunction // addrencode
1333
 
1334
 
1335
    localparam
1336
        NXw= log2(NX),
1337 56 alirezamon
        NYw= (TOPOLOGY=="RING" || TOPOLOGY=="LINE")? 0 : log2(NY),
1338 54 alirezamon
        NEw = log2(NE);
1339
 
1340
 
1341
     input [NEw-1 :0] id;
1342
     output [EAw-1 : 0] code;
1343
 
1344
    wire [EAw-1 : 0 ] codes [NE-1 : 0];
1345
    genvar i;
1346
    generate
1347
    for(i=0; i< NE; i=i+1) begin : endpoints
1348
        //Endpoint decoded address
1349
       /* verilator lint_off WIDTH */
1350
        localparam [EAw-1 : 0] ENDP= addrencode(i,NX,NXw,NL,NYw);
1351
       /* verilator lint_on WIDTH */
1352
        assign codes[i] = ENDP;
1353
    end
1354
    endgenerate
1355
 
1356
    assign code = codes[id];
1357
endmodule
1358
 
1359
 
1360
module  mesh_tori_addr_coder #(
1361 56 alirezamon
    parameter   TOPOLOGY = "MESH",
1362 54 alirezamon
    parameter   NX=2,
1363
    parameter   NY=2,
1364
    parameter   NL=2,
1365
    parameter   NE=16,
1366
    parameter   EAw=4
1367
)(
1368
    id,
1369
    code
1370
);
1371
 
1372
    function integer log2;
1373
      input integer number; begin
1374
         log2=(number <=1) ? 1: 0;
1375
         while(2**log2
1376
            log2=log2+1;
1377
         end
1378
      end
1379
    endfunction // log2
1380
 
1381
 
1382
 
1383
    function integer addrencode;
1384
        input integer in,nx,nxw,nl,nyw;
1385
        integer  y, x, l;begin
1386
            addrencode=0;
1387
            y = ((in/nl) / nx );
1388
            x = ((in/nl) % nx );
1389
            l = (in % nl);
1390
            addrencode =(nl==1)?   (y<
1391
        end
1392
    endfunction // addrencode
1393
 
1394
 
1395
    localparam
1396
        NXw= log2(NX),
1397 56 alirezamon
        NYw= (TOPOLOGY=="RING" || TOPOLOGY=="LINE")? 0 : log2(NY),
1398 54 alirezamon
        NEw = log2(NE);
1399
 
1400
 
1401
     output [NEw-1 :0] id;
1402
     input [EAw-1 : 0] code;
1403
 
1404
    wire   [NEw-1 : 0]  codes   [(2**EAw)-1 : 0 ];
1405
    genvar i;
1406
    generate
1407
    for(i=0; i< NE; i=i+1) begin : endpoints
1408
        //Endpoint decoded address
1409
       /* verilator lint_off WIDTH */
1410
        localparam [EAw-1 : 0] ENDP= addrencode(i,NX,NXw,NL,NYw);
1411
       /* verilator lint_on WIDTH */
1412
        assign codes[ENDP] = i;
1413
    end
1414
    endgenerate
1415
 
1416
    assign id = codes[code];
1417
endmodule
1418
 
1419
 
1420
 
1421
module mesh_torus_destp_generator #(
1422
    parameter TOPOLOGY = "MESH",
1423
    parameter ROUTE_NAME = "XY",
1424
    parameter ROUTE_TYPE = "DETERMINISTIC",
1425
    parameter P=5,
1426
    parameter DSTPw=4,
1427
    parameter NL=1,
1428
    parameter PLw=1,
1429
    parameter PPSw=4,
1430
    parameter SW_LOC=0,
1431
    parameter SELF_LOOP_EN="NO"
1432
)(
1433
    dest_port_out,
1434
    dest_port_coded,
1435
    endp_localp_num,
1436
    swap_port_presel,
1437
    port_pre_sel,
1438
    odd_column
1439
);
1440
    localparam P_1 =  ( SELF_LOOP_EN=="NO")?  P-1 : P;
1441
 
1442
    input  [DSTPw-1 : 0] dest_port_coded;
1443
    input  [PLw-1 : 0] endp_localp_num;
1444
    output [P_1-1 : 0] dest_port_out;
1445
    input           swap_port_presel;
1446
    input  [PPSw-1 : 0] port_pre_sel;
1447
    input odd_column;
1448
 
1449
 
1450
    wire [P_1-1 : 0] dest_port_in;
1451
 
1452
 
1453
        generate
1454
        /* verilator lint_off WIDTH */
1455
        if (TOPOLOGY == "RING" || TOPOLOGY == "LINE" ) begin : one_D
1456
        /* verilator lint_on WIDTH */
1457
 
1458
            line_ring_destp_decoder #(
1459
                .ROUTE_TYPE(ROUTE_TYPE),
1460
                .P(P),
1461
                .DSTPw(DSTPw),
1462
                .NL(NL),
1463
                .ELw(PLw),
1464
                .PPSw(PPSw),
1465
                .SW_LOC(SW_LOC),
1466
                .SELF_LOOP_EN(SELF_LOOP_EN)
1467
            )
1468
            decoder
1469
            (
1470
                .dest_port_coded(dest_port_coded),
1471
                .dest_port_out(dest_port_in),
1472
                .endp_localp_num(endp_localp_num)
1473
            );
1474
 
1475
 
1476
       end else begin :two_D
1477
 
1478
            mesh_torus_destp_decoder #(
1479
                .ROUTE_TYPE(ROUTE_TYPE),
1480
                .P(P),
1481
                .DSTPw(DSTPw),
1482
                .NL(NL),
1483
                .ELw(PLw),
1484
                .PPSw(PPSw),
1485
                .SW_LOC(SW_LOC),
1486
                .SELF_LOOP_EN(SELF_LOOP_EN)
1487
            )
1488
            decoder
1489
            (
1490
                .dest_port_coded(dest_port_coded),
1491
                .dest_port_out(dest_port_in),
1492
                .endp_localp_num(endp_localp_num),
1493
                .swap_port_presel(swap_port_presel),
1494
                .port_pre_sel(port_pre_sel)
1495
            );
1496
      end
1497
 endgenerate
1498
 
1499
      mesh_torus_mask_non_assignable_destport #(
1500
                .TOPOLOGY(TOPOLOGY),
1501
                .ROUTE_NAME(ROUTE_NAME),
1502
                .SW_LOC(SW_LOC),
1503
                .P(P),
1504
                .SELF_LOOP_EN(SELF_LOOP_EN)
1505
            )
1506
            mask_destport
1507
            (
1508
                .dest_port_in(dest_port_in),
1509
                .dest_port_out(dest_port_out),
1510
                .odd_column(odd_column)
1511
            );
1512
 
1513
endmodule
1514
 
1515
module mesh_torus_destp_decoder #(
1516
    parameter ROUTE_TYPE="DETERMINISTIC",
1517
    parameter P=6,
1518
    parameter DSTPw=4,
1519
    parameter NL=2,
1520
    parameter ELw=1,
1521
    parameter PPSw=4,
1522
    parameter SW_LOC=0,
1523
    parameter SELF_LOOP_EN="NO"
1524
)(
1525
    dest_port_coded,
1526
    endp_localp_num,
1527
    dest_port_out,
1528
    swap_port_presel,
1529
    port_pre_sel
1530
 );
1531
 
1532
    localparam P_1 = ( SELF_LOOP_EN=="NO")?  P-1 : P;
1533
 
1534
    input  [DSTPw-1 : 0] dest_port_coded;
1535
    input  [ELw-1 : 0] endp_localp_num;
1536
    output [P_1-1 : 0] dest_port_out;
1537
    input           swap_port_presel;
1538
    input  [PPSw-1 : 0] port_pre_sel;
1539
 
1540
    wire [NL-1 : 0] endp_localp_onehot;
1541
 
1542
    reg [4:0] portout;
1543
 
1544
    generate
1545
    if( ROUTE_TYPE == "DETERMINISTIC") begin :dtrmn
1546
 
1547
 
1548
        wire x,y,a,b;
1549
        assign {x,y,a,b} = dest_port_coded;
1550
 
1551
        always @(*)begin
1552
            case({a,b})
1553
                2'b10 : portout = {1'b0,~x,1'b0,x,1'b0};
1554
                2'b01 : portout = {~y,1'b0,y,1'b0,1'b0};
1555
                2'b00 : portout =  5'b00001;
1556
                2'b11 : portout = {~y,1'b0,y,1'b0,1'b0}; //invalid condition in determinstic routing
1557
            endcase
1558
        end //always
1559
 
1560
    end else begin : adpv
1561
 
1562
        wire x,y,a,b;
1563
        assign {x,y,a,b} = dest_port_coded;
1564
        wire [PPSw-1:0] port_pre_sel_final;
1565
        assign port_pre_sel_final= (swap_port_presel)? ~port_pre_sel: port_pre_sel;
1566
 
1567
        always @(*)begin
1568
            case({a,b})
1569
                2'b10 : portout = {1'b0,~x,1'b0,x,1'b0};
1570
                2'b01 : portout = {~y,1'b0,y,1'b0,1'b0};
1571
                2'b11 : portout = (port_pre_sel_final[{x,y}])?  {~y,1'b0,y,1'b0,1'b0} : {1'b0,~x,1'b0,x,1'b0};
1572
                2'b00 : portout =  5'b00001;
1573
            endcase
1574
        end //always
1575
     end
1576
 
1577
 
1578
     if(NL==1) begin :slp
1579
        if(SELF_LOOP_EN == "NO") begin :nslp
1580
            remove_sw_loc_one_hot #(
1581
                .P(5),
1582
                .SW_LOC(SW_LOC)
1583
            )
1584
            conv
1585
            (
1586
                .destport_in(portout),
1587
                .destport_out(dest_port_out)
1588
            );
1589
         end else begin : slp
1590
            assign dest_port_out = portout;
1591
         end
1592
     end else begin :mlp
1593
 
1594
            wire [P-1 : 0] destport_onehot;
1595
 
1596
            bin_to_one_hot #(
1597
                .BIN_WIDTH(ELw),
1598
                .ONE_HOT_WIDTH(NL)
1599
            )
1600
            conv
1601
            (
1602
                .bin_code(endp_localp_num),
1603
                .one_hot_code(endp_localp_onehot)
1604
            );
1605
 
1606
           assign destport_onehot =(portout[0])?  { endp_localp_onehot[NL-1 : 1] ,{(P-NL){1'b0}},endp_localp_onehot[0]}: /*select local destination*/
1607
                                                              { {(NL-1){1'b0}} ,portout};
1608
           if(SELF_LOOP_EN == "NO") begin :nslp
1609
                remove_sw_loc_one_hot #(
1610
                    .P(P),
1611
                    .SW_LOC(SW_LOC)
1612
                )
1613
                remove_sw_loc
1614
                (
1615
                    .destport_in(destport_onehot),
1616
                    .destport_out(dest_port_out)
1617
                );
1618
            end else begin: slp
1619
                assign dest_port_out = destport_onehot;
1620
            end
1621
    end
1622
    endgenerate
1623
endmodule
1624
 
1625
 
1626
/**************************
1627
 * line_ring_destp_decoder
1628
 * ************************/
1629
 
1630
module line_ring_destp_decoder #(
1631
    parameter ROUTE_TYPE="DETERMINISTIC",
1632
    parameter P=4,
1633
    parameter DSTPw=2,
1634
    parameter NL=2,
1635
    parameter ELw=1,
1636
    parameter PPSw=4,
1637
    parameter SW_LOC=0,
1638
    parameter SELF_LOOP_EN= "NO"
1639
)(
1640
    dest_port_coded,
1641
    endp_localp_num,
1642
    dest_port_out
1643
 );
1644
 
1645
    localparam P_1 = (SELF_LOOP_EN == "NO")?  P-1 : P;
1646
 
1647
    input  [DSTPw-1 : 0] dest_port_coded;
1648
    input  [ELw-1 : 0] endp_localp_num;
1649
    output [P_1-1 : 0] dest_port_out;
1650
 
1651
 
1652
    wire [NL-1 : 0] endp_localp_onehot;
1653
 
1654
    wire [2:0] portout;
1655
 
1656
 
1657
      line_ring_decode_dstport decoder(
1658
        .dstport_one_hot(portout),
1659
        .dstport_encoded(dest_port_coded)
1660
      );
1661
 
1662
 
1663
 
1664
 
1665
     generate
1666
     if(NL==1) begin :slp
1667
        if(SELF_LOOP_EN == "NO") begin :nslp
1668
            remove_sw_loc_one_hot #(
1669
                .P(3),
1670
                .SW_LOC(SW_LOC)
1671
            )
1672
            conv
1673
            (
1674
                .destport_in(portout),
1675
                .destport_out(dest_port_out)
1676
            );
1677
         end else begin : slp
1678
            assign dest_port_out = portout;
1679
         end
1680
     end else begin :mlp
1681
 
1682
            wire [P-1 : 0] destport_onehot;
1683
 
1684
            bin_to_one_hot #(
1685
                .BIN_WIDTH(ELw),
1686
                .ONE_HOT_WIDTH(NL)
1687
            )
1688
            conv
1689
            (
1690
                .bin_code(endp_localp_num),
1691
                .one_hot_code(endp_localp_onehot)
1692
            );
1693
 
1694
           assign destport_onehot =(portout[0])?  { endp_localp_onehot[NL-1 : 1] ,{(P-NL){1'b0}},endp_localp_onehot[0]}: /*select local destination*/
1695
                                                  { {(NL-1){1'b0}} ,portout};
1696
            if(SELF_LOOP_EN == "NO") begin :nslp
1697
                remove_sw_loc_one_hot #(
1698
                    .P(P),
1699
                    .SW_LOC(SW_LOC)
1700
                )
1701
                remove_sw_loc
1702
                (
1703
                    .destport_in(destport_onehot),
1704
                    .destport_out(dest_port_out)
1705
                );
1706
            end else begin :slp
1707
                assign dest_port_out = destport_onehot;
1708
            end
1709
    end
1710
    endgenerate
1711
endmodule
1712
 
1713
 
1714
 
1715
 
1716
/*****************
1717
*   mesh_torus_dynamic_portsel_control
1718
*****************/
1719
 
1720
 
1721
module  mesh_torus_dynamic_portsel_control #(
1722
    parameter  P = 5,
1723
    parameter ROUTE_TYPE =  "FULL_ADAPTIVE",    // "FULL_ADAPTIVE", "PAR_ADAPTIVE"
1724
    parameter V = 4,
1725
    parameter DSTPw=4,
1726
    parameter SSA_EN ="NO",
1727
    parameter PPSw=4,
1728
    parameter [V-1  :   0] ESCAP_VC_MASK = 4'b1000   // mask scape vc, valid only for full adaptive
1729
)(
1730
    dest_port_coded_all,
1731
    ivc_request_all,
1732
    ovc_is_assigned_all,
1733
    port_pre_sel,
1734
    swap_port_presel,
1735
    destport_clear_all,
1736
    ivc_num_getting_ovc_grant,
1737
    ssa_ivc_num_getting_ovc_grant_all,
1738
    masked_ovc_request_all,
1739
    sel,
1740
    reset,
1741
    clk
1742
);
1743
 
1744
 
1745
    localparam
1746
        PV = V * P,
1747
        PVV= PV * V,
1748
        PVDSTPw = PV * DSTPw;
1749
 
1750
     localparam LOCAL   =   0,
1751
                EAST    =   1,
1752
                NORTH   =   2,
1753
                WEST    =   3,
1754
                SOUTH   =   4;
1755
 
1756
 
1757
    input   [PVDSTPw-1  :   0]  dest_port_coded_all;
1758
    input   [PV-1       :   0]  ivc_request_all;
1759
    input   [PV-1       :   0]  ovc_is_assigned_all;
1760
    input   [PVV-1      :   0]  masked_ovc_request_all;
1761
 
1762
 
1763
    input   [PPSw-1      :   0]  port_pre_sel;
1764
    output  [PV-1       :   0]  swap_port_presel;
1765
    output  [PV-1       :   0]  sel;
1766
    output  [PVDSTPw-1 : 0] destport_clear_all;
1767
    input   [PV-1 : 0] ivc_num_getting_ovc_grant;
1768
    input   [PV-1 : 0] ssa_ivc_num_getting_ovc_grant_all;
1769
    input                       reset,clk;
1770
 
1771
 
1772
    wire    [PV-1       :   0]  non_assigned_ovc_request_all;
1773
    wire    [PV-1       :   0]  y_evc_forbiden,x_evc_forbiden;
1774
    wire    [PPSw-1      :   0]  port_pre_sel_perport            [P-1    :   0];
1775
 
1776
 
1777
 
1778
    assign non_assigned_ovc_request_all =   ivc_request_all & ~ovc_is_assigned_all;
1779
 
1780
 
1781
    assign port_pre_sel_perport[LOCAL]   = port_pre_sel;
1782
    assign port_pre_sel_perport[EAST]    = {2'b00,port_pre_sel[1:0]};
1783
    assign port_pre_sel_perport[NORTH]   = {1'b0,port_pre_sel[2],1'b0,port_pre_sel[0]};
1784
    assign port_pre_sel_perport[WEST]    = {port_pre_sel[3:2],2'b0};
1785
    assign port_pre_sel_perport[SOUTH]   = {port_pre_sel[3],1'b0,port_pre_sel[1],1'b0};
1786
 
1787
 
1788
    wire    [PV-1   :   0]  avc_unavailable;
1789
    genvar i;
1790
    generate
1791
 
1792
 
1793
    for(i=0;i< PV;i=i+1) begin :all_vc_loop
1794
        localparam SW_LOC = ((i/V)<5)? i/V : LOCAL;
1795
 
1796
 
1797
        mesh_torus_port_selector #(
1798
           .SW_LOC     (SW_LOC),
1799
           .PPSw(PPSw)
1800
        )
1801
        the_portsel
1802
        (
1803
           .port_pre_sel       (port_pre_sel_perport[SW_LOC]),
1804
           .swap_port_presel   (swap_port_presel[i]),
1805
           .sel                (sel[i]),
1806
           .dest_port_in       (dest_port_coded_all[((i+1)*DSTPw)-1 : i*DSTPw]),
1807
           .y_evc_forbiden     (y_evc_forbiden[i]),
1808
           .x_evc_forbiden     (x_evc_forbiden[i])
1809
          );
1810
 
1811
        mesh_tori_dspt_clear_gen #(
1812
            .SSA_EN(SSA_EN),
1813
            .DSTPw(DSTPw),
1814
            .SW_LOC(SW_LOC)
1815
        )
1816
        dspt_clear_gen
1817
        (
1818
            .destport_clear(destport_clear_all[((i+1)*DSTPw)-1 : i*DSTPw]),
1819
            .ivc_num_getting_ovc_grant(ivc_num_getting_ovc_grant[i]),
1820
            .sel(sel[i]),
1821
            .ssa_ivc_num_getting_ovc_grant(ssa_ivc_num_getting_ovc_grant_all[i])
1822
        );
1823
 
1824
 
1825
        /* verilator lint_off WIDTH */
1826
        if(ROUTE_TYPE ==  "FULL_ADAPTIVE") begin: full_adpt
1827
        /* verilator lint_on WIDTH */
1828
        assign avc_unavailable[i] = (masked_ovc_request_all [((i+1)*V)-1 : i*V] & ~ESCAP_VC_MASK) == {V{1'b0}};
1829
 
1830
            mesh_torus_swap_port_presel_gen #(
1831
                .V(V),
1832
                .ESCAP_VC_MASK(ESCAP_VC_MASK),
1833
                .VC_NUM(i)
1834
            )
1835
            the_swap_port_presel
1836
            (
1837
                .avc_unavailable(avc_unavailable[i]),
1838
                .y_evc_forbiden(y_evc_forbiden[i]),
1839
                .x_evc_forbiden(x_evc_forbiden[i]),
1840
                .non_assigned_ovc_request(non_assigned_ovc_request_all[i]),
1841
                .sel(sel[i]),
1842
                .clk(clk),
1843
                .reset(reset),
1844
                .swap_port_presel(swap_port_presel[i])
1845
            );
1846
 
1847
 
1848
        end else begin : partial_adpt
1849
 
1850
            assign swap_port_presel[i]=1'b0;
1851
            assign avc_unavailable[i]=1'b0;
1852
 
1853
        end// ROUTE_TYPE
1854
    end//for
1855
 
1856
endgenerate
1857
endmodule
1858
 
1859
 
1860
 
1861
 
1862
 
1863
 

powered by: WebSVN 2.1.0

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