异步fifo

这个是基于RAM的异步FIFO代码,个人认为代码结构简单易懂,非常适合于考试中填写。与同步fifo相比增加了读写控制信号的跨时钟域的同步。此外,判空与判满的也稍有不同。

module fifo
#(
	parameter DSIZE = 8, 
				 ASIZE = 4
)
(	
	input [DSIZE-1:0] wdata,
	input winc, wclk, wrst_n, 
	input rinc, rclk, rrst_n,
	output [DSIZE-1:0] rdata,
	output reg wfull,
	output reg rempty
);
 
reg [ASIZE:0] wptr, rptr, wq2_rptr, rq2_wptr, wq1_rptr,rq1_wptr; 
reg [ASIZE:0] rbin, wbin; 
reg [DSIZE-1:0] mem[0:(1<<ASIZE)-1]; 
wire [ASIZE-1:0] waddr, raddr; 
wire [ASIZE:0] rgraynext, rbinnext,wgraynext,wbinnext; 
wire rempty_val,wfull_val; 
//-----------------双口RAM存储器-------------------- 
assign rdata=mem[raddr]; 
always @(posedge wclk) 
if (winc && !wfull) 
	mem[waddr] <= wdata; 
//-------------同步rptr 指针------------------------- 
always @(posedge wclk or negedge wrst_n) 
	if (!wrst_n) 
		{wq2_rptr,wq1_rptr} <= 0; 
	else 
		{wq2_rptr,wq1_rptr} <= {wq1_rptr,rptr}; 
//-------------同步wptr指针--------------------------- 
always @(posedge rclk or negedge rrst_n) 
	if (!rrst_n) 
		{rq2_wptr,rq1_wptr} <= 0; 
	else 
		{rq2_wptr,rq1_wptr} <= {rq1_wptr,wptr}; 
//-------------rempty产生与raddr产生------------------- 
always @(posedge rclk or negedge rrst_n) // GRAYSTYLE2 pointer 
begin 
	if (!rrst_n) 
		{rbin, rptr} <= 0; 
	else 
		{rbin, rptr} <= {rbinnext, rgraynext}; 
end 

// Memory read-address pointer (okay to use binary to address memory) 
assign raddr = rbin[ASIZE-1:0]; 
assign rbinnext = rbin + (rinc & ~rempty); 
assign rgraynext = (rbinnext>>1) ^ rbinnext; 

// FIFO empty when the next rptr == synchronized wptr or on reset 
assign rempty_val = (rgraynext == rq2_wptr); 
always @(posedge rclk or negedge rrst_n) 
begin 
	if (!rrst_n) 
		rempty <= 1'b1; 
	else 
		rempty <= rempty_val; 
end 
//---------------wfull产生与waddr产生------------------------------ 
always @(posedge wclk or negedge wrst_n) // GRAYSTYLE2 pointer 
	if (!wrst_n) 
		{wbin, wptr} <= 0; 
	else 
		{wbin, wptr} <= {wbinnext, wgraynext}; 
// Memory write-address pointer (okay to use binary to address memory) 
assign waddr = wbin[ASIZE-1:0]; 
assign wbinnext = wbin + (winc & ~wfull); 
assign wgraynext = (wbinnext>>1) ^ wbinnext; 
assign wfull_val = (wgraynext=={~wq2_rptr[ASIZE:ASIZE-1], wq2_rptr[ASIZE-2:0]}); //:ASIZE-1]

always @(posedge wclk or negedge wrst_n) 
	if (!wrst_n) 
		wfull <= 1'b0; 
	else 
		wfull <= wfull_val; 
endmodule

 

参考文章:Clifford E. Cummings http://www.sunburst-design.com/papers/

http://www.cnblogs.com/qiweiwang/archive/2011/04/09/2010591.html

http://www.cnblogs.com/qiweiwang/archive/2011/04/09/2010591.html

posted on 2011-09-16 16:48  齐威王  阅读(3536)  评论(2编辑  收藏  举报

导航