Spaces:
Running
Running
| // 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 | |