Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

Unknown xx req signal for NoC coding

Status
Not open for further replies.

promach

Advanced Member level 4
Joined
Feb 22, 2016
Messages
1,199
Helped
2
Reputation
4
Reaction score
5
Trophy points
1,318
Activity points
11,636
I am having unknown xx for req[1:0] signal in a NoC verilog code implementation

Please advise.

uw2hSak.png



Code Verilog - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
// a single node within the Spidergon
 
module spidergon_router 
#(
    `ifdef FORMAL   
        parameter NUM_OF_NODES=8, 
        parameter FLIT_DATA_WIDTH=8,
        parameter NODE_BUFFER_WIDTH=16,
    `else
        parameter NUM_OF_NODES=32,
        parameter FLIT_DATA_WIDTH=16,
        parameter NODE_BUFFER_WIDTH=32, // a single vc buffer can hold 2 flits at one time
    `endif
 
    parameter NODE_IDENTIFIER=0,  
    parameter NUM_OF_VIRTUAL_CHANNELS=2 // 2 vc for each input ports of each node
) 
(
    clk, reset, 
    `ifdef FORMAL
    input_flit_type,
    OUT_PORT_NUM,
    `endif
    flit_data_input_across, flit_data_input_clockwise, flit_data_input_anticlockwise,
    flit_data_output_across, flit_data_output_clockwise, flit_data_output_anticlockwise, 
    node_data_from_cpu, node_data_to_cpu, data_input,
    flit_data_input_are_valid, flit_data_output_are_valid,
    current_node_is_ready, adjacent_nodes_are_ready,
    current_node_vc_are_full, adjacent_node_vc_are_full
);
 
 
localparam STOP = 3;
localparam ACROSS = 2;
localparam CLOCKWISE = 1;
localparam ANTI_CLOCKWISE = 0;
 
 
// the most significant two bits are to indicate head and/or tail flits,
// followed by dest_node and flit_data_payload
// See [url]https://www.lisnoc.org/packets.html[/url]
 
// 01 = head_flit , 10 = data_flit (body_flit), 00 = tail_flit, 11 = flit_without_data_payload
localparam HEAD_FLIT = 'b01;
localparam HEADER = 'b11; // flit_without_data_payload
localparam BODY_FLIT = 'b10;
localparam TAIL_FLIT = 'b00;
 
localparam HEAD_TAIL = 2;
localparam DEST_NODE_WIDTH = $clog2(NUM_OF_NODES);
localparam FLIT_TOTAL_WIDTH = HEAD_TAIL+FLIT_DATA_WIDTH;
 
 
localparam NUM_OF_PORTS = 3; // clockwise, anti-clockwise, across
localparam BIDIRECTIONAL_PER_PORT = 2; // two-way data traffic
 
 
input clk, reset;
 
input [FLIT_TOTAL_WIDTH-1:0] data_input;
 
input [FLIT_TOTAL_WIDTH-1:0] flit_data_input_across;
input [FLIT_TOTAL_WIDTH-1:0] flit_data_input_clockwise;
input [FLIT_TOTAL_WIDTH-1:0] flit_data_input_anticlockwise;
 
input [FLIT_TOTAL_WIDTH-1:0] node_data_from_cpu;
output [FLIT_TOTAL_WIDTH-1:0] node_data_to_cpu;
 
output [FLIT_TOTAL_WIDTH-1:0] flit_data_output_across;
output [FLIT_TOTAL_WIDTH-1:0] flit_data_output_clockwise;
output [FLIT_TOTAL_WIDTH-1:0] flit_data_output_anticlockwise;
 
input [NUM_OF_PORTS-1:0] flit_data_input_are_valid;
output [NUM_OF_PORTS-1:0] flit_data_output_are_valid;
 
// adjacent nodes can accept new head flit to reserve one virtual channel
input [NUM_OF_PORTS*NUM_OF_VIRTUAL_CHANNELS-1:0] adjacent_nodes_are_ready;
 
// current node can accept new head flit to reserve one virtual channel
output [NUM_OF_PORTS*NUM_OF_VIRTUAL_CHANNELS-1:0] current_node_is_ready;
 
// to indicate to the node about the virtual channel buffers fill status
input [NUM_OF_PORTS*NUM_OF_VIRTUAL_CHANNELS-1:0] adjacent_node_vc_are_full;
output [NUM_OF_PORTS*NUM_OF_VIRTUAL_CHANNELS-1:0] current_node_vc_are_full;
 
 
reg [NUM_OF_PORTS-1:0] flit_data_output_are_valid_previously;
 
wire [FLIT_TOTAL_WIDTH-1:0] flit_data_input [NUM_OF_PORTS-1:0];
reg [FLIT_TOTAL_WIDTH-1:0] flit_data_output [NUM_OF_PORTS-1:0];
 
 
assign flit_data_input[ACROSS] = flit_data_input_across;
assign flit_data_input[CLOCKWISE] = flit_data_input_clockwise;
assign flit_data_input[ANTI_CLOCKWISE] = flit_data_input_anticlockwise;
 
assign flit_data_output_across = flit_data_output[ACROSS];
assign flit_data_output_clockwise = flit_data_output[CLOCKWISE];
assign flit_data_output_anticlockwise = flit_data_output[ANTI_CLOCKWISE];
 
 
// these virtual channel buffers are at input port side
wire [FLIT_TOTAL_WIDTH-1:0] data_output_from_vc [NUM_OF_PORTS-1:0][NUM_OF_VIRTUAL_CHANNELS-1:0];
wire [FLIT_TOTAL_WIDTH-1:0] data_input_to_vc [NUM_OF_PORTS-1:0][NUM_OF_VIRTUAL_CHANNELS-1:0];
 
wire [NUM_OF_VIRTUAL_CHANNELS-1:0] vc_is_available [NUM_OF_PORTS-1:0]; // vc is not BUSY
wire [NUM_OF_VIRTUAL_CHANNELS-1:0] vc_buffer_is_empty [NUM_OF_PORTS-1:0]; // no flits inside vc
 
// requests for the input data (from one of the 3 input ports) 
// to be routed to  destination node (via one of the 3 output ports)
// this 'req' is not a one-hot vector: reg [vc_num] req [out_port];
// multiple input data streams from different virtual channels could compete for the same output port
reg [NUM_OF_VIRTUAL_CHANNELS-1:0] req [NUM_OF_PORTS-1:0];
 
reg [NUM_OF_VIRTUAL_CHANNELS-1:0] req_previous [NUM_OF_PORTS-1:0];
 
 
wire [NUM_OF_VIRTUAL_CHANNELS-1:0] vc_is_to_be_allocated [NUM_OF_PORTS-1:0];
wire [NUM_OF_VIRTUAL_CHANNELS-1:0] vc_is_to_be_deallocated [NUM_OF_PORTS-1:0];
 
 
localparam DIRECTION_WIDTH = 2;
wire [DIRECTION_WIDTH-1:0] direction [NUM_OF_PORTS-1:0]; // stop, clockwise, anti-clockwise, across
 
wire [DEST_NODE_WIDTH-1:0] dest_node [NUM_OF_PORTS-1:0];
 
 
localparam NON_EXISTENCE_VC_NUM = {(NUM_OF_VIRTUAL_CHANNELS+1){1'b1}};
 
 
wire [NUM_OF_PORTS-1:0] req_port;
 
// note that 'grant' is one-hot vector, 
// when asserted, it means the corresponding 'req' is approved/granted
// and only a single priority line is serviced (granted) at any given clock cycle
wire [NUM_OF_VIRTUAL_CHANNELS-1:0] granted_vc;
wire [NUM_OF_PORTS-1:0] granted_port;
 
// binary encoding of 'granted_vc' and 'granted_port'. Refer to module 'oh_to_idx'
wire [$clog2(NUM_OF_VIRTUAL_CHANNELS)-1:0] granted_vc_index;
wire [$clog2(NUM_OF_PORTS)-1:0] granted_port_index;
 
// Ports round-robin arbitration (maps port to cpu)
arbiter #(NUM_OF_PORTS) rr_arb_port_to_cpu
(.clk(clk), .reset(reset), .req(req_port), .grant(granted_port));
 
 
// remember that each ports have multiple vc
// virtual channel (VC) outgoing buffers round-robin arbitration (maps vc in port to cpu)
arbiter #(NUM_OF_VIRTUAL_CHANNELS) rr_arb_vc_to_cpu
(.clk(clk), .reset(reset), .req(req[granted_port]), .grant(granted_vc));
 
 
// for one-hot encoding to binary encoding conversion
oh_to_idx #(NUM_OF_PORTS) port_index (.one_hot(granted_port), .index(granted_port_index));
oh_to_idx #(NUM_OF_VIRTUAL_CHANNELS) vc_index (.one_hot(granted_vc), .index(granted_vc_index));
 
 
assign node_data_to_cpu = (reset || (vc_buffer_is_empty[granted_port_index][granted_vc_index])) ? 
                            data_input[0 +: FLIT_TOTAL_WIDTH] :
                            data_output_from_vc[granted_port_index][granted_vc_index];
 
`ifdef FORMAL
    output [NUM_OF_PORTS*HEAD_TAIL-1:0] input_flit_type;
    output [NUM_OF_PORTS*DIRECTION_WIDTH-1:0] OUT_PORT_NUM;
