module async_fifo (
input wire clk,
input wire rst,
input wire wr_en,
input wire rd_en,
input wire [7:0] wr_data,
output reg [7:0] rd_data,
output wire full,
output wire empty
);
parameter FIFO_DEPTH = 16;
reg [FIFO_DEPTH-1:0][7:0] fifo;
reg [FIFO_DEPTH-1:0] wr_ptr;
reg [FIFO_DEPTH-1:0] rd_ptr;
reg [4:0] count;
always @ (posedge clk) begin
if(rst) begin
wr_ptr <= 0;
rd_ptr <= 0;
count <= 0;
end
else begin
if (wr_en && !full) begin
fifo[wr_ptr] <= wr_data;
wr_ptr <= (wr_ptr == FIFO_DEPTH-1) ? 0 : wr_ptr+1;
count <= count + 1;
end
if (rd_en && !empty) begin
rd_data <= fifo[rd_ptr];
rd_ptr <= (rd_ptr == FIFO_DEPTH-1) ? 0 : rd_ptr+1;
count <= count - 1;
end
end
end
assign full = (count == FIFO_DEPTH);
assign empty = (count == 0);
endmodule
这个异步FIFO有一个输入时钟clk,一个同步复位rst,一个写使能信号wr_en,一个读使能信号rd_en,一个8位写数据输入口wr_data,一个8位读数据输出口rd_data,还有一个满标志位full和一个空标志位empty。
FIFO的深度由参数FIFO_DEPTH定义,这里设置为16。我们使用一个具有深度FIFO_DEPTH的循环缓冲区来实现FIFO。它由FIFO_DEPTH个8位寄存器组成。一个写指针wr_ptr指向下一个可用的位置,一个读指针rd_ptr指向下一个可用的位置。计数器count指示FIFO中有多少数据。
在时钟的上升沿,异步FIFO会执行以下操作:
- 如果复位信号rst被拉低,我们将写指针、读指针和计数器都重置为0。
- 如果写使能信号wr_en被拉低或者FIFO已经满了count已经等于FIFO_DEPTH,我们不会写入任何数据。
- 如果写使能信号wr_en被拉高,并且FIFO还有空闲位置count小于FIFO_DEPTH,我们将数据写入到FIFO的下一个位置,将写指针wr_ptr加1,计数器count加1。
- 如果读使能信号rd_en被拉低或者FIFO已经为空count已经等于0,我们不会读取任何数据。
- 如果读使能信号rd_en被拉高,并且FIFO还有数据count大于0,我们将下一个数据从FIFO中读出来,将读指针rd_ptr加1,计数器count减1。这个数据通过rd_data传递给输出端口。
最后,使用assign语句在full和empty信号与计数器count相关联,分别表示FIFO是否已满或为空。