FIFO(First In First Out),是一种先进先出的数据缓存器,它与普通存储器的区别是没有外部读写地址线,但缺点就是只能顺序写入和顺序读出数据,其数据地址由内部读写指针自动加1完成,无法同普通存储器那样可以由地址线决定读取或写入某个指定的地址。
读写频率,突发速率,突发长度决定FIFO的最小深度。
① 无明确说明,考虑最坏情况
e.g.1 时钟为100MHz,每100个cycle可以写入80个数据,每10个cycle可以读出8个数据,突发长度160。
解析:考虑最坏的情况(背靠背模式:两次连续的突发写入),突发长度为160即在160个clk写160个数据(如上图所示),在这160clk读侧只能读出(160/10)*8 = 128;所以没读走的160-128=32个数据,故FIFO最小深度为32。
e.g.2 写时钟20MHz,读时钟40MHz,每1000个时钟周期写入500个数据,每4个时钟周期读出1个数据,读写数据位宽一致。
解析:考虑最坏的情况(背靠背模式:两次连续的突发写入),突发长度为500*2 = 1000。写一个数需要1/20M=50 ns,写1000个需要50*1000 = 50000 ns,读一个数需要4*1/40M = 100 ns,则可以读出50000/100 = 500个,所以深度为1000-500 = 500。
② fw>fr
无空闲周期:写速率80MHz,读速率50MHz,突发长度Burst Length = 120。
解析:写一个数需要1/80M=12.5 ns,写120个需要12.5*120 = 1500 ns,读一个数需要1/50M = 20 ns,则可以读出1500/20 = 75个,所以深度为120-75 = 45。
有空闲周期:写速率80MHz,读速率50MHz,突发长度Burst Length = 120,两个连续写入之间的空闲周期为 = 1,两个连续读取之间的空闲周期为 = 3
解析:写一个数需要2*1/80M=25 ns,写120个需要25*120 = 3000 ns,读一个数需要4*1/50M = 80 ns,则可以读出3000/80 = 37.5个,所以深度为120-37 = 83。
读写使能百分比:写速率80MHz,读速率50MHz,突发长度Burst Length = 120,写使能占得百分比为 = 50% = 1 / 2,读使能占得百分比为 = 25% = 1 / 4
解析:写使能占得百分比为 = 50% = 1 / 2,读使能占得百分比为 = 25% = 1 / 4,说明两个周期写一个,四个周期读一个。故有写一个数需要2*1/80M=25 ns,写120个需要25*120 = 3000 ns,读一个数需要4*1/50M = 80 ns,则可以读出3000/80 = 37.5个,所以深度为120-37 = 83。
③ fw
无空闲周期:由于读大于写,刚写完就会被读走,所以深度≥1就可以。
有空闲周期:写速率30MHz,读速率50MHz,突发长度Burst Length = 120,两个连续写入之间的空闲周期为 = 1,两个连续读取之间的空闲周期为 = 3
解析:写一个数需要2*1/30M=66.7 ns,写120个需要66.7*120 = 8000 ns,读一个数需要4*1/50M = 80 ns,则可以读出8000/80 = 100个,所以深度为120-100 = 20。
读写使能百分比:同上。
④ fw=fr
无空闲周期:由于读等于写,刚写完就会被读走,所以深度≥1就可以。
有空闲周期:写速率50MHz,读速率50MHz,突发长度Burst Length = 120,两个连续写入之间的空闲周期为 = 1,两个连续读取之间的空闲周期为 = 3
解析:写一个数需要2*1/50M=40 ns,写120个需要40*120 = 4800 ns,读一个数需要4*1/50M = 80 ns,则可以读出4800/80 = 60个,所以深度为120-60 = 60。
读写使能百分比:同上。
同步FIFO和异步FIFO,两者的区别在于读写时钟是否是同一个时钟。
格雷码用作读写指针(即地址值)。由于将一个二进制的值从一个时钟域同步到另一个时钟域容易出现问题,因为采用二进制计数器时所有位都可能同时变化,在同一个时钟沿同步多个信号的变化会产生亚稳态问题。而使用格雷码无论如何都只有一位变化,因此在两个时钟域间同步多个bit数值不会产生问题。所以需要将二进制转换到gray码,即将地址值转换为相应的gray码,然后将该gray码同步到另一个时钟域进行对比,作为空满状态的检测。
二进制转格雷码:二进制本身与二进制右移一位后进行异或,代码为:
g_rd_ptr = (rd_ptr)^(rd_ptr>>1)
格雷码转二进制:最高位保持不变,格雷码最高位与次高位异或得二进制次高位,以此类推,代码为:
assign bin[data_width-1] = gray[data_width-1];//最高位相等
genvar i;
generate
for(i=0;i<=data_width-2;i=i+1)begin:BLOCK1
assign bin[i] = bin[i+1] ^ gray[i]; //次高位等于高位与格雷码次高位相异或
end
两级触发同步器,它要求异步输入信号在新时钟域中至少稳定两个时钟周期。
(27 封私信 / 80 条消息) 跨时钟域同步,为什么两级寄存器结构能够降低亚稳态? - 知乎 (zhihu.com)
每读一个,读指针加一,每写一个,写指针加一。当读写指针相等时,FIFO为空或满。为了区分空与满,常多加1bit,或多加一个使能信号。例如,当多加一位后,当写指针最高位为与读指针相反(写指针最高位为1),其他位相同时为满。全相等时为空。
对于异步电路来说,还存在跨时钟域的问题,需要将读指针用写时钟答两拍与写指针比较,判断是否满,将写指针应读时钟打两拍与读指针比较,判断是否空。
1.主要是作数据的缓存,解决读写速度不匹配的问题。
2.跨时钟域处理。需要异步FIFO用作两个不同时钟域的模块之间的数据缓冲,确保不会丢失数据。而且通过FIFO进行隔离,可以避免跨时钟域的数据传输带来的设计和约束上的复杂度。(异步FIFO)
3.用于不同宽度的数据接口。
关于同步fifo和异步fifo深度设计和特殊情况 - 知乎 (zhihu.com)
你问我FIFO有多深? - 知乎 (zhihu.com)
IC设计 — 同步FIFO和异步FIFO设计实现(一) (ngui.cc)
FPGA——verilog实现格雷码与二进制的转换_格雷码verilog_漠影zy的博客-CSDN博客
同步FIFO和异步FIFO总结 (xjx100.cn)
FIFO(同步与异步)_同步fifo和异步fifo_酒后敲代码的博客-CSDN博客
verilog同步/异步FIFO设计 - 知乎 (zhihu.com)
两级同步为什么能解决亚稳态问题?_两级同步器_燕飞西山的博客-CSDN博客