`else
    wire [NUM_OF_PORTS*HEAD_TAIL-1:0] input_flit_type;
    wire [NUM_OF_PORTS*DIRECTION_WIDTH-1:0] OUT_PORT_NUM;
`endif
 
wire [$clog2(NUM_OF_NODES)-1:0] current_node = NODE_IDENTIFIER;
 
 
// note that flits from the same data packet cannot be interleaved 
// among different virtual channels
// Why ? Because of head flit and tail flit indication
 
// let FLIT_DATA_WIDTH = 16 in the discussion below:
 
// 16-bit head flit format as follows: {01, prev_vc, destination_node, 8 bits of data_payload}
// prev_vc consumes 1 bit, destination_node consumes 5 bits (32 nodes in total), 
// so we are left with 8 bits in the head flit
// these 8 bits could be data payload as well
 
// 16-bit body flit format as follows: {10, prev_vc, 13 bits of data_payload}
// 16-bit tail flit format as follows: {00, prev_vc, 13 bits of data_payload}
// So, a single body_flit or tail_flit could carry 13 bits of data payload
// tail flit will deallocate all the virtual channels along the path to the destination nodes
 
// for wormhole switching flow control purpose 
// basically each node itself need to remember(store) exactly which header 
// allocates which virtual channel, and this storing has to be coherent for 
// previous and current nodes due to wormhole switching requirement
 
