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 54

Go to most recent revision | 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
        RYw = log2(NY);    // number of node in y axis
1188
 
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
        EYw = log2(NY),
1245
        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
        NYw= log2(NY),
1338
        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
    parameter   NX=2,
1362
    parameter   NY=2,
1363
    parameter   NL=2,
1364
    parameter   NE=16,
1365
    parameter   EAw=4
1366
)(
1367
    id,
1368
    code
1369
);
1370
 
1371
    function integer log2;
1372
      input integer number; begin
1373
         log2=(number <=1) ? 1: 0;
1374
         while(2**log2
1375
            log2=log2+1;
1376
         end
1377
      end
1378
    endfunction // log2
1379
 
1380
 
1381
 
1382
    function integer addrencode;
1383
        input integer in,nx,nxw,nl,nyw;
1384
        integer  y, x, l;begin
1385
            addrencode=0;
1386
            y = ((in/nl) / nx );
1387
            x = ((in/nl) % nx );
1388
            l = (in % nl);
1389
            addrencode =(nl==1)?   (y<
1390
        end
1391
    endfunction // addrencode
1392
 
1393
 
1394
    localparam
1395
        NXw= log2(NX),
1396
        NYw= log2(NY),
1397
        NEw = log2(NE);
1398
 
1399
 
1400
     output [NEw-1 :0] id;
1401
     input [EAw-1 : 0] code;
1402
 
1403
    wire   [NEw-1 : 0]  codes   [(2**EAw)-1 : 0 ];
1404
    genvar i;
1405
    generate
1406
    for(i=0; i< NE; i=i+1) begin : endpoints
1407
        //Endpoint decoded address
1408
       /* verilator lint_off WIDTH */
1409
        localparam [EAw-1 : 0] ENDP= addrencode(i,NX,NXw,NL,NYw);
1410
       /* verilator lint_on WIDTH */
1411
        assign codes[ENDP] = i;
1412
    end
1413
    endgenerate
1414
 
1415
    assign id = codes[code];
1416
endmodule
1417
 
1418
 
1419
 
1420
module mesh_torus_destp_generator #(
1421
    parameter TOPOLOGY = "MESH",
1422
    parameter ROUTE_NAME = "XY",
1423
    parameter ROUTE_TYPE = "DETERMINISTIC",
1424
    parameter P=5,
1425
    parameter DSTPw=4,
1426
    parameter NL=1,
1427
    parameter PLw=1,
1428
    parameter PPSw=4,
1429
    parameter SW_LOC=0,
1430
    parameter SELF_LOOP_EN="NO"
1431
)(
1432
    dest_port_out,
1433
    dest_port_coded,
1434
    endp_localp_num,
1435
    swap_port_presel,
1436
    port_pre_sel,
1437
    odd_column
1438
);
1439
    localparam P_1 =  ( SELF_LOOP_EN=="NO")?  P-1 : P;
1440
 
1441
    input  [DSTPw-1 : 0] dest_port_coded;
1442
    input  [PLw-1 : 0] endp_localp_num;
1443
    output [P_1-1 : 0] dest_port_out;
1444
    input           swap_port_presel;
1445
    input  [PPSw-1 : 0] port_pre_sel;
1446
    input odd_column;
1447
 
1448
 
1449
    wire [P_1-1 : 0] dest_port_in;
1450
 
1451
 
1452
        generate
1453
        /* verilator lint_off WIDTH */
1454
        if (TOPOLOGY == "RING" || TOPOLOGY == "LINE" ) begin : one_D
1455
        /* verilator lint_on WIDTH */
1456
 
1457
            line_ring_destp_decoder #(
1458
                .ROUTE_TYPE(ROUTE_TYPE),
1459
                .P(P),
1460
                .DSTPw(DSTPw),
1461
                .NL(NL),
1462
                .ELw(PLw),
1463
                .PPSw(PPSw),
1464
                .SW_LOC(SW_LOC),
1465
                .SELF_LOOP_EN(SELF_LOOP_EN)
1466
            )
