同步FIFO
- FIFO是( first input first output)一般用作不同时钟域的缓冲器,顺序写入数据,顺序的读出数据,其数据地址由内部读写指针自动加一完成,根据读和写的时钟是否为同一时钟分为同步FIFO和异步FIFO。
- FIFO设计的难点在于怎样判断FIFO的空/满状态。为了保证数据正确的写入或读出,而不发生益处或读空的状态出现,必须保证FIFO在满的情况下,不 能进行写操作。在空的状态下不能进行读操作。
- 典型的同步FIFO由三部分组成:
- FIFO写控制逻辑:用于产生FIFO写地址、写有效信号,同时产生FIFO写满、写错等状态信号。
- FIFO读控制逻辑:用于产生FIFO读地址、读有效信号,同时产生FIFO读空、读错等状态信号。
- FIFO存储实体(memory、reg)
结构图如下:

设计主要分为以下两部分:
- 读写过程的地址控制
- 定义reg来存储FIFO写数据,读数据。
- FIFO写操作:写地址加一。
- FIFO读操作:读地址加一。
- 空满状态的产生
引入计数器,count计数器存储FIFO数据的的个数。
- 写操作:count+1。
- 读操作 :count-1。
- 写满:count=fifo深度,写满为full。
- 读空:count=0,读空为empty。
设计代码如下:
module syn_fifo
(
input clk;
input rst_n;
input wr_cs;
input wr_en;
input [7:0]wr_data;
output reg full;
input rd_cs;
input dr_en;
output [7:0]rd_data;
output reg empty;
);
reg [7:0] wr_addr;
reg [7:0] rd_addr;
reg [8:0] count;
reg [7:0] fifo_ram [255:0];
integer i;
//写数据
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
for(i = 0; i < 128;i = i + 1)
fifo_ram[i] <= {8{1'b0}};
end
else
if(wr_en&&(!full))
fifo_ram[wr_addr] <= wr_data;
end
//读数据
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
rd_data <= {8{1'b0}};
else if(rd_en&&(!empty))
rd_data <= fifo_ram[rd_addr];
end
//读写控制
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
wr_addr <= {8{1'b0}};
else if(wr_en&&(!full))
wr_addr <= wr_addr +1'b1;
end
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
rd_addr <= {8{1'b0}};
else if(rd_en&&(!empty))
rd_addr <= rd_addr +1'b1;
end
//数据计数器 读一次减1,写一次加1
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
count <= 9'b0;
else if(wr_en&&(!full))
count <= count + 1;
else if(rd_en&&(!empty))
count <= count - 1;
end
//空满判断
assign full = (count == {8{1'b1} + 1});
assign empty = (count == 0);
endmodule