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

Subversion Repositories spacewiresystemc

[/] [spacewiresystemc/] [trunk/] [altera_work/] [spw_fifo_ulight/] [ulight_fifo/] [synthesis/] [submodules/] [altera_avalon_sc_fifo.v] - Blame information for rev 32

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 32 redbear
// -----------------------------------------------------------
2
// Legal Notice: (C)2007 Altera Corporation. All rights reserved.  Your
3
// use of Altera Corporation's design tools, logic functions and other
4
// software and tools, and its AMPP partner logic functions, and any
5
// output files any of the foregoing (including device programming or
6
// simulation files), and any associated documentation or information are
7
// expressly subject to the terms and conditions of the Altera Program
8
// License Subscription Agreement or other applicable license agreement,
9
// including, without limitation, that your use is for the sole purpose
10
// of programming logic devices manufactured by Altera and sold by Altera
11
// or its authorized distributors.  Please refer to the applicable
12
// agreement for further details.
13
//
14
// Description: Single clock Avalon-ST FIFO.
15
// -----------------------------------------------------------
16
 
17
`timescale 1 ns / 1 ns
18
 
19
 
20
//altera message_off 10036
21
module altera_avalon_sc_fifo
22
#(
23
    // --------------------------------------------------
24
    // Parameters
25
    // --------------------------------------------------
26
    parameter SYMBOLS_PER_BEAT  = 1,
27
    parameter BITS_PER_SYMBOL   = 8,
28
    parameter FIFO_DEPTH        = 16,
29
    parameter CHANNEL_WIDTH     = 0,
30
    parameter ERROR_WIDTH       = 0,
31
    parameter USE_PACKETS       = 0,
32
    parameter USE_FILL_LEVEL    = 0,
33
    parameter USE_STORE_FORWARD = 0,
34
    parameter USE_ALMOST_FULL_IF = 0,
35
    parameter USE_ALMOST_EMPTY_IF = 0,
36
 
37
    // --------------------------------------------------
38
    // Empty latency is defined as the number of cycles
39
    // required for a write to deassert the empty flag.
40
    // For example, a latency of 1 means that the empty
41
    // flag is deasserted on the cycle after a write.
42
    //
43
    // Another way to think of it is the latency for a
44
    // write to propagate to the output. 
45
    // 
46
    // An empty latency of 0 implies lookahead, which is
47
    // only implemented for the register-based FIFO.
48
    // --------------------------------------------------
49
    parameter EMPTY_LATENCY     = 3,
50
    parameter USE_MEMORY_BLOCKS = 1,
51
 
52
    // --------------------------------------------------
53
    // Internal Parameters
54
    // --------------------------------------------------
55
    parameter DATA_WIDTH  = SYMBOLS_PER_BEAT * BITS_PER_SYMBOL,
56
    parameter EMPTY_WIDTH = log2ceil(SYMBOLS_PER_BEAT)
57
)
58
(
59
    // --------------------------------------------------
60
    // Ports
61
    // --------------------------------------------------
62
    input                       clk,
63
    input                       reset,
64
 
65
    input [DATA_WIDTH-1: 0]     in_data,
66
    input                       in_valid,
67
    input                       in_startofpacket,
68
    input                       in_endofpacket,
69
    input [((EMPTY_WIDTH>0) ? (EMPTY_WIDTH-1):0) : 0]     in_empty,
70
    input [((ERROR_WIDTH>0) ? (ERROR_WIDTH-1):0) : 0]     in_error,
71
    input [((CHANNEL_WIDTH>0) ? (CHANNEL_WIDTH-1):0): 0]  in_channel,
72
    output                      in_ready,
73
 
74
    output [DATA_WIDTH-1 : 0]   out_data,
75
    output reg                  out_valid,
76
    output                      out_startofpacket,
77
    output                      out_endofpacket,
78
    output [((EMPTY_WIDTH>0) ? (EMPTY_WIDTH-1):0) : 0]    out_empty,
79
    output [((ERROR_WIDTH>0) ? (ERROR_WIDTH-1):0) : 0]    out_error,
80
    output [((CHANNEL_WIDTH>0) ? (CHANNEL_WIDTH-1):0): 0] out_channel,
81
    input                       out_ready,
82
 
83
    input [(USE_STORE_FORWARD ? 2 : 1) : 0]   csr_address,
84
    input                       csr_write,
85
    input                       csr_read,
86
    input [31 : 0]              csr_writedata,
87
    output reg [31 : 0]         csr_readdata,
88
 
89
    output  wire                almost_full_data,
90
    output  wire                almost_empty_data
91
);
92
 
93
    // --------------------------------------------------
94
    // Local Parameters
95
    // --------------------------------------------------
96
    localparam ADDR_WIDTH   = log2ceil(FIFO_DEPTH);
97
    localparam DEPTH        = FIFO_DEPTH;
98
    localparam PKT_SIGNALS_WIDTH = 2 + EMPTY_WIDTH;
99
    localparam PAYLOAD_WIDTH     = (USE_PACKETS == 1) ?
100
                   2 + EMPTY_WIDTH + DATA_WIDTH + ERROR_WIDTH + CHANNEL_WIDTH:
101
                   DATA_WIDTH + ERROR_WIDTH + CHANNEL_WIDTH;
102
 
103
    // --------------------------------------------------
104
    // Internal Signals
105
    // --------------------------------------------------
106
    genvar i;
107
 
108
    reg [PAYLOAD_WIDTH-1 : 0] mem [DEPTH-1 : 0];
109
    reg [ADDR_WIDTH-1 : 0]  wr_ptr;
110
    reg [ADDR_WIDTH-1 : 0]  rd_ptr;
111
    reg [DEPTH-1      : 0]  mem_used;
112
 
113
    wire [ADDR_WIDTH-1 : 0] next_wr_ptr;
114
    wire [ADDR_WIDTH-1 : 0] next_rd_ptr;
115
    wire [ADDR_WIDTH-1 : 0] incremented_wr_ptr;
116
    wire [ADDR_WIDTH-1 : 0] incremented_rd_ptr;
117
 
118
    wire [ADDR_WIDTH-1 : 0] mem_rd_ptr;
119
 
120
    wire read;
121
    wire write;
122
 
123
    reg empty;
124
    reg next_empty;
125
    reg full;
126
    reg next_full;
127
 
128
    wire [PKT_SIGNALS_WIDTH-1 : 0] in_packet_signals;
129
    wire [PKT_SIGNALS_WIDTH-1 : 0] out_packet_signals;
130
    wire [PAYLOAD_WIDTH-1 : 0] in_payload;
131
    reg  [PAYLOAD_WIDTH-1 : 0] internal_out_payload;
132
    reg  [PAYLOAD_WIDTH-1 : 0] out_payload;
133
 
134
    reg  internal_out_valid;
135
    wire internal_out_ready;
136
 
137
    reg  [ADDR_WIDTH : 0] fifo_fill_level;
138
    reg  [ADDR_WIDTH : 0] fill_level;
139
 
140
    reg  [ADDR_WIDTH-1 : 0]   sop_ptr = 0;
141
    wire [ADDR_WIDTH-1 : 0]   curr_sop_ptr;
142
    reg  [23:0]   almost_full_threshold;
143
    reg  [23:0]   almost_empty_threshold;
144
    reg  [23:0]   cut_through_threshold;
145
    reg  [15:0]   pkt_cnt;
146
    reg           drop_on_error_en;
147
    reg           error_in_pkt;
148
    reg           pkt_has_started;
149
    reg           sop_has_left_fifo;
150
    reg           fifo_too_small_r;
151
    reg           pkt_cnt_eq_zero;
152
    reg           pkt_cnt_eq_one;
153
 
154
    wire          wait_for_threshold;
155
    reg           pkt_mode;
156
    wire          wait_for_pkt;
157
    wire          ok_to_forward;
158
    wire          in_pkt_eop_arrive;
159
    wire          out_pkt_leave;
160
    wire          in_pkt_start;
161
    wire          in_pkt_error;
162
    wire          drop_on_error;
163
    wire          fifo_too_small;
164
    wire          out_pkt_sop_leave;
165
    wire [31:0]   max_fifo_size;
166
    reg           fifo_fill_level_lt_cut_through_threshold;
167
 
168
    // --------------------------------------------------
169
    // Define Payload
170
    //
171
    // Icky part where we decide which signals form the
172
    // payload to the FIFO with generate blocks.
173
    // --------------------------------------------------
174
    generate
175
        if (EMPTY_WIDTH > 0) begin : gen_blk1
176
            assign in_packet_signals = {in_startofpacket, in_endofpacket, in_empty};
177
            assign {out_startofpacket, out_endofpacket, out_empty} = out_packet_signals;
178
        end
179
        else begin : gen_blk1_else
180
            assign out_empty = in_error;
181
            assign in_packet_signals = {in_startofpacket, in_endofpacket};
182
            assign {out_startofpacket, out_endofpacket} = out_packet_signals;
183
        end
184
    endgenerate
185
 
186
    generate
187
        if (USE_PACKETS) begin : gen_blk2
188
            if (ERROR_WIDTH > 0) begin : gen_blk3
189
                if (CHANNEL_WIDTH > 0) begin : gen_blk4
190
                    assign in_payload = {in_packet_signals, in_data, in_error, in_channel};
191
                    assign {out_packet_signals, out_data, out_error, out_channel} = out_payload;
192
                end
193
                else begin : gen_blk4_else
194
                    assign out_channel = in_channel;
195
                    assign in_payload = {in_packet_signals, in_data, in_error};
196
                    assign {out_packet_signals, out_data, out_error} = out_payload;
197
                end
198
            end
199
            else begin : gen_blk3_else
200
                assign out_error = in_error;
201
                if (CHANNEL_WIDTH > 0) begin : gen_blk5
202
                    assign in_payload = {in_packet_signals, in_data, in_channel};
203
                    assign {out_packet_signals, out_data, out_channel} = out_payload;
204
                end
205
                else begin : gen_blk5_else
206
                    assign out_channel = in_channel;
207
                    assign in_payload = {in_packet_signals, in_data};
208
                    assign {out_packet_signals, out_data} = out_payload;
209
                end
210
            end
211
        end
212
        else begin : gen_blk2_else
213
            assign out_packet_signals = 0;
214
            if (ERROR_WIDTH > 0) begin : gen_blk6
215
                if (CHANNEL_WIDTH > 0) begin : gen_blk7
216
                    assign in_payload = {in_data, in_error, in_channel};
217
                    assign {out_data, out_error, out_channel} = out_payload;
218
                end
219
                else begin : gen_blk7_else
220
                    assign out_channel = in_channel;
221
                    assign in_payload = {in_data, in_error};
222
                    assign {out_data, out_error} = out_payload;
223
                end
224
            end
225
            else begin : gen_blk6_else
226
                assign out_error = in_error;
227
                if (CHANNEL_WIDTH > 0) begin : gen_blk8
228
                    assign in_payload = {in_data, in_channel};
229
                    assign {out_data, out_channel} = out_payload;
230
                end
231
                else begin : gen_blk8_else
232
                    assign out_channel = in_channel;
233
                    assign in_payload = in_data;
234
                    assign out_data = out_payload;
235
                end
236
            end
237
        end
238
    endgenerate
239
 
240
    // --------------------------------------------------
241
    // Memory-based FIFO storage
242
    //
243
    // To allow a ready latency of 0, the read index is 
244
    // obtained from the next read pointer and memory 
245
    // outputs are unregistered.
246
    //
247
    // If the empty latency is 1, we infer bypass logic
248
    // around the memory so writes propagate to the
249
    // outputs on the next cycle.
250
    //
251
    // Do not change the way this is coded: Quartus needs
252
    // a perfect match to the template, and any attempt to 
253
    // refactor the two always blocks into one will break
254
    // memory inference.
255
    // --------------------------------------------------
256
    generate if (USE_MEMORY_BLOCKS == 1) begin  : gen_blk9
257
 
258
        if (EMPTY_LATENCY == 1) begin : gen_blk10
259
 
260
            always @(posedge clk) begin
261
                if (in_valid && in_ready)
262
                    mem[wr_ptr] = in_payload;
263
 
264
                internal_out_payload = mem[mem_rd_ptr];
265
            end
266
 
267
        end else begin : gen_blk10_else
268
 
269
            always @(posedge clk) begin
270
                if (in_valid && in_ready)
271
                    mem[wr_ptr] <= in_payload;
272
 
273
                internal_out_payload <= mem[mem_rd_ptr];
274
            end
275
 
276
        end
277
 
278
        assign mem_rd_ptr = next_rd_ptr;
279
 
280
    end else begin : gen_blk9_else
281
 
282
    // --------------------------------------------------
283
    // Register-based FIFO storage
284
    //
285
    // Uses a shift register as the storage element. Each
286
    // shift register slot has a bit which indicates if
287
    // the slot is occupied (credit to Sam H for the idea).
288
    // The occupancy bits are contiguous and start from the
289
    // lsb, so 0000, 0001, 0011, 0111, 1111 for a 4-deep
290
    // FIFO.
291
    // 
292
    // Each slot is enabled during a read or when it
293
    // is unoccupied. New data is always written to every
294
    // going-to-be-empty slot (we keep track of which ones
295
    // are actually useful with the occupancy bits). On a
296
    // read we shift occupied slots.
297
    // 
298
    // The exception is the last slot, which always gets 
299
    // new data when it is unoccupied.
300
    // --------------------------------------------------
301
        for (i = 0; i < DEPTH-1; i = i + 1) begin : shift_reg
302
            always @(posedge clk or posedge reset) begin
303
                if (reset) begin
304
                    mem[i] <= 0;
305
                end
306
                else if (read || !mem_used[i]) begin
307
                    if (!mem_used[i+1])
308
                        mem[i] <= in_payload;
309
                    else
310
                        mem[i] <= mem[i+1];
311
                end
312
            end
313
        end
314
 
315
        always @(posedge clk, posedge reset) begin
316
            if (reset) begin
317
                mem[DEPTH-1] <= 0;
318
            end
319
            else begin
320
                if (DEPTH == 1) begin
321
                    if (write)
322
                        mem[DEPTH-1] <= in_payload;
323
                end
324
                else if (!mem_used[DEPTH-1])
325
                    mem[DEPTH-1] <= in_payload;
326
            end
327
        end
328
 
329
    end
330
    endgenerate
331
 
332
    assign read  = internal_out_ready && internal_out_valid  && ok_to_forward;
333
    assign write = in_ready && in_valid;
334
 
335
    // --------------------------------------------------
336
    // Pointer Management
337
    // --------------------------------------------------
338
    generate if (USE_MEMORY_BLOCKS == 1) begin : gen_blk11
339
 
340
        assign incremented_wr_ptr = wr_ptr + 1'b1;
341
        assign incremented_rd_ptr = rd_ptr + 1'b1;
342
        assign next_wr_ptr =  drop_on_error ? curr_sop_ptr : write ?  incremented_wr_ptr : wr_ptr;
343
        assign next_rd_ptr = (read) ? incremented_rd_ptr : rd_ptr;
344
 
345
        always @(posedge clk or posedge reset) begin
346
            if (reset) begin
347
                wr_ptr <= 0;
348
                rd_ptr <= 0;
349
            end
350
            else begin
351
                wr_ptr <= next_wr_ptr;
352
                rd_ptr <= next_rd_ptr;
353
            end
354
        end
355
 
356
    end else begin : gen_blk11_else
357
 
358
    // --------------------------------------------------
359
    // Shift Register Occupancy Bits
360
    //
361
    // Consider a 4-deep FIFO with 2 entries: 0011
362
    // On a read and write, do not modify the bits.
363
    // On a write, left-shift the bits to get 0111.
364
    // On a read, right-shift the bits to get 0001.
365
    //
366
    // Also, on a write we set bit0 (the head), while
367
    // clearing the tail on a read.
368
    // --------------------------------------------------
369
        always @(posedge clk or posedge reset) begin
370
            if (reset) begin
371
                mem_used[0] <= 0;
372
            end
373
            else begin
374
                if (write ^ read) begin
375
                    if (write)
376
                        mem_used[0] <= 1;
377
                    else if (read) begin
378
                        if (DEPTH > 1)
379
                            mem_used[0] <= mem_used[1];
380
                        else
381
                            mem_used[0] <= 0;
382
                    end
383
                end
384
            end
385
        end
386
 
387
        if (DEPTH > 1) begin : gen_blk12
388
            always @(posedge clk or posedge reset) begin
389
                if (reset) begin
390
                    mem_used[DEPTH-1] <= 0;
391
                end
392
                else begin
393
                    if (write ^ read) begin
394
                        mem_used[DEPTH-1] <= 0;
395
                        if (write)
396
                            mem_used[DEPTH-1] <= mem_used[DEPTH-2];
397
                    end
398
                end
399
            end
400
          end
401
 
402
        for (i = 1; i < DEPTH-1; i = i + 1) begin : storage_logic
403
            always @(posedge clk, posedge reset) begin
404
                if (reset) begin
405
                    mem_used[i] <= 0;
406
                end
407
                else begin
408
                    if (write ^ read) begin
409
                        if (write)
410
                            mem_used[i] <= mem_used[i-1];
411
                        else if (read)
412
                            mem_used[i] <= mem_used[i+1];
413
                    end
414
                end
415
            end
416
        end
417
 
418
    end
419
    endgenerate
420
 
421
 
422
    // --------------------------------------------------
423
    // Memory FIFO Status Management
424
    //
425
    // Generates the full and empty signals from the
426
    // pointers. The FIFO is full when the next write 
427
    // pointer will be equal to the read pointer after
428
    // a write. Reading from a FIFO clears full.
429
    //
430
    // The FIFO is empty when the next read pointer will
431
    // be equal to the write pointer after a read. Writing
432
    // to a FIFO clears empty.
433
    //
434
    // A simultaneous read and write must not change any of 
435
    // the empty or full flags unless there is a drop on error event.
436
    // --------------------------------------------------
437
    generate if (USE_MEMORY_BLOCKS == 1) begin : gen_blk13
438
 
439
        always @* begin
440
            next_full = full;
441
            next_empty = empty;
442
 
443
            if (read && !write) begin
444
                next_full = 1'b0;
445
 
446
                if (incremented_rd_ptr == wr_ptr)
447
                    next_empty = 1'b1;
448
            end
449
 
450
            if (write && !read) begin
451
                if (!drop_on_error)
452
                  next_empty = 1'b0;
453
                else if (curr_sop_ptr == rd_ptr)   // drop on error and only 1 pkt in fifo
454
                  next_empty = 1'b1;
455
 
456
                if (incremented_wr_ptr == rd_ptr && !drop_on_error)
457
                    next_full = 1'b1;
458
            end
459
 
460
            if (write && read && drop_on_error) begin
461
                if (curr_sop_ptr == next_rd_ptr)
462
                  next_empty = 1'b1;
463
            end
464
        end
465
 
466
        always @(posedge clk or posedge reset) begin
467
            if (reset) begin
468
                empty <= 1;
469
                full  <= 0;
470
            end
471
            else begin
472
                empty <= next_empty;
473
                full  <= next_full;
474
            end
475
        end
476
 
477
    end else begin : gen_blk13_else
478
    // --------------------------------------------------
479
    // Register FIFO Status Management
480
    //
481
    // Full when the tail occupancy bit is 1. Empty when
482
    // the head occupancy bit is 0.
483
    // --------------------------------------------------
484
        always @* begin
485
            full  = mem_used[DEPTH-1];
486
            empty = !mem_used[0];
487
 
488
            // ------------------------------------------
489
            // For a single slot FIFO, reading clears the
490
            // full status immediately.
491
            // ------------------------------------------
492
            if (DEPTH == 1)
493
                full = mem_used[0] && !read;
494
 
495
            internal_out_payload = mem[0];
496
 
497
            // ------------------------------------------
498
            // Writes clear empty immediately for lookahead modes.
499
            // Note that we use in_valid instead of write to avoid
500
            // combinational loops (in lookahead mode, qualifying
501
            // with in_ready is meaningless).
502
            //
503
            // In a 1-deep FIFO, a possible combinational loop runs
504
            // from write -> out_valid -> out_ready -> write
505
            // ------------------------------------------
506
            if (EMPTY_LATENCY == 0) begin
507
                empty = !mem_used[0] && !in_valid;
508
 
509
                if (!mem_used[0] && in_valid)
510
                    internal_out_payload = in_payload;
511
            end
512
        end
513
 
514
    end
515
    endgenerate
516
 
517
    // --------------------------------------------------
518
    // Avalon-ST Signals
519
    //
520
    // The in_ready signal is straightforward. 
521
    //
522
    // To match memory latency when empty latency > 1, 
523
    // out_valid assertions must be delayed by one clock
524
    // cycle.
525
    //
526
    // Note: out_valid deassertions must not be delayed or 
527
    // the FIFO will underflow.
528
    // --------------------------------------------------
529
    assign in_ready = !full;
530
    assign internal_out_ready = out_ready || !out_valid;
531
 
532
    generate if (EMPTY_LATENCY > 1) begin : gen_blk14
533
        always @(posedge clk or posedge reset) begin
534
            if (reset)
535
                internal_out_valid <= 0;
536
            else begin
537
                internal_out_valid <= !empty & ok_to_forward & ~drop_on_error;
538
 
539
                if (read) begin
540
                    if (incremented_rd_ptr == wr_ptr)
541
                        internal_out_valid <= 1'b0;
542
                end
543
            end
544
        end
545
    end else begin : gen_blk14_else
546
        always @* begin
547
            internal_out_valid = !empty & ok_to_forward;
548
        end
549
    end
550
    endgenerate
551
 
552
    // --------------------------------------------------
553
    // Single Output Pipeline Stage
554
    //
555
    // This output pipeline stage is enabled if the FIFO's 
556
    // empty latency is set to 3 (default). It is disabled
557
    // for all other allowed latencies.
558
    //
559
    // Reason: The memory outputs are unregistered, so we have to
560
    // register the output or fmax will drop if combinatorial
561
    // logic is present on the output datapath.
562
    // 
563
    // Q: The Avalon-ST spec says that I have to register my outputs
564
    //    But isn't the memory counted as a register?
565
    // A: The path from the address lookup to the memory output is
566
    //    slow. Registering the memory outputs is a good idea. 
567
    //
568
    // The registers get packed into the memory by the fitter
569
    // which means minimal resources are consumed (the result
570
    // is a altsyncram with registered outputs, available on 
571
    // all modern Altera devices). 
572
    //
573
    // This output stage acts as an extra slot in the FIFO, 
574
    // and complicates the fill level.
575
    // --------------------------------------------------
576
    generate if (EMPTY_LATENCY == 3) begin : gen_blk15
577
        always @(posedge clk or posedge reset) begin
578
            if (reset) begin
579
                out_valid   <= 0;
580
                out_payload <= 0;
581
            end
582
            else begin
583
                if (internal_out_ready) begin
584
                    out_valid   <= internal_out_valid & ok_to_forward;
585
                    out_payload <= internal_out_payload;
586
                end
587
            end
588
        end
589
    end
590
    else begin : gen_blk15_else
591
        always @* begin
592
            out_valid   = internal_out_valid;
593
            out_payload = internal_out_payload;
594
        end
595
    end
596
    endgenerate
597
 
598
    // --------------------------------------------------
599
    // Fill Level
600
    //
601
    // The fill level is calculated from the next write
602
    // and read pointers to avoid unnecessary latency
603
    // and logic.
604
    //
605
    // However, if the store-and-forward mode of the FIFO
606
    // is enabled, the fill level is an up-down counter
607
    // for fmax optimization reasons.
608
    //
609
    // If the output pipeline is enabled, the fill level 
610
    // must account for it, or we'll always be off by one.
611
    // This may, or may not be important depending on the
612
    // application.
613
    //
614
    // For now, we'll always calculate the exact fill level
615
    // at the cost of an extra adder when the output stage
616
    // is enabled.
617
    // --------------------------------------------------
618
    generate if (USE_FILL_LEVEL) begin : gen_blk16
619
        wire [31:0] depth32;
620
        assign depth32 = DEPTH;
621
 
622
        if (USE_STORE_FORWARD) begin
623
 
624
            reg [ADDR_WIDTH : 0] curr_packet_len_less_one;
625
 
626
            // --------------------------------------------------
627
            // We only drop on endofpacket. As long as we don't add to the fill
628
            // level on the dropped endofpacket cycle, we can simply subtract
629
            // (packet length - 1) from the fill level for dropped packets.
630
            // --------------------------------------------------
631
            always @(posedge clk or posedge reset) begin
632
                if (reset) begin
633
                    curr_packet_len_less_one <= 0;
634
                end else begin
635
                    if (write) begin
636
                        curr_packet_len_less_one <= curr_packet_len_less_one + 1'b1;
637
                        if (in_endofpacket)
638
                            curr_packet_len_less_one <= 0;
639
                    end
640
                end
641
            end
642
 
643
            always @(posedge clk or posedge reset) begin
644
                if (reset) begin
645
                    fifo_fill_level <= 0;
646
                end else if (drop_on_error) begin
647
                    fifo_fill_level <= fifo_fill_level - curr_packet_len_less_one;
648
                    if (read)
649
                        fifo_fill_level <= fifo_fill_level - curr_packet_len_less_one - 1'b1;
650
                end else if (write && !read) begin
651
                    fifo_fill_level <= fifo_fill_level + 1'b1;
652
                end else if (read && !write) begin
653
                    fifo_fill_level <= fifo_fill_level - 1'b1;
654
                end
655
            end
656
 
657
        end else begin
658
 
659
            always @(posedge clk or posedge reset) begin
660
                if (reset)
661
                    fifo_fill_level <= 0;
662
                else if (next_full & !drop_on_error)
663
                    fifo_fill_level <= depth32[ADDR_WIDTH:0];
664
                else begin
665
                    fifo_fill_level[ADDR_WIDTH]     <= 1'b0;
666
                    fifo_fill_level[ADDR_WIDTH-1 : 0] <= next_wr_ptr - next_rd_ptr;
667
                end
668
            end
669
 
670
        end
671
 
672
        always @* begin
673
            fill_level = fifo_fill_level;
674
 
675
            if (EMPTY_LATENCY == 3)
676
                fill_level = fifo_fill_level + {{ADDR_WIDTH{1'b0}}, out_valid};
677
        end
678
    end
679
    else begin : gen_blk16_else
680
        always @* begin
681
            fill_level = 0;
682
        end
683
    end
684
    endgenerate
685
 
686
    generate if (USE_ALMOST_FULL_IF) begin : gen_blk17
687
      assign almost_full_data = (fill_level >= almost_full_threshold);
688
    end
689
    else
690
      assign almost_full_data = 0;
691
    endgenerate
692
 
693
    generate if (USE_ALMOST_EMPTY_IF) begin : gen_blk18
694
      assign almost_empty_data = (fill_level <= almost_empty_threshold);
695
    end
696
    else
697
      assign almost_empty_data = 0;
698
    endgenerate
699
 
700
    // --------------------------------------------------
701
    // Avalon-MM Status & Control Connection Point
702
    //
703
    // Register map:
704
    //
705
    // | Addr   | RW |     31 - 0      |
706
    // |  0     | R  |   Fill level    |
707
    //
708
    // The registering of this connection point means
709
    // that there is a cycle of latency between 
710
    // reads/writes and the updating of the fill level.
711
    // --------------------------------------------------
712
    generate if (USE_STORE_FORWARD) begin : gen_blk19
713
    assign max_fifo_size = FIFO_DEPTH - 1;
714
      always @(posedge clk or posedge reset) begin
715
          if (reset) begin
716
              almost_full_threshold  <= max_fifo_size[23 : 0];
717
              almost_empty_threshold <= 0;
718
              cut_through_threshold  <= 0;
719
              drop_on_error_en       <= 0;
720
              csr_readdata           <= 0;
721
              pkt_mode               <= 1'b1;
722
          end
723
          else begin
724
              if (csr_read) begin
725
                csr_readdata <= 32'b0;
726
                if (csr_address == 5)
727
                    csr_readdata <= {31'b0, drop_on_error_en};
728
                else if (csr_address == 4)
729
                    csr_readdata <= {8'b0, cut_through_threshold};
730
                else if (csr_address == 3)
731
                    csr_readdata <= {8'b0, almost_empty_threshold};
732
                else if (csr_address == 2)
733
                    csr_readdata <= {8'b0, almost_full_threshold};
734
                else if (csr_address == 0)
735
                    csr_readdata <= {{(31 - ADDR_WIDTH){1'b0}}, fill_level};
736
             end
737
             else if (csr_write) begin
738
               if(csr_address == 3'b101)
739
                   drop_on_error_en       <= csr_writedata[0];
740
               else if(csr_address == 3'b100) begin
741
                   cut_through_threshold  <= csr_writedata[23:0];
742
                   pkt_mode <= (csr_writedata[23:0] == 0);
743
               end
744
               else if(csr_address == 3'b011)
745
                    almost_empty_threshold <= csr_writedata[23:0];
746
               else if(csr_address == 3'b010)
747
                  almost_full_threshold  <= csr_writedata[23:0];
748
             end
749
          end
750
      end
751
    end
752
    else if (USE_ALMOST_FULL_IF || USE_ALMOST_EMPTY_IF) begin : gen_blk19_else1
753
    assign max_fifo_size = FIFO_DEPTH - 1;
754
      always @(posedge clk or posedge reset) begin
755
          if (reset) begin
756
              almost_full_threshold  <= max_fifo_size[23 : 0];
757
              almost_empty_threshold <= 0;
758
              csr_readdata           <= 0;
759
          end
760
          else begin
761
             if (csr_read) begin
762
                csr_readdata <= 32'b0;
763
                if (csr_address == 3)
764
                    csr_readdata <= {8'b0, almost_empty_threshold};
765
                else if (csr_address == 2)
766
                    csr_readdata <= {8'b0, almost_full_threshold};
767
                else if (csr_address == 0)
768
                    csr_readdata <= {{(31 - ADDR_WIDTH){1'b0}}, fill_level};
769
             end
770
             else if (csr_write) begin
771
               if(csr_address == 3'b011)
772
                   almost_empty_threshold <= csr_writedata[23:0];
773
               else if(csr_address == 3'b010)
774
                  almost_full_threshold  <= csr_writedata[23:0];
775
             end
776
          end
777
      end
778
    end
779
    else begin : gen_blk19_else2
780
      always @(posedge clk or posedge reset) begin
781
          if (reset) begin
782
              csr_readdata <= 0;
783
          end
784
          else if (csr_read) begin
785
              csr_readdata <= 0;
786
 
787
              if (csr_address == 0)
788
                  csr_readdata <= {{(31 - ADDR_WIDTH){1'b0}}, fill_level};
789
          end
790
      end
791
    end
792
    endgenerate
793
 
794
    // --------------------------------------------------
795
    // Store and forward logic
796
    // --------------------------------------------------
797
    // if the fifo gets full before the entire packet or the
798
    // cut-threshold condition is met then start sending out
799
    // data in order to avoid dead-lock situation
800
 
801
    generate if (USE_STORE_FORWARD) begin : gen_blk20
802
      assign wait_for_threshold   = (fifo_fill_level_lt_cut_through_threshold) & wait_for_pkt ;
803
      assign wait_for_pkt         = pkt_cnt_eq_zero  | (pkt_cnt_eq_one  & out_pkt_leave);
804
      assign ok_to_forward        = (pkt_mode ? (~wait_for_pkt | ~pkt_has_started) :
805
                                     ~wait_for_threshold) | fifo_too_small_r;
806
      assign in_pkt_eop_arrive    = in_valid & in_ready & in_endofpacket;
807
      assign in_pkt_start         = in_valid & in_ready & in_startofpacket;
808
      assign in_pkt_error         = in_valid & in_ready & |in_error;
809
      assign out_pkt_sop_leave    = out_valid & out_ready & out_startofpacket;
810
      assign out_pkt_leave        = out_valid & out_ready & out_endofpacket;
811
      assign fifo_too_small       = (pkt_mode ? wait_for_pkt : wait_for_threshold) & full & out_ready;
812
 
813
      // count packets coming and going into the fifo
814
      always @(posedge clk or posedge reset) begin
815
        if (reset) begin
816
          pkt_cnt           <= 0;
817
          pkt_has_started   <= 0;
818
          sop_has_left_fifo <= 0;
819
          fifo_too_small_r  <= 0;
820
          pkt_cnt_eq_zero   <= 1'b1;
821
          pkt_cnt_eq_one    <= 1'b0;
822
          fifo_fill_level_lt_cut_through_threshold <= 1'b1;
823
        end
824
        else begin
825
          fifo_fill_level_lt_cut_through_threshold <= fifo_fill_level < cut_through_threshold;
826
          fifo_too_small_r <= fifo_too_small;
827
 
828
          if( in_pkt_eop_arrive )
829
            sop_has_left_fifo <= 1'b0;
830
          else if (out_pkt_sop_leave & pkt_cnt_eq_zero )
831
            sop_has_left_fifo <= 1'b1;
832
 
833
          if (in_pkt_eop_arrive & ~out_pkt_leave & ~drop_on_error ) begin
834
            pkt_cnt <= pkt_cnt + 1'b1;
835
            pkt_cnt_eq_zero <= 0;
836
            if (pkt_cnt == 0)
837
              pkt_cnt_eq_one <= 1'b1;
838
            else
839
              pkt_cnt_eq_one <= 1'b0;
840
          end
841
          else if((~in_pkt_eop_arrive | drop_on_error) & out_pkt_leave) begin
842
            pkt_cnt <= pkt_cnt - 1'b1;
843
            if (pkt_cnt == 1)
844
              pkt_cnt_eq_zero <= 1'b1;
845
            else
846
              pkt_cnt_eq_zero <= 1'b0;
847
            if (pkt_cnt == 2)
848
              pkt_cnt_eq_one <= 1'b1;
849
            else
850
              pkt_cnt_eq_one <= 1'b0;
851
          end
852
 
853
          if (in_pkt_start)
854
            pkt_has_started <= 1'b1;
855
          else if (in_pkt_eop_arrive)
856
            pkt_has_started <= 1'b0;
857
        end
858
      end
859
 
860
      // drop on error logic
861
      always @(posedge clk or posedge reset) begin
862
        if (reset) begin
863
          sop_ptr <= 0;
864
          error_in_pkt <= 0;
865
        end
866
        else begin
867
          // save the location of the SOP
868
          if ( in_pkt_start )
869
            sop_ptr <= wr_ptr;
870
 
871
          // remember if error in pkt
872
          // log error only if packet has already started
873
          if (in_pkt_eop_arrive)
874
            error_in_pkt <= 1'b0;
875
          else if ( in_pkt_error & (pkt_has_started | in_pkt_start))
876
            error_in_pkt <= 1'b1;
877
        end
878
      end
879
 
880
      assign drop_on_error = drop_on_error_en & (error_in_pkt | in_pkt_error) & in_pkt_eop_arrive &
881
                            ~sop_has_left_fifo & ~(out_pkt_sop_leave & pkt_cnt_eq_zero);
882
 
883
      assign curr_sop_ptr = (write && in_startofpacket && in_endofpacket) ? wr_ptr : sop_ptr;
884
 
885
    end
886
    else begin : gen_blk20_else
887
      assign ok_to_forward = 1'b1;
888
      assign drop_on_error = 1'b0;
889
      if (ADDR_WIDTH <= 1)
890
        assign curr_sop_ptr = 1'b0;
891
      else
892
        assign curr_sop_ptr = {ADDR_WIDTH - 1 { 1'b0 }};
893
    end
894
    endgenerate
895
 
896
 
897
    // --------------------------------------------------
898
    // Calculates the log2ceil of the input value
899
    // --------------------------------------------------
900
    function integer log2ceil;
901
        input integer val;
902
        reg[31:0] i;
903
 
904
        begin
905
            i = 1;
906
            log2ceil = 0;
907
 
908
            while (i < val) begin
909
                log2ceil = log2ceil + 1;
910
                i = i[30:0] << 1;
911
            end
912
        end
913
    endfunction
914
 
915
endmodule

powered by: WebSVN 2.1.0

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