1467
            decoder
1468
            (
1469
                .dest_port_coded(dest_port_coded),
1470
                .dest_port_out(dest_port_in),
1471
                .endp_localp_num(endp_localp_num)
1472
            );
1473
 
1474
 
1475
       end else begin :two_D
1476
 
1477
            mesh_torus_destp_decoder #(
1478
                .ROUTE_TYPE(ROUTE_TYPE),
1479
                .P(P),
1480
                .DSTPw(DSTPw),
1481
                .NL(NL),
1482
                .ELw(PLw),
1483
                .PPSw(PPSw),
1484
                .SW_LOC(SW_LOC),
1485
                .SELF_LOOP_EN(SELF_LOOP_EN)
1486
            )
1487
            decoder
1488
            (
1489
                .dest_port_coded(dest_port_coded),
1490
                .dest_port_out(dest_port_in),
1491
                .endp_localp_num(endp_localp_num),
1492
                .swap_port_presel(swap_port_presel),
1493
                .port_pre_sel(port_pre_sel)
1494
            );
1495
      end
1496
 endgenerate
1497
 
1498
      mesh_torus_mask_non_assignable_destport #(
1499
                .TOPOLOGY(TOPOLOGY),
1500
                .ROUTE_NAME(ROUTE_NAME),
1501
                .SW_LOC(SW_LOC),
1502
                .P(P),
1503
                .SELF_LOOP_EN(SELF_LOOP_EN)
1504
            )
1505
            mask_destport
1506
            (
1507
                .dest_port_in(dest_port_in),
1508
                .dest_port_out(dest_port_out),
1509
                .odd_column(odd_column)
1510
            );
1511
 
1512
endmodule
1513
 
1514
module mesh_torus_destp_decoder #(
1515
    parameter ROUTE_TYPE="DETERMINISTIC",
1516
    parameter P=6,
1517
    parameter DSTPw=4,
1518
    parameter NL=2,
1519
    parameter ELw=1,
1520
    parameter PPSw=4,
1521
    parameter SW_LOC=0,
1522
    parameter SELF_LOOP_EN="NO"
1523
)(
1524
    dest_port_coded,
1525
    endp_localp_num,
1526
    dest_port_out,
1527
    swap_port_presel,
1528
    port_pre_sel
1529
 );
1530
 
1531
    localparam P_1 = ( SELF_LOOP_EN=="NO")?  P-1 : P;
1532
 
1533
    input  [DSTPw-1 : 0] dest_port_coded;
1534
    input  [ELw-1 : 0] endp_localp_num;
1535
    output [P_1-1 : 0] dest_port_out;
1536
    input           swap_port_presel;
1537
    input  [PPSw-1 : 0] port_pre_sel;
1538
 
1539
    wire [NL-1 : 0] endp_localp_onehot;
1540
 
1541
    reg [4:0] portout;
1542
 
1543
    generate
1544
    if( ROUTE_TYPE == "DETERMINISTIC") begin :dtrmn
1545
 
1546
 
1547
        wire x,y,a,b;
1548
        assign {x,y,a,b} = dest_port_coded;
1549
 
1550
        always @(*)begin
1551
            case({a,b})
1552
                2'b10 : portout = {1'b0,~x,1'b0,x,1'b0};
1553
                2'b01 : portout = {~y,1'b0,y,1'b0,1'b0};
1554
                2'b00 : portout =  5'b00001;
1555
                2'b11 : portout = {~y,1'b0,y,1'b0,1'b0}; //invalid condition in determinstic routing
1556
            endcase
1557
        end //always
1558
 
1559
    end else begin : adpv
1560
 
1561
        wire x,y,a,b;
1562
        assign {x,y,a,b} = dest_port_coded;
1563
        wire [PPSw-1:0] port_pre_sel_final;
1564
        assign port_pre_sel_final= (swap_port_presel)? ~port_pre_sel: port_pre_sel;
1565
 
1566
        always @(*)begin
