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

Subversion Repositories openmsp430

[/] [openmsp430/] [trunk/] [fpga/] [altera_de0_nano_soc/] [doc/] [Terasic/] [DE0_NANO_SOC/] [Demonstrations/] [FPGA/] [DE0_NANO_SOC_ADC/] [DE0_NANO_SOC_QSYS/] [synthesis/] [submodules/] [altera_merlin_traffic_limiter.sv] - Blame information for rev 221

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 221 olivier.gi
// (C) 2001-2014 Altera Corporation. All rights reserved.
2
// Your use of Altera Corporation's design tools, logic functions and other
3
// software and tools, and its AMPP partner logic functions, and any output
4
// files any of the foregoing (including device programming or simulation
5
// files), and any associated documentation or information are expressly subject
6
// to the terms and conditions of the Altera Program License Subscription
7
// Agreement, Altera MegaCore Function License Agreement, or other applicable
8
// license agreement, including, without limitation, that your use is for the
9
// sole purpose of programming logic devices manufactured by Altera and sold by
10
// Altera or its authorized distributors.  Please refer to the applicable
11
// agreement for further details.
12
 
13
 
14
// $Id: //acds/rel/14.0/ip/merlin/altera_merlin_traffic_limiter/altera_merlin_traffic_limiter.sv#1 $
15
// $Revision: #1 $
16
// $Date: 2014/02/16 $
17
// $Author: swbranch $
18
 
19
// -----------------------------------------------------
20
// Merlin Traffic Limiter
21
//
22
// Ensures that non-posted transaction responses are returned
23
// in order of request. Out-of-order responses can happen
24
// when a master does a non-posted transaction on a slave
25
// while responses are pending from a different slave.
26
// Examples
27
//  1) read to any latent slave, followed by a read to a
28
//   variable-latent slave
29
//  2) read to any fixed-latency slave, followed by a read
30
//   to another fixed-latency slave whose fixed latency is smaller.
31
//
32
// For now, we'll backpressure to prevent a master from
33
// switching slaves until all outstanding read responses have
34
// returned. We also have to suppress the read, obviously.
35
//
36
// Note: folding this into the router may give better fmax,
37
// consider after profiling. If folding into router, break
38
// into separate components: address router and destid router.
39
// This only needs to be in the address router.
40
// -----------------------------------------------------
41
 
