This example describes a synthesizable implementation of a FIFO. The FIFO depth and FIFO width in bits can be modified by simply changing the value of two parameters, `FWIDTH and `FDEPTH. For this example, the FIFO depth is 4 and the FIFO width is 32 bits. The input/output ports of the FIFO are shown in Figure F-1.
Figure F-1. FIFO Input/Output Ports
All ports with a suffix "N" are low-asserted.
Clk— Clock signal
RstN— Reset signal
Data_In— 32-bit data into the FIFO
FInN— Write into FIFO signal
FClrN— Clear signal to FIFO
FOutN— Read from FIFO signal
F_Data— 32-bit output data from FIFO
F_FullN— Signal indicating that FIFO is full
F_EmptyN— Signal indicating that FIFO is empty
F_LastN— Signal indicating that FIFO has space for one data value
F_SLastN— Signal indicating that FIFO has space for two data values
F_FirstN— Signal indicating that there is only one data value in FIFO
The Verilog HDL code for the FIFO implementation is shown in Example F-1.
////////////////////////////////////////////////////////////////////
// FileName:"Fifo.v"
// Author:Venkata Ramana Kalapatapu
// Company :Sand Microelectronics Inc.
//(now a part of Synopsys, Inc.),
// Profile :Sand develops Simulation Models, Synthesizable Cores and
//Performance Analysis Tools for Processors, buses and
//memory products.Sand's products include models for
//industry-standard components and custom-developed models
//for specific simulation environments.
//
////////////////////////////////////////////////////////////////////
`defineFWIDTH32// Width of the FIFO.
`defineFDEPTH4// Depth of the FIFO.
`defineFCWIDTH2// Counter Width of the FIFO 2 to power
// FCWIDTH = FDEPTH.
module FIFO(Clk,
RstN,
Data_In,
FClrN,
FInN,
FOutN,
F_Data,
F_FullN,
F_LastN,
F_SLastN,
F_FirstN,
F_EmptyN
);
inputClk;// CLK signal.
inputRstN;// Low Asserted Reset signal.
input [(`FWIDTH-1):0]Data_In;// Data into FIFO.
inputFInN;// Write into FIFO Signal.
inputFClrN;// Clear signal to FIFO.
inputFOutN;// Read from FIFO signal.
output [(`FWIDTH-1):0]F_Data;// FIFO data out.
outputF_FullN;// FIFO full indicating signal.
outputF_EmptyN; // FIFO empty indicating signal.
outputF_LastN;// FIFO Last but one signal.
outputF_SLastN; // FIFO SLast but one signal.
outputF_FirstN; // Signal indicating only one
// word in FIFO.
regF_FullN;
regF_EmptyN;
regF_LastN;
regF_SLastN;
regF_FirstN;
reg[`FCWIDTH:0]fcounter; //counter indicates num of data in FIFO
reg[(`FCWIDTH-1):0]rd_ptr;// Current read pointer.
reg[(`FCWIDTH-1):0]wr_ptr;// Current write pointer.
wire[(`FWIDTH-1):0]FIFODataOut; // Data out from FIFO MemBlk
wire[(`FWIDTH-1):0]FIFODataIn;// Data into FIFO MemBlk
wireReadN= FOutN;
wireWriteN = FInN;
assign F_Data= FIFODataOut;
assign FIFODataIn = Data_In;
FIFO_MEM_BLK memblk(.clk(Clk),
.writeN(WriteN),
.rd_addr(rd_ptr),
.wr_addr(wr_ptr),
.data_in(FIFODataIn),
.data_out(FIFODataOut)
);
// Control circuitry for FIFO. If reset or clr signal is asserted,
// all the counters are set to 0. If write only the write counter
// is incremented else if read only read counter is incremented
// else if both, read and write counters are incremented.
// fcounter indicates the num of items in the FIFO. Write only
// increments the fcounter, read only decrements the counter, and
// read && write doesn't change the counter value.
always @(posedge Clk or negedge RstN)
begin
if(!RstN) begin
fcounter<= 0;
rd_ptr<= 0;
wr_ptr<= 0;
end
else begin
if(!FClrN ) begin
fcounter<= 0;
rd_ptr<= 0;
wr_ptr<= 0;
end
else begin
if(!WriteN && F_FullN)
wr_ptr <= wr_ptr + 1;
if(!ReadN && F_EmptyN)
rd_ptr <= rd_ptr + 1;
if(!WriteN && ReadN && F_FullN)
fcounter <= fcounter + 1;
else if(WriteN && !ReadN && F_EmptyN)
fcounter <= fcounter - 1;
end
end
end
// All the FIFO status signals depends on the value of fcounter.
// If the fcounter is equal to fdepth, indicates FIFO is full.
// If the fcounter is equal to zero, indicates the FIFO is empty.
// F_EmptyN signal indicates FIFO Empty Status. By default it is
// asserted, indicating the FIFO is empty. After the First Data is
// put into the FIFO the signal is deasserted.
always @(posedge Clk or negedge RstN)
begin
if(!RstN)
F_EmptyN <= 1'b0;
else begin
if(FClrN==1'b1) begin
if(F_EmptyN==1'b0 && WriteN==1'b0)
F_EmptyN <= 1'b1;
else if(F_FirstN==1'b0 && ReadN==1'b0 && WriteN==1'b1)
F_EmptyN <= 1'b0;
end
else
F_EmptyN <= 1'b0;
end
end
// F_FirstN signal indicates that there is only one datum sitting
// in the FIFO. When the FIFO is empty and a write to FIFO occurs,
// this signal gets asserted.
always @(posedge Clk or negedge RstN)
begin
if(!RstN)
F_FirstN <= 1'b1;
else begin
if(FClrN==1'b1) begin
if((F_EmptyN==1'b0 && WriteN==1'b0) ||
(fcounter==2 && ReadN==1'b0 && WriteN==1'b1))
F_FirstN <= 1'b0;
else if (F_FirstN==1'b0 && (WriteN ^ ReadN))
F_FirstN <= 1'b1;
end
else begin
F_FirstN <= 1'b1;
end
end
end
// F_SLastN indicates that there is space for only two data words
//in the FIFO.
always @(posedge Clk or negedge RstN)
begin
if(!RstN)
F_SLastN <= 1'b1;
else begin
if(FClrN==1'b1) begin
if( (F_LastN==1'b0 && ReadN==1'b0 && WriteN==1'b1) ||
(fcounter == (`FDEPTH-3) && WriteN==1'b0 && ReadN==1'b1))
F_SLastN <= 1'b0;
else if(F_SLastN==1'b0 && (ReadN ^ WriteN) )
F_SLastN <= 1'b1;
end
else
F_SLastN <= 1'b1;
end
end
// F_LastN indicates that there is one space for only one data
// word in the FIFO.
always @(posedge Clk or negedge RstN)
begin
if(!RstN)
F_LastN <= 1'b1;
else begin
if(FClrN==1'b1) begin
if ((F_FullN==1'b0 && ReadN==1'b0)||
(fcounter == (`FDEPTH-2) && WriteN==1'b0 && ReadN==1'b1))
F_LastN <= 1'b0;
else if(F_LastN==1'b0 && (ReadN ^ WriteN) )
F_LastN <= 1'b1;
end
else
F_LastN <= 1'b1;
end
end
// F_FullN indicates that the FIFO is full.
always @(posedge Clk or negedge RstN)
begin
if(!RstN)
F_FullN <= 1'b1;
else begin
if(FClrN==1'b1)begin
if (F_LastN==1'b0 && WriteN==1'b0 && ReadN==1'b1)
F_FullN <= 1'b0;
else if(F_FullN==1'b0 && ReadN==1'b0)
F_FullN <= 1'b1;
end
else
F_FullN <= 1'b1;
end
end
endmodule
///////////////////////////////////////////////////////////////////
//
//
//Configurable memory block for fifo. The width of the mem
//block is configured via FWIDTH. All the data into fifo is done
//synchronous to block.
//
//Author : Venkata Ramana Kalapatapu
//
///////////////////////////////////////////////////////////////////
module FIFO_MEM_BLK( clk,
writeN,
wr_addr,
rd_addr,
data_in,
data_out
);
inputclk;// input clk.
inputwriteN;// Write Signal to put data into fifo.
input[(`FCWIDTH-1):0]wr_addr;// Write Address.
input[(`FCWIDTH-1):0]rd_addr;// Read Address.
input[(`FWIDTH-1):0]data_in;// DataIn in to Memory Block
output [(`FWIDTH-1):0]data_out;// Data Out from the Memory
// Block(FIFO)
wire[(`FWIDTH-1):0] data_out;
reg[(`FWIDTH-1):0] FIFO[0:(`FDEPTH-1)];
assign data_out= FIFO[rd_addr];
always @(posedge clk)
begin
if(writeN==1'b0)
FIFO[wr_addr] <= data_in;
end
endmodule