Verilog code for asynchronous FIFO is given below. The module “a_fifo5” should be used for Modelsim (or any other HDL simulator) simulation. The module “fifo_top” is used to synthesize the design in Spartan 3 board. Before invoking this module in ISE you should add Digital Clock Manager (DCM) code to your project. This can be done using Xilinx ISE wizard.
//==================================================
//a_fifo5.v; verilog code for asynchronous FIFO
//This module describes FIFO
//===================================================
module a_fifo5(d_out,f_full_flag,f_half_full_flag,f_empty_flag,
f_almost_full_flag,f_almost_empty_flag,d_in,r_en,w_en,r_clk,w_clk,reset);
parameter f_width=8; //FIFO width
parameter f_depth=16; //FIFO depth
parameter f_ptr_width=4; //because depth =16;
parameter f_half_full_value=8;
parameter f_almost_full_value=14;
parameter f_almost_empty_value=2;
output [f_width-1:0] d_out; reg [f_width-1:0] d_out; //outputs
output f_full_flag,f_half_full_flag,f_almost_full_flag,f_empty_flag,f_almost_empty_flag;
input [f_width-1:0] d_in;
input r_en,w_en,r_clk,w_clk;
input reset;
//internal registers,wires
wire [f_ptr_width-1:0] r_ptr,w_ptr;
reg r_next_en,w_next_en;
reg [f_ptr_width-1:0] ptr_diff;
reg [f_width-1:0] f_memory[f_depth-1:0];
assign f_full_flag=(ptr_diff==(f_depth-1)); //assign FIFO status
assign f_empty_flag=(ptr_diff==0);
assign f_half_full_flag=(ptr_diff==f_half_full_value);
assign f_almost_full_flag=(ptr_diff==f_almost_full_value);
assign f_almost_empty_flag=(ptr_diff==f_almost_empty_value);
//---------------------------------------------------------
always @(posedge w_clk) //write to memory
begin
if(w_en) begin
if(!f_full_flag)
f_memory[w_ptr]<=d_in; end
end
//---------------------------------------------------------
always @(posedge r_clk) //read from memory
begin
if(reset)
d_out<=0; //f_memory[r_ptr];
else if(r_en) begin
if(!f_empty_flag)
d_out<=f_memory[r_ptr]; end
else d_out<=0;
end
//---------------------------------------------------------
always @(*) //ptr_diff changes as read or write clock change
begin
if(w_ptr>r_ptr)
ptr_diff<=w_ptr-r_ptr;
else if(w_ptr
begin
ptr_diff<=((f_depth-r_ptr)+w_ptr);
end
else ptr_diff<=0;
end
//---------------------------------------------------------
always @(*) //after empty flag activated fifo read counter should not increment;
begin if(r_en && (!f_empty_flag))
r_next_en=1;
else r_next_en=0;
end
//--------------------------------------------------------
always @(*) //after full flag activated fifo write counter should not increment;
begin if(w_en && (!f_full_flag))
w_next_en=1;
else w_next_en=0;
end
//---------------------------------------------------------
b_counter //instantiate address counters r_b_counter(.c_out(r_ptr),.c_reset(reset),.c_clk(r_clk),.en(r_next_en));
b_counter w_b_counter(.c_out(w_ptr),.c_reset(reset),.c_clk(w_clk),.en(w_next_en));
endmodule
//==============================================================
//b_counter.v; 4 bit asynchronous binary up counter
//==============================================================
module b_counter(c_out,c_reset,c_clk,en);
parameter c_width=4; //counter width
output [c_width-1:0] c_out; reg [c_width-1:0] c_out;
input c_reset,c_clk,en;
always @(posedge c_clk or posedge c_reset)
if (c_reset)
c_out <= 0;
else if(en)
c_out <= c_out + 1;
endmodule
//===========================================================
//===========================================================
//fifo_top.v; top level verilog code of FIFO
//To be used with Xilinx ISE-simulation and synthesis
//For functional simulation this module is not necessary
//============================================================
module fifo_top(x,y,z,d_out,f_full_flag,f_half_full_flag,f_empty_flag,
f_almost_full_flag,f_almost_empty_flag,d_in,r_en,w_en,CLKIN_IN,RST_IN,reset);
parameter f_width=8;
parameter f_depth=16;
parameter f_ptr_width=4;
parameter f_half_full_value=8;
parameter f_almost_full_value=14;
parameter f_almost_empty_value=2;
output [f_width-1:0] d_out; //reg [f_width-1:0] d_out; //outputs
output f_full_flag,f_half_full_flag,f_almost_full_flag,f_empty_flag,f_almost_empty_flag;
output x,y,z;
input [f_width-1:0] d_in;
input r_en,w_en,CLKIN_IN,RST_IN;
input reset;
a_fifo5 a_fifo55(d_out,f_full_flag,f_half_full_flag,f_empty_flag,
f_almost_full_flag,f_almost_empty_flag,d_in,r_en,w_en,CLK0_OUT,CLKDV_OUT,reset); //instantiate fifo
dcm_fifo dcm_fifo1(CLKIN_IN,RST_IN,CLKDV_OUT,CLKFX_OUT,CLKIN_IBUFG_OUT,CLK0_OUT, LOCKED_OUT); //instantiate DCM
assign x=CLKIN_IBUFG_OUT; //simply to avoid error
assign y=LOCKED_OUT;
assign z=CLKFX_OUT;
endmodule
//=================================================
Related Articles
-
Asynchronous FIFO Design
-
FIFO Pointers
-
Verilog Test Bench for Asynchronous FIFO
-
New Asynchronous FIFO Design
-
Asynchronous FIFO: Simulation and Synthesis
Good stuff Murali!!
ReplyDeleteI congratulate your efforts in writing the blog.I wish graduates will find this blog helpful for making their careers in this prospective and challenging field.
In fact it is a good idea of sharing knowledge. Thank you:-)
thanks sharma....happy reading !
ReplyDeleteFor a long time I am looking for Multi-Clock domain and CDC stuff.I haven't got an opportunity to work with these.Could ypu please provide some stuff on this. Theoritically to some extent I am clear but I want to see few examples also which I never find on Internet.
ReplyDeletethis is nice......
ReplyDeletebut is there any verilog code for async fifo using SRAM(dual port SRAM). if not, will give me any idea about how to implement this?
Keep up the Good Job Murali...
ReplyDeleteRegards,
Sainath
good job dude...its rreally helpful......keep on addind such stuff..... :)
ReplyDeleteHi,
ReplyDeleteWe are proud to inform you that we are one of the leading training centre for both VLSI and Embedded System Design at Chennai.
Regards,
siva
vlsiva@yahoo.co.in
9003241032
Hi Murali,
ReplyDeleteI dont get this. In you implementation, How come you are not using synchronizers to in the to synchronize read and write pointers in the two clock domains?
Please explain.
Thanks
Tariq
hi everyone
ReplyDeletecan any one tell me please
where is the code for DCM (digital clock manager)?
Really awesome blog
ReplyDeleteThank you soooooooooooooo much
This code looks completely wrong to me. You are randomly mixing signals from different clock domains with no synchronization. The full condition is wrong.
ReplyDeleteptr_diff logic you missed it. it is no the complete code. please correct the code.
ReplyDelete