FIFO1
- FIFO 常用于数据的跨时钟域传输。
- FIFO 设计难点在于读/写指针的生成和空/满状态的判断。
同步 FIFO
- 对写入和读取进行计数,增加(写入但不读取)、减少(读取但不写入)、保持(不读也不写/同时读写)。
- 当计数为 0 ,为空状态;当计数为满,为满状态。
异步 FIFO
- 异步 FIFO 不能使用计数方法,因为读写端口时钟域不同。
- 为了判断空/满状态,必须对读/写指针进行比较。
- 读指针指向要读取的地址,写指针指向要写入的地址。在读取/写入之后,读/写指针递增。
- 当 FIFO 为空,读指针指向无效数据地址。进行写操作之后,空标志清零,读指针变为有效,立即将有效数据驱动到输出口,供接收端读取。
读/写指针的生成(计数器)
#1 寄存器输出是格雷码

- 格雷码和二进制码转换、递增,得到 n 位格雷码计数器。
- 将最高两位异或,与剩余位拼接,得到 n-1 位格雷码计数器。
#2 寄存器输出分别是二进制码和格雷码

- n-1位二进制码用于寻址 FIFO地址。
- n 位格雷码用于同步到另一个时钟域。
- 若不使用 extra bit ,则都是 n-1 位。
指针计数信号的跨时钟域同步
FIFO 指针常用格雷码计数,每个时钟边沿只会有 1 位变化,避免多 bit CDC 问题。
指针计数是否会在采样间隔中持续变化甚至上溢、下溢?答案是不会。
- FIFO 满:写指针追上同步采样的读指针。同步采样的读指针可能不是读指针的实时值,但写指针不会超过同步采样的读指针,所以上溢不会发生。
- FIFO 空:读指针追上同步采样的写指针。同步采样的写指针可能不是写指针的实时值,但读指针不会超过同步采样的写指针,所以下溢不会发生。
二进制计数器
如果对二进制指针进行采样,并在两个时钟域之间使用握手信号来安全传递,则可以使用二进制指针设计 FIFO 。
优点:
- 采样+握手信号,可以用于进行任意比特信号的跨时钟域传递。
- 触发器数量:格雷码需要 2n 个触发器,同步模块需要 2n+4 个触发器(每位 1 个触发器,同步 ready 信号 2 个触发器,同步 acknowledge 信号 2 个触发器)
- 格雷码只能递增,二进制码则可以任意改变。
- 二进制指针允许任意深度的 FIFO ,而格雷码只能是 2 的 n 次方。
- 二进制指针容易计算 almost full & empty 。
缺点:
- 采样并握手,会延迟新样本的采样,至少从接收时钟域延迟两个时钟,从发送时钟域延迟两个时钟。
方法:
- 使用寄存器采样指针计数信号,并向接收时钟域输出 ready 信号。
- 当 ready 信号被接收时,接收时钟域向发送时钟域发回一个同步的 acknowledge 信号。
- 在从接收时钟域接收到 acknowledge 信号之前,采样的指针计数信号不得改变。
- 接收到 acknowledge 信号后,发送时钟域有权清除 ready 信号并重新采样指针计数信号。
空/满标志的生成
#1 增加额外位 extra bit

空 empty
- rptr next 和 synchronized wptr:
- extra bit 相同,其余位也相同
- rptr next 和 synchronized wptr:
满 full
- wptr next 和 synchronized rptr:
- MSB 不同
- 2nd MSB 也不同(格雷码特性)
- 其余位相同
almost empty:rptr+4 赶上 wptr
almost full:wptr+4 赶上 rptr
- wptr next 和 synchronized rptr:
#2 趋势信号 direction
- 将地址空间分为四个象限,通过两个 MSB 生成趋势信号 direction 。



- 空满:

FIFO #1 同步比较

fifo1.v
:顶层模块fifomem.v
:FIFO memory buffer,此处是一个双端口 RAM 。- 注:双端口 RAM 面积比单端口 RAM 大一倍,所以要注意控制 FIFO 深度。
sync_r2w.v
:将 read pointer 同步到 write pointer 时钟域,仅包含触发器。sync_w2r.v
:将 write pointer 同步到 read pointer 时钟域,仅包含触发器。wptr_full.v
:生成 write pointer 和 full flag 。rptr_empty.v
:生成 read pointer 和 empty flag 。
问题
时钟不同速的问题
n
保守的 full & empty flag 清除策略
异步复位时多位同时跳变的问题
n
FIFO #2 异步比较

fifo1.v
:顶层模块fifomem.v
:FIFO memory buffer,此处是一个双端口 RAM 。- 注:双端口 RAM 面积比单端口 RAM 大一倍,所以要注意控制 FIFO 深度。
sync_cmp.v
:生成异步的afull_n
和aempty_n
信号。wptr_full.v
:生成 write pointer 和 full flag 。rptr_empty.v
:生成 read pointer 和 empty flag 。
空/满
- 异步生成
afull_n
和aempty_n
信号。 - 异步设置
rempty
和wfull
信号,同步释放。

复位
- 清除
wfull
,而不清除rempty
。 - 复位
wptr
和rptr
。 - 清除
direction
。 - 异步产生
aemtpy_n
,进而清除rempty
。
仅用于测试的 FIFO 行为模型
