Last active
October 18, 2018 03:54
-
-
Save ktbarrett/6d662ae2cb8d7d486896a990aeda8baa to your computer and use it in GitHub Desktop.
Synchronous FIFO implementation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
`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