0%

FIFO

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 。

优点

  1. 采样+握手信号,可以用于进行任意比特信号的跨时钟域传递。
  2. 触发器数量:格雷码需要 2n 个触发器,同步模块需要 2n+4 个触发器(每位 1 个触发器,同步 ready 信号 2 个触发器,同步 acknowledge 信号 2 个触发器)
  3. 格雷码只能递增,二进制码则可以任意改变。
  4. 二进制指针允许任意深度的 FIFO ,而格雷码只能是 2 的 n 次方。
  5. 二进制指针容易计算 almost full & empty 。

缺点

  1. 采样并握手,会延迟新样本的采样,至少从接收时钟域延迟两个时钟,从发送时钟域延迟两个时钟。

方法

  • 使用寄存器采样指针计数信号,并向接收时钟域输出 ready 信号。
  • 当 ready 信号被接收时,接收时钟域向发送时钟域发回一个同步的 acknowledge 信号。
  • 在从接收时钟域接收到 acknowledge 信号之前,采样的指针计数信号不得改变。
  • 接收到 acknowledge 信号后,发送时钟域有权清除 ready 信号并重新采样指针计数信号。

空/满标志的生成

#1 增加额外位 extra bit

  • 空 empty

    • rptr next 和 synchronized wptr:
      • extra bit 相同,其余位也相同
    image-20230709161731837
  • 满 full

    • wptr next 和 synchronized rptr:
      • MSB 不同
      • 2nd MSB 也不同(格雷码特性)
      • 其余位相同
    image-20230709161707621 image-20230710164058628
    • almost empty:rptr+4 赶上 wptr

    • almost full:wptr+4 赶上 rptr

#2 趋势信号 direction

  • 将地址空间分为四个象限,通过两个 MSB 生成趋势信号 direction 。
image-20230714152857811 image-20230714152311605 image-20230714152835265
  • 空满:
image-20230714152931113

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 异步比较

image-20230714151224529
  • fifo1.v :顶层模块

  • fifomem.v :FIFO memory buffer,此处是一个双端口 RAM 。

    • 注:双端口 RAM 面积比单端口 RAM 大一倍,所以要注意控制 FIFO 深度。
  • sync_cmp.v :生成异步的 afull_naempty_n 信号。

  • wptr_full.v :生成 write pointer 和 full flag 。

  • rptr_empty.v :生成 read pointer 和 empty flag 。

空/满

  • 异步生成 afull_naempty_n 信号。
  • 异步设置 remptywfull 信号,同步释放。
image-20230714154212501

复位

  1. 清除 wfull ,而不清除 rempty
  2. 复位 wptrrptr
  3. 清除 direction
  4. 异步产生 aemtpy_n ,进而清除 rempty

仅用于测试的 FIFO 行为模型

image-20230709085504647