Skip to content

Instantly share code, notes, and snippets.

@ktbarrett
Last active October 18, 2018 03:54
Show Gist options
  • Save ktbarrett/6d662ae2cb8d7d486896a990aeda8baa to your computer and use it in GitHub Desktop.
Save ktbarrett/6d662ae2cb8d7d486896a990aeda8baa to your computer and use it in GitHub Desktop.
Synchronous FIFO implementation
`timescale 1ns / 1ps
`default_nettype none
module fifo #(
parameter WIDTH = 32,
parameter DEPTH = 1024,
parameter SKID = 0,
parameter GEN_EXCEPTIONS = 1,
parameter GEN_CONSENTS = 1
)(
input wire clk,
input wire rst,
input wire [WIDTH-1:0] wrData,
output reg [WIDTH-1:0] rdData,
input wire rdEn,
input wire wrEn,
output reg rdConsent,
output reg wrConsent,
output reg oflow,
output reg uflow
);
reg [WIDTH-1:0] buff[0:DEPTH-1];
reg [$clog2(DEPTH+1)-1:0] wr_ptr, rd_ptr;
integer i;
initial begin
for (i = 0; i < DEPTH; i = i + 1) begin
buff[i] = 0;
end
end
// updates read and write pointers on enable
always @(posedge clk, posedge rst) begin
if (rst) begin
wr_ptr <= 0;
rd_ptr <= 0;
end else begin
if (wrEn) begin
wr_ptr <= wr_ptr + 1;
end
if (rdEn) begin
rd_ptr <= rd_ptr + 1;
end
end
end
reg [$clog2(DEPTH+1)-1:0] cnt;
reg empty, full;
// calculate full and empty, which are used by both the consents and exceptions
generate if (GEN_CONSENTS || GEN_EXCEPTIONS) begin
always @* begin
cnt = wr_ptr - rd_ptr;
full = cnt >= (DEPTH - SKID);
empty = cnt == 0;
end
end endgenerate
// calculate read and write consents based on full and empty
generate if (GEN_CONSENTS) begin
always @(posedge clk) begin
rdConsent <= !empty;
wrConsent <= !full;
end
end else begin
initial begin
rdConsent <= 1;
wrConsent <= 1;
end
end endgenerate
// calculate overflow and underflow using full and empty
generate if (GEN_EXCEPTIONS) begin
always @(posedge clk, posedge rst) begin
if (rst) begin
oflow <= 0;
uflow <= 0;
end else begin
if (full && wrEn && !rdEn) begin
oflow <= 1;
end
if (empty && rdEn) begin
uflow <= 1;
end
end
end
end else begin
initial begin
uflow <= 1;
oflow <= 1;
end
end endgenerate
// update and read values from RAM when enabled
always @(posedge clk) begin
if (rdEn) begin
rdData <= buff[(rd_ptr+1) % DEPTH];
end else begin
rdData <= buff[rd_ptr % DEPTH];
end
if (wrEn) begin
buff[wr_ptr % DEPTH] <= wrData;
end
end
endmodule
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment