FIFO在硬件上是一种地址依次自增的Simple Dual Port RAM,按读数据和写数据工作的时钟域是否相同分为同步FIFO和异步FIFO,其中同步FIFO是指读时钟和写时钟为同步时钟,常用于数据缓存和数据位宽转换;异步FIFO通常情况下是指读时钟和写时钟频率有差异,即由两个异步时钟驱动的FIFO,由于读写操作是独立的,故常用于多比特数据跨时钟域处理。本文仅讨论异步FIFO的设计。
因为FIFO的硬件本质是一块Simple Dual Port RAM,无论它的内部结构和原理如何复杂,最核心的部分都只是对这个RAM的读写操作而已,所以我们先设计RAM部分的RTL。一个Simple Dual Port RAM应该由读写时钟、读写使能、读写地址总线和读写数据总线接口构成,这里为了在功能仿真中初始化读数据寄存器,再加入一个读复位接口。Verilog代码如下:
module DPRAM #
(
parameter WIDTH = 16 , // DPRAM数据总线宽度
parameter DEPTH = 16 , // DPRAM存储深度
parameter ADDR = 4 // DPRAM地址总线宽度
)
(
input wrclk , // 写时钟
input rdclk , // 读时钟
input rd_rst_n, // 读复位
input wr_en , // 写使能
input rd_en , // 读使能
input [WIDTH-1:0] wr_data , // 写数据
output reg [WIDTH-1:0] rd_data , // 读数据
input [ADDR-1:0] wr_addr , // 写地址
input [ADDR-1:0] rd_addr // 读地址
);
reg [WIDTH-1:0] DPRAM [DEPTH-1:0];
// RAM写数据
always @(posedge wrclk) begin
if (wr_en)
DPRAM[wr_addr] |