File size: 1,536 Bytes
2b4ae64
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
`timescale 1ns/1ps
// Reference implementation: parameterized ring buffer (circular FIFO)
module ring_buffer #(
    parameter DEPTH  = 8,
    parameter DATA_W = 8
) (
    input  wire              clk,
    input  wire              rst,
    input  wire              push,
    input  wire [DATA_W-1:0] push_data,
    input  wire              pop,
    output wire [DATA_W-1:0] pop_data,
    output wire              full,
    output wire              empty,
    output wire [$clog2(DEPTH):0] count
);
    localparam PTR_W = $clog2(DEPTH);

    reg [DATA_W-1:0] mem  [0:DEPTH-1];
    reg [PTR_W-1:0]  head, tail;
    reg [PTR_W:0]    cnt;

    assign full     = (cnt == DEPTH);
    assign empty    = (cnt == 0);
    assign count    = cnt;
    assign pop_data = mem[head];

    wire do_push = push & ~full;
    wire do_pop  = pop  & ~empty;

    always @(posedge clk) begin
        if (rst) begin
            head <= {PTR_W{1'b0}};
            tail <= {PTR_W{1'b0}};
            cnt  <= {(PTR_W+1){1'b0}};
        end else begin
            if (do_push) begin
                mem[tail] <= push_data;
                tail      <= (tail == DEPTH-1) ? {PTR_W{1'b0}} : tail + 1'b1;
            end
            if (do_pop)
                head <= (head == DEPTH-1) ? {PTR_W{1'b0}} : head + 1'b1;
            // Explicit case split avoids synthesis warning on subtraction
            if (do_push & ~do_pop)
                cnt <= cnt + 1'b1;
            else if (do_pop & ~do_push)
                cnt <= cnt - 1'b1;
        end
    end

endmodule