module asyn_fifo #(parameter FIFO_WIDTH = 32,
parameter FIFO_DEPTH = 16,
parameter ADDR_WIDTH = 4)
(
input wr_clk ,
input rd_clk ,
input rst_n ,
input wr_en ,
input [FIFO_WIDTH-1:0] wr_data,
input rd_en ,
output reg [FIFO_WIDTH-1:0] rd_data,
output wr_full,
output rd_empty
);
reg [ADDR_WIDTH:0] wr_addr_ptr; //地址指针,比地址多一位
reg [ADDR_WIDTH:0] rd_addr_ptr;
reg [ADDR_WIDTH-1:0] wr_addr; //RAM地址
reg [ADDR_WIDTH-1:0] rd_addr;
reg [ADDR_WIDTH:0] wr_addr_ptr_gray;
reg [ADDR_WIDTH:0] wr_addr_ptr_gray_d1;
reg [ADDR_WIDTH:0] wr_addr_ptr_gray_d2;
reg [ADDR_WIDTH:0] rd_addr_ptr_gray;
reg [ADDR_WIDTH:0] rd_addr_ptr_gray_d1;
reg [ADDR_WIDTH:0] rd_addr_ptr_gray_d2;
reg [FIFO_WIDTH-1:0] mem [0:FIFO_DEPTH-1];
integer i;
//==========write fifo==============
always @(posedge wr_clk, negedge rst_n) begin
if(~rst_n) begin
for(i=0;i<FIFO_DEPTH;i=i+1) begin
mem[i] <= 'h0;
end
end
else if(wr_en) begin
mem[wr_addr] <= wr_data;
end
end
//==========read fifo==============
always @(posedge rd_clk, negedge rst_n) begin
if(~rst_n) begin
rd_data <= 'h0;
end
else if(rd_en) begin
rd_data <= mem[rd_addr];
end
end
//################## write clock ################
//=========write pointer generate==========
always @(posedge wr_clk, negedge rst_n) begin
if(~rst_n) begin
wr_addr_ptr <= 'h0;
end
else if(wr_en && (~wr_full)) begin
wr_addr_ptr <= wr_addr_ptr+1'b1;
end
end
//==========translate write pointer gray code==========
always @(posedge wr_clk, negedge rst_n) begin
if(~rst_n) begin
wr_addr_ptr_gray <= 'h0;
end
else begin
wr_addr_ptr_gray <= (wr_addr_ptr>>1)^wr_addr_ptr;
end
end
//===========read pointer gray syn==============
always @(posedge wr_clk, negedge rst_n) begin
if(~rst_n) begin
rd_addr_ptr_gray_d1 <= 'h0;
rd_addr_ptr_gray_d2 <= 'h0;
end
else begin
rd_addr_ptr_gray_d1 <= rd_addr_ptr_gray;
rd_addr_ptr_gray_d2 <= rd_addr_ptr_gray_d1;
end
end
//############### read clock ##################
//=========read pointer generate==========
always @(posedge rd_clk, negedge rst_n) begin
if(~rst_n) begin
rd_addr_ptr <= 'h0;
end
else if(rd_en && (~rd_empty)) begin
rd_addr_ptr <= rd_addr_ptr+1'b1;
end
end
//==========translate read pointer gray code==========
always @(posedge rd_clk, negedge rst_n) begin
if(~rst_n) begin
rd_addr_ptr_gray <= 'h0;
end
else begin
rd_addr_ptr_gray <= (rd_addr_ptr>>1)^rd_addr_ptr;
end
end
//===========write pointer gray syn==============
always @(posedge rd_clk, negedge rst_n) begin
if(~rst_n) begin
wr_addr_ptr_gray_d1 <= 'h0;
wr_addr_ptr_gray_d2 <= 'h0;
end
else begin
wr_addr_ptr_gray_d1 <= wr_addr_ptr_gray;
wr_addr_ptr_gray_d2 <= wr_addr_ptr_gray_d1;
end
end
assign wr_addr = wr_addr_ptr[ADDR_WIDTH-1:0];
assign rd_addr = rd_addr_ptr[ADDR_WIDTH-1:0];
assign wr_full = (wr_addr_ptr_gray == {~rd_addr_ptr_gray_d2[ADDR_WIDTH:ADDR_WIDTH-1],rd_addr_ptr_gray_d2[ADDR_WIDTH-2:0]});
assign rd_empty = (rd_addr_ptr_gray == wr_addr_ptr_gray_d2);
endmodule
异步fifo代码
最新推荐文章于 2024-08-03 22:47:46 发布