对于异步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