对于异步FIFO。最基本的两个方面是地址控制和空、满标志位的产生。首先地址控制分别为读地址和写地址,每次读写时能读写地址应该加1.计数次数为ram深度的2倍。当读写地址相等时则空标志位有效,当读写地址最高位互补其余位相等时则满标志位有效。

存储部分採用双口RAM实现。


以下是详细的Verilog代码:

module afifo(r_clk,w_clk,rst_n,data_in,data_out,we,re,empty,full);
input r_clk,w_clk,rst_n,re,we;
output empty,full;
input [7:0] data_in;
output[7:0] data_out;
wire[4:0] waddr,raddr;
wire [4:0] g_waddr,g_raddr;
// empty full
assign empty=(raddr==waddr);
assign full=((raddr[3:0]==waddr[3:0])&&(raddr[4]==(~waddr[4])));


wire wenable=we&&(~full);
wire renable=re&&(~empty);


afifo_control afifo_control1(
.r_clk(r_clk),
.w_clk(w_clk),
.rst_n(rst_n),
.we(wenable),
.re(renable),
.raddr(raddr),
.waddr(waddr)
);


dualram dualram_inst (
.data ( data_in ),
.rdaddress ( raddr[3:0] ),
.rdclock ( r_clk ),
.wraddress ( waddr[3:0] ),
.wrclock ( w_clk ),
.wren ( wenable ),
.q ( data_out )
);


endmodule 


module afifo_control(r_clk,w_clk,rst_n,we,re,raddr,waddr);
input r_clk,w_clk,rst_n,we,re;
output reg[4:0] raddr,waddr;


always @(posedge r_clk or negedge rst_n)
if(!rst_n) begin
raddr<=3'd0;
end
else if(re) begin
raddr<=raddr+1'b1;
end
always @(posedge w_clk or negedge rst_n)
if(!rst_n) begin
waddr<=3'd0;
end
else if(we) begin
waddr<=waddr+1'b1;
end
endmodule 


testbench例如以下:

`timescale 1 ns/ 1 ps
module afifo_vlg_tst();
// constants                                           
// general purpose registers
//reg eachvec;
// test vector input registers
reg [7:0] data_in;
reg r_clk;
reg re;
reg rst_n;
reg w_clk;
reg we;
// wires                                               
wire [7:0]  data_out;
wire empty;
wire full;


// assign statements (if any)                          
afifo i1 (
// port map - connection between master ports and signals/registers   
.data_in(data_in),
.data_out(data_out),
.empty(empty),
.full(full),
.r_clk(r_clk),
.re(re),
.rst_n(rst_n),
.w_clk(w_clk),
.we(we)
);
initial                                                
begin                                                  
#0; rst_n=1;data_in=100;re=0;we=0;
#50;rst_n=0; 
#50;rst_n=1;  
#20;re=1;
#20;re=0; 
#20;we=1;
#60;data_in=180;
#2000;we=0;re=1;
#3000;re=0;
#100;$stop();
                   
end                                                    
always                                                 
// optional sensitivity list                           
// @(event1 or event2 or .... eventn)                  
begin                                                  
// code executes for every event on sensitivity list   
// insert code here --> begin                          
   #10 r_clk=1; w_clk=0;
   #10 r_clk=0; w_clk=1;
//@eachvec;                                              
// --> end                                             
end                                                    
endmodule