1567
            case({a,b})
1568
                2'b10 : portout = {1'b0,~x,1'b0,x,1'b0};
1569
                2'b01 : portout = {~y,1'b0,y,1'b0,1'b0};
1570
                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};
1571
                2'b00 : portout =  5'b00001;
1572
            endcase
1573
        end //always
1574
     end
1575
 
1576
 
1577
     if(NL==1) begin :slp
1578
        if(SELF_LOOP_EN == "NO") begin :nslp
1579
            remove_sw_loc_one_hot #(
1580
                .P(5),
1581
                .SW_LOC(SW_LOC)
1582
            )
1583
            conv
1584
            (
1585
                .destport_in(portout),
1586
                .destport_out(dest_port_out)
1587
            );
1588
         end else begin : slp
1589
            assign dest_port_out = portout;
1590
         end
1591
     end else begin :mlp
1592
 
1593
            wire [P-1 : 0] destport_onehot;
1594
 
1595
            bin_to_one_hot #(
1596
                .BIN_WIDTH(ELw),
1597
                .ONE_HOT_WIDTH(NL)
1598
            )
1599
            conv
1600
            (
1601
                .bin_code(endp_localp_num),
1602
                .one_hot_code(endp_localp_onehot)
1603
            );
1604
 
1605
           assign destport_onehot =(portout[0])?  { endp_localp_onehot[NL-1 : 1] ,{(P-NL){1'b0}},endp_localp_onehot[0]}: /*select local destination*/
1606
                                                              { {(NL-1){1'b0}} ,portout};
1607
           if(SELF_LOOP_EN == "NO") begin :nslp
1608
                remove_sw_loc_one_hot #(
1609
                    .P(P),
1610
                    .SW_LOC(SW_LOC)
1611
                )
1612
                remove_sw_loc
1613
                (
1614
                    .destport_in(destport_onehot),
1615
                    .destport_out(dest_port_out)
1616
                );
1617
            end else begin: slp
1618
                assign dest_port_out = destport_onehot;
1619
            end
1620
    end
1621
    endgenerate
1622
endmodule
1623
 
1624
 
1625
/**************************
1626
 * line_ring_destp_decoder
1627
 * ************************/
1628
 
1629
module line_ring_destp_decoder #(
1630
    parameter ROUTE_TYPE="DETERMINISTIC",
1631
    parameter P=4,
1632
    parameter DSTPw=2,
1633
    parameter NL=2,
1634
    parameter ELw=1,
1635
    parameter PPSw=4,
1636
    parameter SW_LOC=0,
1637
    parameter SELF_LOOP_EN= "NO"
1638
)(
1639
    dest_port_coded,
1640
    endp_localp_num,
1641
    dest_port_out
1642
 );
1643
 
1644
    localparam P_1 = (SELF_LOOP_EN == "NO")?  P-1 : P;
1645
 
1646
    input  [DSTPw-1 : 0] dest_port_coded;
1647
    input  [ELw-1 : 0] endp_localp_num;
1648
    output [P_1-1 : 0] dest_port_out;
1649
 
1650
 
1651
    wire [NL-1 : 0] endp_localp_onehot;
1652
 
1653
    wire [2:0] portout;
1654
 
1655
 
1656
      line_ring_decode_dstport decoder(
1657
        .dstport_one_hot(portout),
1658
        .dstport_encoded(dest_port_coded)
1659
      );
1660
 
1661
 
1662
 
1663
 
1664
     generate
1665
     if(NL==1) begin :slp
1666
        if(SELF_LOOP_EN == "NO") begin :nslp
1667
            remove_sw_loc_one_hot #(
1668
                .P(3),
1669
                .SW_LOC(SW_LOC)
1670
            )
1671
            conv
1672
            (
1673
                .destport_in(portout),
1674
                .destport_out(dest_port_out)
1675
            );
1676
         end else begin : slp
1677
            assign dest_port_out = portout;
1678
         end
1679
     end else begin :mlp
1680
 
1681
            wire [P-1 : 0] destport_onehot;
1682
 
1683
            bin_to_one_hot #(
1684
                .BIN_WIDTH(ELw),
1685
                .ONE_HOT_WIDTH(NL)
1686
            )
1687
            conv
1688
            (
1689
                .bin_code(endp_localp_num),
1690
                .one_hot_code(endp_localp_onehot)
1691
            );
1692
 
1693
           assign destport_onehot =(portout[0])?  { endp_localp_onehot[NL-1 : 1] ,{(P-NL){1'b0}},endp_localp_onehot[0]}: /*select local destination*/
1694
                                                  { {(NL-1){1'b0}} ,portout};
1695
            if(SELF_LOOP_EN == "NO") begin :nslp
1696
                remove_sw_loc_one_hot #(
1697
                    .P(P),
1698
                    .SW_LOC(SW_LOC)
1699
                )
1700
                remove_sw_loc
1701
                (
1702
                    .destport_in(destport_onehot),
1703
                    .destport_out(dest_port_out)
1704
                );
1705
            end else begin :slp
1706
                assign dest_port_out = destport_onehot;
1707
            end
1708
    end
1709
    endgenerate
1710
endmodule
1711
 
1712
 
1713
 
1714
 
1715
/*****************
1716
*   mesh_torus_dynamic_portsel_control
1717
*****************/
1718
 
1719
 
1720
module  mesh_torus_dynamic_portsel_control #(
1721
    parameter  P = 5,
1722
    parameter ROUTE_TYPE =  "FULL_ADAPTIVE",    // "FULL_ADAPTIVE", "PAR_ADAPTIVE"
1723
    parameter V = 4,
1724
    parameter DSTPw=4,
1725
    parameter SSA_EN ="NO",
1726
    parameter PPSw=4,
1727
    parameter [V-1  :   0] ESCAP_VC_MASK = 4'b1000   // mask scape vc, valid only for full adaptive
1728
)(
1729
    dest_port_coded_all,
1730
    ivc_request_all,
1731
    ovc_is_assigned_all,
1732
    port_pre_sel,
1733
    swap_port_presel,
1734
    destport_clear_all,
1735
    ivc_num_getting_ovc_grant,
1736
    ssa_ivc_num_getting_ovc_grant_all,
1737
    masked_ovc_request_all,
1738
    sel,
1739
    reset,
1740
    clk
1741
);
1742
 
1743
 
1744
    localparam
1745
        PV = V * P,
1746
        PVV= PV * V,
1747
        PVDSTPw = PV * DSTPw;
1748
 
1749
     localparam LOCAL   =   0,
1750
                EAST    =   1,
1751
                NORTH   =   2,
1752
                WEST    =   3,
1753
                SOUTH   =   4;
1754
 
1755
 
1756
    input   [PVDSTPw-1  :   0]  dest_port_coded_all;
1757
    input   [PV-1       :   0]  ivc_request_all;
1758
    input   [PV-1       :   0]  ovc_is_assigned_all;
1759
    input   [PVV-1      :   0]  masked_ovc_request_all;
1760
 
1761
 
1762
    input   [PPSw-1      :   0]  port_pre_sel;
1763
    output  [PV-1       :   0]  swap_port_presel;
1764
    output  [PV-1       :   0]  sel;
1765
    output  [PVDSTPw-1 : 0] destport_clear_all;
1766
    input   [PV-1 : 0] ivc_num_getting_ovc_grant;
1767
    input   [PV-1 : 0] ssa_ivc_num_getting_ovc_grant_all;
1768
    input                       reset,clk;
1769
 
1770
 
1771
    wire    [PV-1       :   0]  non_assigned_ovc_request_all;
1772
    wire    [PV-1       :   0]  y_evc_forbiden,x_evc_forbiden;
1773
    wire    [PPSw-1      :   0]  port_pre_sel_perport            [P-1    :   0];
1774
 
1775
 
1776
 
1777
    assign non_assigned_ovc_request_all =   ivc_request_all & ~ovc_is_assigned_all;
1778
 
1779
 
1780
    assign port_pre_sel_perport[LOCAL]   = port_pre_sel;
1781
    assign port_pre_sel_perport[EAST]    = {2'b00,port_pre_sel[1:0]};
1782
    assign port_pre_sel_perport[NORTH]   = {1'b0,port_pre_sel[2],1'b0,port_pre_sel[0]};
1783
    assign port_pre_sel_perport[WEST]    = {port_pre_sel[3:2],2'b0};
1784
    assign port_pre_sel_perport[SOUTH]   = {port_pre_sel[3],1'b0,port_pre_sel[1],1'b0};
1785
 
1786
 
1787
    wire    [PV-1   :   0]  avc_unavailable;
1788
    genvar i;
1789
    generate
1790
 
1791
 
1792
    for(i=0;i< PV;i=i+1) begin :all_vc_loop
1793
        localparam SW_LOC = ((i/V)<5)? i/V : LOCAL;
1794
 
1795
 
1796
        mesh_torus_port_selector #(
1797
           .SW_LOC     (SW_LOC),
1798
           .PPSw(PPSw)
1799
        )
1800
        the_portsel
1801
        (
1802
           .port_pre_sel       (port_pre_sel_perport[SW_LOC]),
1803
           .swap_port_presel   (swap_port_presel[i]),
1804
           .sel                (sel[i]),
1805
           .dest_port_in       (dest_port_coded_all[((i+1)*DSTPw)-1 : i*DSTPw]),
1806
           .y_evc_forbiden     (y_evc_forbiden[i]),
1807
           .x_evc_forbiden     (x_evc_forbiden[i])
1808
          );
1809
 
1810
        mesh_tori_dspt_clear_gen #(
1811
            .SSA_EN(SSA_EN),
1812
            .DSTPw(DSTPw),
1813
            .SW_LOC(SW_LOC)
1814
        )
1815
        dspt_clear_gen
1816
        (
1817
            .destport_clear(destport_clear_all[((i+1)*DSTPw)-1 : i*DSTPw]),
1818
            .ivc_num_getting_ovc_grant(ivc_num_getting_ovc_grant[i]),
1819
            .sel(sel[i]),
1820
            .ssa_ivc_num_getting_ovc_grant(ssa_ivc_num_getting_ovc_grant_all[i])
1821
        );
1822
 
1823
 
1824
        /* verilator lint_off WIDTH */
1825
        if(ROUTE_TYPE ==  "FULL_ADAPTIVE") begin: full_adpt
1826
        /* verilator lint_on WIDTH */
1827
        assign avc_unavailable[i] = (masked_ovc_request_all [((i+1)*V)-1 : i*V] & ~ESCAP_VC_MASK) == {V{1'b0}};
1828
 
1829
            mesh_torus_swap_port_presel_gen #(
1830
                .V(V),
1831
                .ESCAP_VC_MASK(ESCAP_VC_MASK),
1832
                .VC_NUM(i)
1833
            )
1834
            the_swap_port_presel
1835
            (
1836
                .avc_unavailable(avc_unavailable[i]),
1837
                .y_evc_forbiden(y_evc_forbiden[i]),
1838
                .x_evc_forbiden(x_evc_forbiden[i]),
1839
                .non_assigned_ovc_request(non_assigned_ovc_request_all[i]),
1840
                .sel(sel[i]),
1841
                .clk(clk),
1842
                .reset(reset),
1843
                .swap_port_presel(swap_port_presel[i])
1844
            );
1845
 
1846
 
1847
        end else begin : partial_adpt
1848
 
1849
            assign swap_port_presel[i]=1'b0;
1850
            assign avc_unavailable[i]=1'b0;
1851
 
1852
        end// ROUTE_TYPE
1853
    end//for
1854
 
1855
endgenerate
1856
endmodule
1857
 
1858
 
1859
 
1860
 
1861
 
1862
 

powered by: WebSVN 2.1.0

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