42
`timescale 1 ns / 1 ns
43
// altera message_off 10036
44
module altera_merlin_traffic_limiter
45
#(
46
    parameter PKT_TRANS_POSTED          = 1,
47
              PKT_DEST_ID_H             = 0,
48
              PKT_DEST_ID_L             = 0,
49
              PKT_SRC_ID_H              = 0,
50
              PKT_SRC_ID_L              = 0,
51
              ST_DATA_W                 = 72,
52
              ST_CHANNEL_W              = 32,
53
              MAX_OUTSTANDING_RESPONSES = 1,
54
              PIPELINED                 = 0,
55
              ENFORCE_ORDER             = 1,
56
              PKT_BYTE_CNT_H            = 0,
57
              PKT_BYTE_CNT_L            = 0,
58
              PKT_BYTEEN_H              = 0,
59
              PKT_BYTEEN_L              = 0,
60
              PKT_TRANS_WRITE           = 0,
61
              PKT_TRANS_READ            = 0,
62
 
63
              // -------------------------------------
64
              // internal: allows optimization between this
65
              // component and the demux
66
              // -------------------------------------
67
              VALID_WIDTH               = 1,
68
              // -------------------------------------
69
              // beta: prevents all RAW and WAR hazards by
70
              // waiting for responses to return before issuing
71
              // a command with different direction.
72
              //
73
              // this is intended for Avalon masters that are
74
              // connected to AXI slaves.
75
              //
76
              // expect this to be replaced with a less
77
              // restrictive scheme in the future.
78
              // -------------------------------------
79
              PREVENT_HAZARDS           = 0,
80
              // -------------------------------------------------
81
              // Reorder buffer: allow master to switch slaves
82
              // while still have pending responses.
83
              // Reponses will be reordered to command issued order
84
              // -------------------------------------------------
85
                          REORDER                                       = 0
86
)
87
(
88
    // -------------------
89
    // Clock & Reset
90
    // -------------------
91
    input clk,
92
    input reset,
93
 
94
    // -------------------
95
    // Command
96
    // -------------------
97
    input                           cmd_sink_valid,
98
    input  [ST_DATA_W-1 : 0]        cmd_sink_data,
99
    input  [ST_CHANNEL_W-1 : 0]     cmd_sink_channel,
100
    input                           cmd_sink_startofpacket,
101
    input                           cmd_sink_endofpacket,
102
    output                          cmd_sink_ready,
103
 
104
    output reg [VALID_WIDTH-1  : 0] cmd_src_valid,
105
    output reg [ST_DATA_W-1    : 0] cmd_src_data,
106
    output reg [ST_CHANNEL_W-1 : 0] cmd_src_channel,
107
    output reg                      cmd_src_startofpacket,
108
    output reg                      cmd_src_endofpacket,
109
    input                           cmd_src_ready,
110
 
111
    // -------------------
112
    // Response
113
    // -------------------
114
    input                           rsp_sink_valid,
115
    input  [ST_DATA_W-1 : 0]        rsp_sink_data,
116
    input  [ST_CHANNEL_W-1 : 0]     rsp_sink_channel,
117
    input                           rsp_sink_startofpacket,
118
    input                           rsp_sink_endofpacket,
119
    output reg                      rsp_sink_ready,
120
 
121
    output reg                      rsp_src_valid,
122
    output reg [ST_DATA_W-1    : 0] rsp_src_data,
123
    output reg [ST_CHANNEL_W-1 : 0] rsp_src_channel,
124
    output reg                      rsp_src_startofpacket,
125
    output reg                      rsp_src_endofpacket,
126
    input                           rsp_src_ready
127
);
128
 
129
    // -------------------------------------
130
    // Local Parameters
131
    // -------------------------------------
132
    localparam DEST_ID_W  = PKT_DEST_ID_H - PKT_DEST_ID_L + 1;
133
    localparam COUNTER_W  = log2ceil(MAX_OUTSTANDING_RESPONSES + 1);
134
    localparam PAYLOAD_W  = ST_DATA_W + ST_CHANNEL_W + 4;
135
    localparam NUMSYMBOLS  = PKT_BYTEEN_H - PKT_BYTEEN_L + 1;
136
    localparam MAX_DEST_ID  = 1 << (DEST_ID_W);
137
    localparam PKT_BYTE_CNT_W  = PKT_BYTE_CNT_H - PKT_BYTE_CNT_L + 1;
138
 
139
    // -------------------------------------------------------
140
    // Memory parameter
141
    //
142
    // Store whole packet includes sop, eop to memory
143
    // ------------------------------------------------------
144
    //localparam MAX_RESPONSE_CNT_W  = log2ceil(MAX_OUTSTANDING_RESPONSES);
145
    localparam MAX_BYTE_CNT  = 1 << (PKT_BYTE_CNT_W);
146
    localparam MAX_BURST_LENGTH  = log2ceil(MAX_BYTE_CNT/NUMSYMBOLS);
147
    localparam MEM_W  = ST_DATA_W + ST_CHANNEL_W + 1 + 1;
148
    localparam MEM_DEPTH  = MAX_OUTSTANDING_RESPONSES * (MAX_BYTE_CNT/NUMSYMBOLS);
149
 
150
 
151
    // -----------------------------------------------------
152
    // Input Stage
153
    //
154
    // Figure out if the destination id has changed
155
    // -----------------------------------------------------
156
    wire                    stage1_nonposted_cmd;
157
    wire                    stage1_dest_changed;
158
    wire                    stage1_trans_changed;
159
    wire [PAYLOAD_W-1 : 0]  stage1_payload;
160
    wire [DEST_ID_W-1 : 0]  dest_id;
161
    reg  [DEST_ID_W-1 : 0]  last_dest_id;
162
    reg  [ST_CHANNEL_W-1:0] last_channel;
163
    reg                     was_write;
164
    wire                    is_write;
165
    wire                    suppress;
166
    wire                    save_dest_id;
167
 
168
    wire                    suppress_change_dest_id;
169
    wire                    suppress_max_outstanding;
170
    wire                    suppress_change_trans_but_not_dest;
171
    wire                                        suppress_change_trans_for_one_slave;
172
 
173
    assign dest_id = cmd_sink_data[PKT_DEST_ID_H:PKT_DEST_ID_L];
174
 
175
    generate if (PREVENT_HAZARDS == 1) begin : stage1_nonposted_block
176
        assign stage1_nonposted_cmd = 1'b1;
177
    end else begin
178
        assign stage1_nonposted_cmd = (cmd_sink_data[PKT_TRANS_POSTED] == 0);
179
    end
180
    endgenerate
181
 
182
    // ------------------------------------
183
    // Optimization: for the unpipelined case, we can save the destid if
184
    // this is an unsuppressed nonposted command. This eliminates
185
    // dependence on the backpressure signal.
186
    //
187
    // Not a problem for the pipelined case.
188
    // ------------------------------------
189
    generate begin : pipelined_save_dest_id
190
        if (PIPELINED)
191
            assign save_dest_id = cmd_sink_valid & cmd_sink_ready & stage1_nonposted_cmd;
192
        else
193
            //assign save_dest_id = cmd_sink_valid & ~suppress & stage1_nonposted_cmd;
194
            assign save_dest_id  = cmd_sink_valid & ~(suppress_change_dest_id | suppress_max_outstanding)  & stage1_nonposted_cmd;
195
    end endgenerate
196
 
197
    always @(posedge clk, posedge reset) begin
198
        if (reset) begin
199
            last_dest_id <= 0;
200
            last_channel <= 0;
201
            was_write    <= 0;
202
        end
203
        else if (save_dest_id) begin
204
            last_dest_id <= dest_id;
205
            last_channel <= cmd_sink_channel;
206
            was_write    <= is_write;
207
        end
208
    end
209
 
210
    assign is_write = cmd_sink_data[PKT_TRANS_WRITE];
211
    assign stage1_dest_changed = (last_dest_id != dest_id);
212
    assign stage1_trans_changed = (was_write != is_write);
213
 
214
    assign stage1_payload = { cmd_sink_data,
215
        cmd_sink_channel,
216
        cmd_sink_startofpacket,
217
        cmd_sink_endofpacket,
218
        stage1_dest_changed,
219
        stage1_trans_changed };
220
 
221
    // -----------------------------------------------------
222
    // (Optional) pipeline between input and output
223
    // -----------------------------------------------------
224
    wire                    stage2_valid;
225
    reg                     stage2_ready;
226
    wire [PAYLOAD_W-1 : 0]  stage2_payload;
227
 
228
    generate begin : pipelined_limiter
229
        if (PIPELINED == 1) begin
230
            altera_avalon_st_pipeline_base
231
            #(
232
                .BITS_PER_SYMBOL(PAYLOAD_W)
233
            ) stage1_pipe (
234
                .clk        (clk),
235
                .reset      (reset),
236
                .in_ready   (cmd_sink_ready),
237
                .in_valid   (cmd_sink_valid),
238
                .in_data    (stage1_payload),
239
                .out_valid  (stage2_valid),
240
                .out_ready  (stage2_ready),
241
                .out_data   (stage2_payload)
242
            );
243
        end else begin
244
            assign stage2_valid   = cmd_sink_valid;
245
            assign stage2_payload = stage1_payload;
246
            assign cmd_sink_ready = stage2_ready;
247
        end
248
    end endgenerate
249
 
250
    // -----------------------------------------------------
251
    // Output Stage
252
    // -----------------------------------------------------
253
    wire [ST_DATA_W-1 : 0]  stage2_data;
254
    wire [ST_CHANNEL_W-1:0] stage2_channel;
255
    wire                    stage2_startofpacket;
256
    wire                    stage2_endofpacket;
257
    wire                    stage2_dest_changed;
258
    wire                    stage2_trans_changed;
259
    reg                     has_pending_responses;
260
    reg  [COUNTER_W-1 : 0]  pending_response_count;
261
    reg  [COUNTER_W-1 : 0]  next_pending_response_count;
262
    wire                    nonposted_cmd;
263
    wire                    nonposted_cmd_accepted;
264
    wire                    response_accepted;
265
        wire                    response_sink_accepted;
266
        wire                                    response_src_accepted;
267
    wire                    count_is_1;
268
    wire                    count_is_0;
269
    reg                     internal_valid;
270
 
271
    assign { stage2_data,
272
        stage2_channel,
273
        stage2_startofpacket,
274
        stage2_endofpacket,
275
        stage2_dest_changed,
276
        stage2_trans_changed } = stage2_payload;
277
 
278
    generate if (PREVENT_HAZARDS == 1) begin : stage2_nonposted_block
279
        assign nonposted_cmd = 1'b1;
280
    end else begin
281
        assign nonposted_cmd = (stage2_data[PKT_TRANS_POSTED] == 0);
282
    end
283
    endgenerate
284
 
285
    assign nonposted_cmd_accepted = nonposted_cmd && internal_valid && (cmd_src_ready && cmd_src_endofpacket);
286
 
287
    // -----------------------------------------------------------------------------
288
    // Use the sink's control signals here, because write responses may be dropped
289
    // when hazard prevention is on.
290
        // When case REORDER, move all side to rsp_source as all packets from rsp_sink will
291
        // go in the reprder memory
292
        // One special case when PREVENT_HARD is on, need to use reorder_memory_valid
293
        // as the rsp_source will drop
294
    // -----------------------------------------------------------------------------
295
 
296
        assign response_sink_accepted = rsp_sink_valid && rsp_sink_ready && rsp_sink_endofpacket;
297
        // Avoid Qis warning when incase, no REORDER, the signal reorder_mem_valid is not in used.
298
        wire    reorder_mem_out_valid;
299
        wire    reorder_mem_valid;
300
        generate
301
                if (REORDER) begin
302
                        assign  reorder_mem_out_valid = reorder_mem_valid;
303
                end else begin
304
                        assign  reorder_mem_out_valid = '0;
305
                end
306
        endgenerate
307
    assign response_src_accepted = reorder_mem_out_valid & rsp_src_ready & rsp_src_endofpacket;
308
        assign response_accepted = (REORDER == 1) ? response_src_accepted : response_sink_accepted;
309
 
310
    always @* begin
311
        next_pending_response_count = pending_response_count;
312
 
313
        if (nonposted_cmd_accepted)
314
            next_pending_response_count = pending_response_count + 1'b1;
315
        if (response_accepted)
316
            next_pending_response_count = pending_response_count - 1'b1;
317
        if (nonposted_cmd_accepted && response_accepted)
318
            next_pending_response_count = pending_response_count;
319
    end
320
 
321
    assign count_is_1 = (pending_response_count == 1);
322
    assign count_is_0 = (pending_response_count == 0);
323
        // ------------------------------------------------------------------
324
    // count_max_reached : count if maximum command reach to backpressure
325
    // ------------------------------------------------------------------
326
        reg count_max_reached;
327
    always @(posedge clk, posedge reset) begin
328
        if (reset) begin
329
            pending_response_count <= 0;
330
            has_pending_responses  <= 0;
331
                        count_max_reached                  <= 0;
332
        end
333
        else begin
334
            pending_response_count <= next_pending_response_count;
335
            // synthesis translate_off
336
            if (count_is_0 && response_accepted)
337
                $display("%t: %m: Error: unexpected response: pending_response_count underflow", $time());
338
            // synthesis translate_on
339
            has_pending_responses  <= has_pending_responses
340
                && ~(count_is_1 && response_accepted && ~nonposted_cmd_accepted)
341
                || (count_is_0 && nonposted_cmd_accepted && ~response_accepted);
342
                count_max_reached <= (next_pending_response_count == MAX_OUTSTANDING_RESPONSES);
343
 
344
        end
345
    end
346
 
347
        wire suppress_prevent_harzard_for_particular_destid;
348
        wire this_destid_trans_changed;
349
    genvar j;
350
    generate begin : reorder_memory_functions
351
        if (REORDER) begin: fifo_dest_id_write_read_control_reorder_on
352
            wire [COUNTER_W - 1 : 0]    current_trans_seq_of_this_destid;
353
            wire [MAX_DEST_ID - 1 : 0]          current_trans_seq_of_this_destid_valid;
354
            wire [MAX_DEST_ID - 1 : 0]          responses_arrived;
355
            reg [COUNTER_W - 1:0]      trans_sequence;
356
            wire [MAX_DEST_ID - 1 : 0]          trans_sequence_we;
357
 
358
                        wire [COUNTER_W : 0]            trans_sequence_plus_trans_type;
359
                        wire                                                            current_trans_type_of_this_destid;
360
                        wire [COUNTER_W : 0]            current_trans_seq_of_this_destid_plus_trans_type [MAX_DEST_ID];
361
            // ------------------------------------------------------------
362
            // Control write trans_sequence to fifos
363
            //
364
            // 1. when command accepted, read destid from command packet,
365
            //      write this id to the fifo (each fifo for each desitid)
366
            // 2. when response acepted, read the destid from response packet,
367
            //      will know which sequence of this response, write it to
368
            //      correct segment in memory.
369
            //      what if two commands go to same slave, the two sequences
370
            //      go time same fifo, this even helps us to maintain order
371
            //      when two commands same thread to one slave.
372
            // -----------------------------------------------------------
373
            wire [DEST_ID_W - 1 : 0]   rsp_sink_dest_id;
374
            wire [DEST_ID_W - 1 : 0]   cmd_dest_id;
375
            assign rsp_sink_dest_id  = rsp_sink_data[PKT_SRC_ID_H : PKT_SRC_ID_L];
376
 
377
                        // write in fifo the trans_sequence and type of transaction
378
                        assign trans_sequence_plus_trans_type = {stage2_data[PKT_TRANS_WRITE], trans_sequence};
379
 
380
            // read the cmd_dest_id from output of pipeline stage so that either
381
            // or not, it wont affect how we write to fifo
382
            assign cmd_dest_id  = stage2_data[PKT_DEST_ID_H : PKT_DEST_ID_L];
383
            // -------------------------------------
384
            //  Get the transaction_seq for that dest_id
385
            // -------------------------------------
386
                        wire [COUNTER_W - 1: 0]         trans_sequence_rsp;
387
            wire [COUNTER_W : 0]                trans_sequence_rsp_plus_trans_type;
388
                        wire [COUNTER_W - 1: 0]         trans_sequence_rsp_this_destid_waiting;
389
                        wire [COUNTER_W : 0]            sequence_and_trans_type_this_destid_waiting;
390
                        wire                                                            trans_sequence_rsp_this_destid_waiting_valid;
391
                        assign trans_sequence_rsp_plus_trans_type       = current_trans_seq_of_this_destid_plus_trans_type[rsp_sink_dest_id];
392
            assign trans_sequence_rsp                                   = trans_sequence_rsp_plus_trans_type[COUNTER_W - 1: 0];
393
 
394
            // do I need to check if this fifo is valid, it should be always valid, unless a command not yet sent
395
            // and response comes back which means something weird happens.
396
            // It is worth to do an assertion but now to avoid QIS warning, just do as normal ST handshaking
397
            // check valid and ready
398
 
399
            for (j = 0; j < MAX_DEST_ID; j = j +1)
400
                begin : write_and_read_trans_sequence
401
                    assign trans_sequence_we[j]  = (cmd_dest_id == j) && nonposted_cmd_accepted;
402
                    assign responses_arrived[j]  = (rsp_sink_dest_id == j) && response_sink_accepted;
403
                end
404
 
405
            // --------------------------------------------------------------------
406
                // This is array of fifos, which will be created base on how many slaves
407
            // that this master can see (max dest_id_width)
408
            // Each fifo, will store the trans_sequence, which go to that slave
409
            // On the response path, based in the response from which slave
410
            // the fifo of that slave will be read, to check the sequences.
411
            // and this sequence is the write address to the memory
412
            // -----------------------------------------------------------------------------------
413
            // There are 3 sequences run around the limiter, they have a relationship
414
            // And this is how the key point of reorder work:
415
            //
416
            // trans_sequence        : command sequence, each command go thru the limiter
417
            //                         will have a sequence to show their order. A simple
418
            //                         counter from 0 go up and repeat.
419
            // trans_sequence_rsp    : response sequence, each response that go back to limiter,
420
            //                         will be read from trans_fifos to know their sequence.
421
            // expect_trans_sequence : Expected sequences for response that the master is waiting
422
            //                         The limiter will hold this sequence and wait until exactly response
423
            //                         for this sequence come back (trans_sequence_rsp)
424
            //                         aka: if trans_sequence_rsp back is same as expect_trans_sequence
425
            //                         then it is correct order, else response store in memory and
426
            //                         send out to master later, when expect_trans_sequence match.
427
            // ------------------------------------------------------------------------------------
428
            //    genvar i;
429
            //    generate begin : trans_sequence_fifos
430
            //if (REORDER ) begin : trans_sequence_fifos_when_reorder_on
431
            //for (i = 0;i < MAX_DEST_ID; i = i+1) begin : trans_sequence_per_fifo
432
            for (j = 0;j < MAX_DEST_ID; j = j+1) begin : trans_sequence_per_fifo
433
                altera_avalon_sc_fifo
434
                     #(
435
                       .SYMBOLS_PER_BEAT    (1),
436
                       .BITS_PER_SYMBOL     (COUNTER_W + 1), // one bit extra to store type of transaction
437
                       .FIFO_DEPTH          (MAX_OUTSTANDING_RESPONSES),
438
                       .CHANNEL_WIDTH       (0),
439
                       .ERROR_WIDTH         (0),
440
                       .USE_PACKETS         (0),
441
                       .USE_FILL_LEVEL      (0),
442
                       .EMPTY_LATENCY       (1),
443
                       .USE_MEMORY_BLOCKS   (0),
444
                       .USE_STORE_FORWARD   (0),
445
                       .USE_ALMOST_FULL_IF  (0),
446
                       .USE_ALMOST_EMPTY_IF (0)
447
                       ) dest_id_fifo
448
                     (
449
                      .clk               (clk),
450
                      .reset             (reset),
451
                      .in_data           (trans_sequence_plus_trans_type),
452
                      .in_valid          (trans_sequence_we[j]),
453
                      .in_ready          (),
454
                      .out_data          (current_trans_seq_of_this_destid_plus_trans_type[j]),
455
                      .out_valid         (current_trans_seq_of_this_destid_valid[j]),
456
                      .out_ready         (responses_arrived[j]),
457
                      .csr_address       (2'b00),                                // (terminated)
458
                      .csr_read          (1'b0),                                 // (terminated)
459
                      .csr_write         (1'b0),                                 // (terminated)
460
                      .csr_readdata      (),                                     // (terminated)
461
                      .csr_writedata     (32'b00000000000000000000000000000000), // (terminated)
462
                      .almost_full_data  (),                                     // (terminated)
463
                      .almost_empty_data (),                                     // (terminated)
464
                      .in_startofpacket  (1'b0),                                 // (terminated)
465
                      .in_endofpacket    (1'b0),                                 // (terminated)
466
                      .out_startofpacket (),                                     // (terminated)
467
                      .out_endofpacket   (),                                     // (terminated)
468
                      .in_empty          (1'b0),                                 // (terminated)
469
                      .out_empty         (),                                     // (terminated)
470
                      .in_error          (1'b0),                                 // (terminated)
471
                      .out_error         (),                                     // (terminated)
472
                      .in_channel        (1'b0),                                 // (terminated)
473
                      .out_channel       ()                                      // (terminated)
474
                      );
475
            end // block: trans_sequence_per_fifo
476
 
477
            // -------------------------------------------------------
478
            // Calculate the transaction sequence, just simple increase
479
            // when each commands pass by
480
            // --------------------------------------------------------
481
                always @(posedge clk or posedge reset)
482
                begin
483
                    if (reset) begin
484
                        trans_sequence   <= '0;
485
                    end else begin
486
                        if (nonposted_cmd_accepted)
487
                            trans_sequence <= ( (trans_sequence + 1'b1) == MAX_OUTSTANDING_RESPONSES) ? '0 : trans_sequence + 1'b1;
488
                    end
489
                end
490
 
491
            // -------------------------------------
492
            // Control Memory for reorder responses
493
            // -------------------------------------
494
            wire [COUNTER_W - 1 : 0] next_rd_trans_sequence;
495
            reg [COUNTER_W - 1 : 0]  rd_trans_sequence;
496
            reg [COUNTER_W - 1 : 0]  next_expected_trans_sequence;
497
            reg [COUNTER_W - 1 : 0]  expect_trans_sequence;
498
            wire [ST_DATA_W - 1 : 0]          reorder_mem_data;
499
            wire [ST_CHANNEL_W - 1 : 0]       reorder_mem_channel;
500
            wire                              reorder_mem_startofpacket;
501
            wire                              reorder_mem_endofpacket;
502
            //wire                              reorder_mem_valid;
503
                        wire                                                      reorder_mem_ready;
504
            // -------------------------------------------
505
            // Data to write and read from reorder memory
506
            // Store everything includes channel, sop, eop
507
            // -------------------------------------------
508
            reg [MEM_W - 1 : 0]         mem_in_rsp_sink_data;
509
            reg [MEM_W - 1 : 0]         reorder_mem_out_data;
510
            always_comb
511
                begin
512
                    mem_in_rsp_sink_data  = {rsp_sink_data, rsp_sink_channel, rsp_sink_startofpacket, rsp_sink_endofpacket};
513
                end
514
 
515
            assign next_rd_trans_sequence  = ((rd_trans_sequence + 1'b1) == MAX_OUTSTANDING_RESPONSES) ? '0 : rd_trans_sequence + 1'b1;
516
            assign next_expected_trans_sequence  = ((expect_trans_sequence + 1'b1) == MAX_OUTSTANDING_RESPONSES) ? '0 : expect_trans_sequence + 1'b1;
517
 
518
            always_ff @(posedge clk, posedge reset)
519
                begin
520
                    if (reset) begin
521
                        rd_trans_sequence     <= '0;
522
                        expect_trans_sequence <= '0;
523
                    end else begin
524
                        if (rsp_src_ready && reorder_mem_valid) begin
525
                            if (reorder_mem_endofpacket == 1) begin //endofpacket
526
                                expect_trans_sequence <= next_expected_trans_sequence;
527
                                rd_trans_sequence     <= next_rd_trans_sequence;
528
                                                end
529
                        end
530
                    end
531
                end // always_ff @
532
 
533
                        // For PREVENT_HAZARD,
534
                        // Case: Master Write to S0, read S1, and Read S0 back but if Write for S0
535
                        // not yet return then we need to backpressure this, else read S0 might take over write
536
                        // This is more checking after the fifo destid, as read S1 is inserted in midle
537
                        // when see new packet, try to look at the fifo for that slave id, check if it
538
                        // type of transaction
539
                        assign sequence_and_trans_type_this_destid_waiting      = current_trans_seq_of_this_destid_plus_trans_type[cmd_dest_id];
540
                        assign current_trans_type_of_this_destid                        = sequence_and_trans_type_this_destid_waiting[COUNTER_W];
541
                        assign trans_sequence_rsp_this_destid_waiting_valid     = current_trans_seq_of_this_destid_valid[cmd_dest_id];
542
                        //assign suppress_prevent_harzard_for_particular_destid = (trans_sequence_rsp_this_destid_waiting == expect_trans_sequence) & (current_trans_type_of_this_destid != is_write)
543
                        // it might waiting other sequence, check if different type of transaction as only for PREVENT HAZARD
544
                        // if comming comamnd to one slave and this slave is still waiting for response from previous command
545
                        // which has diiferent type of transaction, we back-pressure this command to avoid HAZARD
546
                        assign suppress_prevent_harzard_for_particular_destid =  (current_trans_type_of_this_destid != is_write) & trans_sequence_rsp_this_destid_waiting_valid;
547
 
548
            // -------------------------------------
549
            // Memory for reorder buffer
550
            // -------------------------------------
551
            altera_merlin_reorder_memory
552
                #(
553
                  .DATA_W      (MEM_W),
554
                  .ADDR_H_W    (COUNTER_W),
555
                  .ADDR_L_W    (MAX_BURST_LENGTH),
556
                          .NUM_SEGMENT (MAX_OUTSTANDING_RESPONSES),
557
                  .DEPTH       (MEM_DEPTH)
558
                  ) reorder_memory
559
                    (
560
                     .clk               (clk),
561
                     .reset             (reset),
562
                     .in_data           (mem_in_rsp_sink_data),
563
                     .in_valid          (rsp_sink_valid),
564
                     .in_ready          (reorder_mem_ready),
565
                     .out_data          (reorder_mem_out_data),
566
                     .out_valid                 (reorder_mem_valid),
567
                             .out_ready                 (rsp_src_ready),
568
                     .wr_segment                (trans_sequence_rsp),
569
                     .rd_segment        (expect_trans_sequence)
570
                     );
571
            // -------------------------------------
572
            // Output from reorder buffer
573
            // -------------------------------------
574
            assign reorder_mem_data  = reorder_mem_out_data[MEM_W -1 : ST_CHANNEL_W + 2];
575
            assign reorder_mem_channel  = reorder_mem_out_data[ST_CHANNEL_W + 2 - 1 : 2];
576
            assign reorder_mem_startofpacket  = reorder_mem_out_data[1];
577
            assign reorder_mem_endofpacket  = reorder_mem_out_data[0];
578
 
579
            // -------------------------------------
580
            // Because use generate statment
581
            // so move all rsp_src_xxx controls here
582
            // -------------------------------------
583
            always_comb begin
584
                cmd_src_data           = stage2_data;
585
                rsp_src_valid          = reorder_mem_valid;
586
                rsp_src_data           = reorder_mem_data;
587
                rsp_src_channel        = reorder_mem_channel;
588
                rsp_src_startofpacket  = reorder_mem_startofpacket;
589
                rsp_src_endofpacket    = reorder_mem_endofpacket;
590
                // -------------------------------------
591
                // Forces commands to be non-posted if hazard prevention
592
                // is on, also drops write responses
593
                // -------------------------------------
594
                if (PREVENT_HAZARDS == 1) begin
595
                    cmd_src_data[PKT_TRANS_POSTED] = 1'b0;
596
 
597
                    if (rsp_src_data[PKT_TRANS_WRITE] == 1'b1) begin
598
                        rsp_src_valid  = 1'b0;
599
                        rsp_sink_ready = 1'b1;
600
                    end
601
                end
602
                rsp_sink_ready         = reorder_mem_ready; // now it takes ready signal from the memory not direct from master
603
            end // always_comb
604
 
605
        end // block: fifo_dest_id_write_read_control_reorder_on
606
    end // block: reorder_memory_functions
607
    endgenerate
608
 
609
    // -------------------------------------
610
    // Pass-through command and response
611
    // -------------------------------------
612
 
613
    always_comb
614
        begin
615
            cmd_src_channel        = stage2_channel;
616
            cmd_src_startofpacket  = stage2_startofpacket;
617
            cmd_src_endofpacket    = stage2_endofpacket;
618
            //cmd_src_data           = stage2_data;
619
        end // always_comb
620
 
621
    // -------------------------------------
622
    // When there is no REORDER requirement
623
    // Just pass thru signals
624
    // -------------------------------------
625
    generate begin : use_selector_or_pass_thru_rsp
626
        if (!REORDER) begin
627
            always_comb begin
628
                cmd_src_data           = stage2_data;
629
                // pass thru almost signals
630
                rsp_src_valid          = rsp_sink_valid;
631
                rsp_src_data           = rsp_sink_data;
632
                rsp_src_channel        = rsp_sink_channel;
633
                rsp_src_startofpacket  = rsp_sink_startofpacket;
634
                rsp_src_endofpacket    = rsp_sink_endofpacket;
635
                // -------------------------------------
636
                // Forces commands to be non-posted if hazard prevention
637
                // is on, also drops write responses
638
                // -------------------------------------
639
                if (PREVENT_HAZARDS == 1) begin
640
                    cmd_src_data[PKT_TRANS_POSTED] = 1'b0;
641
 
642
                    if (rsp_sink_data[PKT_TRANS_WRITE] == 1'b1) begin
643
                        rsp_src_valid  = 1'b0;
644
                        rsp_sink_ready = 1'b1;
645
                    end
646
                end
647
                rsp_sink_ready         = rsp_src_ready; // take care this, should check memory empty
648
            end // always_comb
649
        end // if (!REORDER)
650
    end // block: use_selector_or_pass_thru_rsp
651
    endgenerate
652
 
653
    // --------------------------------------------------------
654
    // Backpressure & Suppression
655
    // --------------------------------------------------------
656
    // ENFORCE_ORDER: unused option, alway is 1, remove it
657
    // Now the lmiter will suppress when max_outstanding reach
658
    // --------------------------------------------------------
659
    generate begin : enforce_order_block
660
        if (ENFORCE_ORDER) begin
661
            assign suppress_change_dest_id = (REORDER == 1) ? 1'b0 : nonposted_cmd && has_pending_responses &&
662
                                              (stage2_dest_changed || (PREVENT_HAZARDS == 1 && stage2_trans_changed));
663
        end else begin
664
            assign suppress_change_dest_id = 1'b0;
665
        end
666
    end endgenerate
667
    // ------------------------------------------------------------
668
    // Even we allow change slave while still have pending responses
669
    // But one special case, when PREVENT_HAZARD=1, we still allow
670
    // switch slave while type of transaction change (RAW, WAR) but
671
    // only to different slaves.
672
    // if to same slave, we still need back pressure that to make
673
    // sure no racing
674
    // ------------------------------------------------------------
675
 
676
    generate begin : prevent_hazard_block
677
        if (REORDER)
678
            assign suppress_change_trans_but_not_dest = nonposted_cmd && has_pending_responses &&
679
                                                        !stage2_dest_changed && (PREVENT_HAZARDS == 1 && stage2_trans_changed);
680
        else
681
            assign suppress_change_trans_but_not_dest  = 1'b0; // no REORDER, the suppress_changes_destid take care of this.
682
        end
683
    endgenerate
684
 
685
        generate begin : prevent_hazard_block_for_particular_slave
686
        if (REORDER)
687
                        assign suppress_change_trans_for_one_slave = nonposted_cmd && has_pending_responses && (PREVENT_HAZARDS == 1 && suppress_prevent_harzard_for_particular_destid);
688
        else
689
            assign suppress_change_trans_for_one_slave  = 1'b0; // no REORDER, the suppress_changes_destid take care of this.
690
        end
691
    endgenerate
692
 
693
    // ------------------------------------------
694
    // Back pressure when max outstanding reached
695
    // ------------------------------------------
696
    generate begin : max_outstanding_block
697
        if (REORDER)
698
            assign suppress_max_outstanding  = count_max_reached;
699
        else
700
            assign suppress_max_outstanding  = 1'b0;
701
    end
702
    endgenerate
703
 
704
        assign suppress = suppress_change_trans_for_one_slave | suppress_change_dest_id | suppress_max_outstanding;
705
    always @* begin
706
        stage2_ready = cmd_src_ready;
707
        internal_valid = stage2_valid;
708
        // --------------------------------------------------------
709
        // change suppress condidtion, in case REODER it will alllow changing slave
710
        // even still have pending transactions.
711
        // -------------------------------------------------------
712
         if (suppress) begin
713
        //if (suppress_change_dest_id || suppress_max_outstanding || suppress_change_trans_but_not_dest) begin
714
            stage2_ready = 0;
715
            internal_valid = 0;
716
        end
717
 
718
        if (VALID_WIDTH == 1) begin
719
            cmd_src_valid = {VALID_WIDTH{1'b0}};
720
            cmd_src_valid [0] = internal_valid;
721
        end else begin
722
            // -------------------------------------
723
            // Use the one-hot channel to determine if the destination
724
            // has changed. This results in a wide valid bus
725
            // -------------------------------------
726
            //cmd_src_valid  = { VALID_WIDTH {stage2_valid} } & cmd_sink_channel;
727
                        // it supposes to use stage2_channel, else PIPELINE switch wrong valid signals
728
                        cmd_src_valid  = { VALID_WIDTH {stage2_valid} } & stage2_channel;
729
            if (nonposted_cmd & has_pending_responses ) begin
730
                if (!REORDER) begin
731
                                        cmd_src_valid  = cmd_src_valid & last_channel;
732
                    // -------------------------------------
733
                    // Mask the valid signals if the transaction type has changed
734
                    // if hazard prevention is enabled
735
                    // -------------------------------------
736
                    if (PREVENT_HAZARDS == 1)
737
                        cmd_src_valid  = cmd_src_valid & { VALID_WIDTH {!stage2_trans_changed} };
738
                                end else  begin // else: !if(!REORDER) if REORFER happen
739
                                        if (PREVENT_HAZARDS == 1)
740
                                                cmd_src_valid  = cmd_src_valid & { VALID_WIDTH {!suppress_change_trans_for_one_slave} };
741
                                        if (suppress_max_outstanding) begin
742
                                                cmd_src_valid  = cmd_src_valid & {VALID_WIDTH {1'b0} };
743
                                        end
744
 
745
                end
746
            end
747
        end
748
    end
749
 
750
    // --------------------------------------------------
751
    // Calculates the log2ceil of the input value.
752
    //
753
    // This function occurs a lot... please refactor.
754
    // --------------------------------------------------
755
    function integer log2ceil;
756
        input integer val;
757
        integer i;
758
 
759
        begin
760
            i = 1;
761
            log2ceil = 0;
762
 
763
            while (i < val) begin
764
                log2ceil = log2ceil + 1;
765
                i = i << 1;
766
            end
767
        end
768
    endfunction
769
 
770
endmodule
771
 
772
 

powered by: WebSVN 2.1.0

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