http://www.cnblogs.com/qiweiwang/archive/2011/04/09/2010591.html
同步fifo---基于循环队列的方式
module fifo
#(
parameter B=8,//存储数据宽度,一个数据有B位
W=3//地址空间位数,可存储2^W个数据
)
(
input clk,
input rst_n,
input rd,
input wr,
input [B-1:0] w_data,
output empty,
output full,
output reg [B-1:0] r_data
);
reg [B-1:0] array_reg[2**W-1:0];
reg [W-1:0] w_ptr_reg,w_ptr_next,w_ptr_succ;
reg [W-1:0] r_ptr_reg,r_ptr_next,r_ptr_succ;
reg full_reg,full_next,empty_reg,empty_next;
wire wr_en,rd_en;
assign wr_en = wr & ~full_reg;
assign rd_en = rd & ~empty_reg;
assign full = full_reg;
assign empty = empty_reg;
always @ (posedge clk)
begin
if(wr_en)
array_reg[w_ptr_reg] <= w_data;
else if (rd_en)
r_data <= array_reg[r_ptr_reg];
end
always @ (posedge clk ,negedge rst_n)
begin
if(!rst_n)
begin
w_ptr_reg <= 1'b0;
r_ptr_reg <= 1'b0;
full_reg <= 1'b0;
empty_reg <= 1'b1;
end
else
begin
w_ptr_reg <= w_ptr_next;
r_ptr_reg <= r_ptr_next;
full_reg <= full_next;
empty_reg <= empty_next;
end
end
always @ (*)
begin
w_ptr_succ = w_ptr_reg + 1'b1;
r_ptr_succ = r_ptr_reg + 1'b1;
w_ptr_next = w_ptr_reg;
r_ptr_next = r_ptr_reg;
full_next = full_reg;
empty_next = empty_reg;
case( {wr,rd} )
2'b01:
if(~empty_reg)
begin
r_ptr_next = r_ptr_succ;
full_next = 1'b0;
if(r_ptr_succ==w_ptr_reg)
empty_next = 1'b1;
end
2'b10:
if(~full_reg)
begin
w_ptr_next = w_ptr_succ;
empty_next = 1'b0;
if(w_ptr_succ==r_ptr_reg)
full_next = 1'b1;
end
2'b11:
begin
w_ptr_next = w_ptr_succ;
r_ptr_next = r_ptr_succ;
end
default:;
endcase
end
endmodule