blob: a76fcd4f1a5a2ea5abcabadd5b5cc4e162e5a9dd [file] [log] [blame]
(*keep_hierarchy = "yes"*) module FIFO
#(
parameter WORD_SIZE = 8,
parameter BUFFER_SIZE = 256 // If this is not a power of two, the actual buffer size will be the smallest power of two greater than BUFFER_SIZE
)(
input wire clk,
input wire rst,
input wire [WORD_SIZE-1:0] data_in,
input wire we,
output wire [WORD_SIZE-1:0] data_out,
input wire oe,
output wire isData,
output wire bufferFull
);
localparam ADDRESS_SIZE = $clog2(BUFFER_SIZE);
localparam DEPTH = 1 << ADDRESS_SIZE;
reg we_buffered = 1'b0;
reg oe_buffered = 1'b0;
reg [WORD_SIZE-1:0] data_in_buffered = 'b0;
reg [ADDRESS_SIZE-1:0] startPointer = 'b0;
reg [ADDRESS_SIZE-1:0] endPointer = 'b0;
reg [WORD_SIZE-1:0] buffer [DEPTH-1:0];
assign isData = startPointer != endPointer;
always @(posedge clk) begin
if (rst) begin
we_buffered <= 1'b0;
oe_buffered <= 1'b0;
data_in_buffered <= 'b0;
end else begin
we_buffered <= we;
oe_buffered <= oe;
data_in_buffered <= data_in;
end
end
assign bufferFull = endPointer + 1 == startPointer;
always @(negedge clk) begin
if (rst) begin
startPointer = 'b0;
endPointer = 'b0;
end else begin
// Update start pointer first, so that if the buffer is full and we try to write,
// it will still work if we are also reading on this update
if (oe_buffered) begin
if (startPointer != endPointer) begin
startPointer = startPointer + 1;
end
end
if (we_buffered) begin
// TODO: Should we allow the buffer to overwrite itself when a write occurs and it is already full
if (endPointer + 1 != startPointer) begin
buffer[endPointer] = data_in_buffered;
endPointer = endPointer + 1;
end
end
end
end
assign data_out = buffer[startPointer];
endmodule