/* 
    A vc allocation table for current node (imagine the use of linked-list data structure)
 
    Current_Port    Current_VC      Prev_VC     BUSY    FULL
 
    ACROSS              0           X           X       X
    ACROSS              1           X           X       X
 
    CLOCKWISE           0           X           X       X
    CLOCKWISE           1           X           X       X
 
    ANTI_CLOCKWISE      0           X           X       X
    ANTI_CLOCKWISE      1           X           X       X
 
 
    Note: 
    1. The head flit contains Prev_VC (no need for Prev_Port since we can deduce from Current_Port)
    2. Once a Current_VC is reserved by head flit, the corresponding table entry is filled
    3. Once a Current_VC is de-reserved by tail flit, the corresponding table entry is updated
    4. BUSY and FULL signals are for Current_VC, not for Prev_VC
    5. A table costs 36 bits (NUM_OF_ROWS*(2+1+1+1+1))
*/
 
 
genvar port_num;
genvar vc_num;
 
generate
 
    for(port_num=0; port_num<NUM_OF_PORTS; port_num=port_num+1)
    begin   
 
        assign OUT_PORT_NUM[port_num*DIRECTION_WIDTH +: DIRECTION_WIDTH] = direction[port_num];
 
        // asserted whenever one of the virtual channels in each port is reserved
        assign req_port[port_num] = |req[port_num]; 
 
 
        assign input_flit_type[port_num*HEAD_TAIL +: HEAD_TAIL] 
            = (reset) ? data_input[(FLIT_TOTAL_WIDTH-1) -: HEAD_TAIL] : 
                        flit_data_input[port_num][(FLIT_TOTAL_WIDTH-1) -: HEAD_TAIL] ;
 
        // virtual channel index at previous node
        wire prev_vc = 
                flit_data_input[port_num][(FLIT_DATA_WIDTH-1) -: $clog2(NUM_OF_VIRTUAL_CHANNELS)] ;
 
 
        wire [NUM_OF_VIRTUAL_CHANNELS-1:0] adjacent_nodes_vc_are_reserved_and_not_full;
 
        wire [NUM_OF_VIRTUAL_CHANNELS-1:0] granted_vc_enqueue; // to indicate which vc to reserve
 
        // remember that each ports have multiple vc
        // virtual channel (VC) incoming buffers round-robin arbitration (maps incoming data to vc)
        arbiter #(NUM_OF_VIRTUAL_CHANNELS) rr_arb_data_to_vc
        (
            .clk(clk), 
            .reset(reset), 
            .req(current_node_is_ready[port_num*NUM_OF_VIRTUAL_CHANNELS +: NUM_OF_VIRTUAL_CHANNELS]), 
            .grant(granted_vc_enqueue)
        );
 
        for(vc_num=0; vc_num<NUM_OF_VIRTUAL_CHANNELS; vc_num=vc_num+1)
        begin
            // ON/OFF flow control
            // to indicate whether flit data could come into the node
 
            // (vc buffer is not reserved)
            assign current_node_is_ready[port_num*NUM_OF_VIRTUAL_CHANNELS + vc_num] =
                    vc_is_available[port_num][vc_num];
 
 
            // (the next node has at least one available, non-reserved vc) OR 
            // (any of the reserved vc (at next node) has sufficient buffer space)  
            wire dequeue_en = (reset) ? 0 :
                ((|adjacent_nodes_are_ready[dest_node[port_num]*NUM_OF_VIRTUAL_CHANNELS +:
                                            NUM_OF_VIRTUAL_CHANNELS]) ||
 
                |adjacent_nodes_vc_are_reserved_and_not_full);
 
            assign adjacent_nodes_vc_are_reserved_and_not_full[vc_num] = 
              ((!adjacent_nodes_are_ready[dest_node[port_num]*NUM_OF_VIRTUAL_CHANNELS + vc_num]) 
              & (!adjacent_node_vc_are_full[dest_node[port_num]*NUM_OF_VIRTUAL_CHANNELS + vc_num]));
 
 
            // enqueues when 'vc is still reserved' && 'data is valid' && ('vc is not reserved' || 
            // ('vc is reserved' by the same 'head flit' && '!current vc is full'))
 
            wire enqueue_en = (granted_vc_enqueue[vc_num] || req[port_num][vc_num]) &&
                        flit_data_input_are_valid[port_num] &&
 
                        (vc_is_available[port_num][vc_num] || 
                        (!vc_is_available[port_num][vc_num] && 
                        (flit_data_input[port_num][(FLIT_DATA_WIDTH-1) -: $clog2(NUM_OF_VIRTUAL_CHANNELS)] == vc_num) &&
                         !current_node_vc_are_full[port_num*NUM_OF_VIRTUAL_CHANNELS + vc_num]));
 
 
            // virtual channel buffer in the form of strict FIFO ordering
            sync_fifo 
            #(
                .WIDTH(FLIT_TOTAL_WIDTH),
                .SIZE(NODE_BUFFER_WIDTH/FLIT_DATA_WIDTH)
            )
            fifo
            (
                .clk(clk), .reset(reset), .flush_en(1'b0), 
                .full(current_node_vc_are_full[port_num*NUM_OF_VIRTUAL_CHANNELS + vc_num]), 
                .enqueue_en(enqueue_en), 
                .enqueue_value(data_input_to_vc[port_num][vc_num]),
 
                // buffer could be empty even it is reserved, due to flits not arriving yet
                .empty(vc_buffer_is_empty[port_num][vc_num]),
                .dequeue_en(dequeue_en), // enabled when the buffers at next node can take in flits
                .dequeue_value(data_output_from_vc[port_num][vc_num])
            );
    
            assign data_input_to_vc[port_num][vc_num] = flit_data_input[port_num];          
 
            assign vc_is_available[port_num][vc_num] = !req[port_num][vc_num];
 
 
            always @(posedge clk) 
            begin
                if(reset) req_previous[port_num][vc_num] <= 0;
 
                else req_previous[port_num][vc_num] <= req[port_num][vc_num];
            end
 
 
            // NOT reserved yet for usage by other flit
            // remember that each header or head flit could only reserve ONE vc in each port
            assign vc_is_to_be_allocated[port_num][vc_num] = (reset) ? 0 :
                    (!req[port_num][vc_num] ||
                    (input_flit_type[port_num*HEAD_TAIL +: HEAD_TAIL] == HEADER) ||
                    (input_flit_type[port_num*HEAD_TAIL +: HEAD_TAIL] == HEAD_FLIT));
 
            // vc is already reserved, waiting to be released by tail_flit
            assign vc_is_to_be_deallocated[port_num][vc_num] = (reset) ? 0 :
                    (req_previous[port_num][vc_num] && 
                    (input_flit_type[port_num*HEAD_TAIL +: HEAD_TAIL] == TAIL_FLIT) &&
                    (prev_vc == vc_num));
 
 
            // virtual channel reservation logic block
            always @(posedge clk) 
            begin
                if(reset) req[port_num][vc_num] <= 0;
 
                else if ((vc_is_to_be_allocated[port_num][vc_num] && 
                         !vc_is_to_be_deallocated[port_num][vc_num]) || 
 
                        (vc_is_to_be_deallocated[port_num][vc_num] && 
                         !vc_is_to_be_allocated[port_num][vc_num])) begin
 
                    // HEAD_FLIT or HEADER will reserve the virtual channel
                    // BODY_FLIT will not affect the channel reservation status
                    // TAIL_FLIT will de-reserve the virtual channel reserved by HEAD_FLIT
                    // HEADER will only reserves its virtual channel for single clock cycle
 
                    // check the flit header to determine the flit nature
                    case(input_flit_type[port_num*HEAD_TAIL +: HEAD_TAIL]) 
                    
                        // body_flit
                        // to keep 'req' asserted before the arrival of tail_flit
                        BODY_FLIT : req[port_num][vc_num] <= 1;
 
                        // tail_flit
                        TAIL_FLIT : req[port_num][vc_num] <= 0;
 
                        // head_flit
                        HEAD_FLIT : req[port_num][vc_num] <= 1;
 
                        // flit_without_data_payload
                        HEADER : req[port_num][vc_num] <= 1;
 
                        default : req[port_num][vc_num] <= 0;
 
                    endcase
                end
 
                //else req[direction[port_num]][vc_num] <= 0; // for HEADER
            end
 
            `ifdef FORMAL
 
            //always @(posedge clk)  cover((vc_num == vc_new) || (vc_num == vc_old));
 
            `endif
 
        end
 
 
        assign dest_node[port_num] = (reset) ? data_input[(FLIT_DATA_WIDTH-1) -: DEST_NODE_WIDTH] :
                flit_data_input[port_num][(FLIT_DATA_WIDTH-$clog2(NUM_OF_VIRTUAL_CHANNELS)-1) -: DEST_NODE_WIDTH];
 
        // path routing computation block for each input ports
        router #(NUM_OF_NODES) rt 
        (
            .clk(clk), 
            .reset(reset), 
            .dest_node(dest_node[port_num]), 
            .current_node(current_node), 
            .direction(direction[port_num])
        );
 
 
        always @(posedge clk)
        begin
            if(reset) flit_data_output_are_valid_previously[port_num] <= 1;
                
            else flit_data_output_are_valid_previously[port_num] <= flit_data_output_are_valid[port_num];
        end
        
 
        wire [(HEAD_TAIL-1) : 0] output_flit_type = 
                    node_data_from_cpu[(FLIT_TOTAL_WIDTH-1) -: HEAD_TAIL];
 
        // needs some backpressure logic here
        assign flit_data_output_are_valid[port_num] = (reset) ? 1'b1 : 
                    ((output_flit_type == HEAD_FLIT) || (output_flit_type == HEADER)) ||
                    (flit_data_output_are_valid_previously[port_num] && 
                     (output_flit_type != TAIL_FLIT));
 
 
        always @(posedge clk)
        begin
            if(reset) 
            begin
                flit_data_output[port_num] <= 0; // clears data in all channels first
                flit_data_output[direction[port_num]] <= node_data_from_cpu; // initial data input for NoC
            end
            
            else if(flit_data_output_are_valid[direction[port_num]]) begin
                // needs some backpressure logic here
                // sends out data from cpu to physical channel
                flit_data_output[direction[port_num]] <= node_data_from_cpu;
            end
        end
 
    end
 
endgenerate
 
endmodule

 

The "req" you show in the waveform is not the one you highlight in the code. Its the req inside the rr_arb_port_to_cpu instance
 

Hi,

The XX signal is because of incomplete test signals in your testbench to be able to determine the state of the output signal. Check your testbench signals for the time where the XX signals comes up.

- - - Updated - - -

Just ensure that all required input test signals are complete at all times for there to be a determinate output value.
 

This line only resets one of the req array locations.
if(reset) req[port_num][vc_num] <= 0;

You should use a for loop to reset all the req array entries.
 

Now, I am facing another unknown x problem for 'enqueue_en' signal.

why removing "flit_data_input_are_valid[port_num]" from enqueue_en logic solved the strange, unknown x for 'enqueue_en' signal ?

cACy1ph.png
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top