异步FIFO(Asynchronous First In First Out)
1. 前言
由于EDA工具的广泛支持,采用同步电路设计的方法是目前Soc设计的基本要求,但在一个功能复杂的Soc系统中,难免会有异步信号与同步电路交互的问题。特别是在由许多核组成的Soc中,通常采用全局异步局部同步(GALS)的设计。而跨时钟域传输数据时很容易造成亚稳态的现象,本文主要讲解Asyn_FIFO来解决跨时钟域传输多bit信号的问题。
2. Asyn_FIFO的结构与原理
Asyn_FIFO: 写数据wdata在写时钟域下wclk写入到FIFO中的存储器(双端口RAM)中,读数据rdata在读时钟域rclk下从FIFO中的存储器读出wdata写入的值。综合下,Asynchronous FIFO可以安全地把数据从一个时钟域传输到另外一个时钟域。
2.1 Asynchronous FIFO的结构
- 总体架构图如下
- 可以看出由5个模块组成:FIFO Memory, wptr_full, rptr_empty, sync_r2w, sync_w_r
- FIFO Memory: 这部分就是存储器。
- wptr_full: 在写信号有效的情况下, 生成二进制的写地址指针waddr、Gray码的写地址指针wptr和判满信号wfull。
- rptr_empty: 在读信号有效的情况下, 生成二进制的读地址指针raddr、Gray码的读地址指针rptr和判空信号rempty。
- sync_r2w: rclk domain 到 wclk domain 的同步器,Gray码的读地址指针rptr在wclk domain下的寄存器寄存两拍然后传输给wptr_full模块。
- sync_w2r: wclk domain 到 rclk domain 的同步器,Gray码的写地址指针wptr在rclk domain下的寄存器寄存两拍然后传输给rptr_empty模块。
2.2 Asynchronous FIFO的原理
1) FIFO Memory
- Asyn_FIFO的存储器部分采用RAM,而RAM分类有单端口和双端口,同步和异步。因为Syn_FIFO是需要在两个时钟域下工作的模块(分开读分开写)。所以采用双端口的RAM。而同步RAM和异步RAM的区别是在读端口引入一级DFF在时钟上升沿读取还是raddr改变时直接读取,也即同步读、异步读,理想情况下,同步读数据比异步读数据晚一个读时钟周期。通常这两种都可以,看具体要求再设计。
2) wptr_full and rptr_empty
- 这两个模块实际上是对称的,设计思路都是一样的。具体思路如下:
- 写时钟域:
- 根据写使能信号winc和写满标志位wfull来产生二进制写指针wbin;
- 根据二进制写指针wbin产生双端口RAM的写地址waddr;
- 把二进制写指针wbin转换成Gray码写指针wptr;
- 从同步器sync_r2w得到同步到写时钟域下的Gray码读指针;
- 判断 wptrnext == wq2_rptr 得写满标志位wfull;
- 读时钟域:
- 根据读使能信号rinc和读空标志rempty来产生二进制读指针rbin;
- 根据二进制读指针rbin产生双端口RAM得读地址raddr;
- 把二进制读指针raddr转换成Gray码写指针rptr;
- 从同步器sync_w2r得到同步到读时钟域下得Gray码写指针;
- 判断 rptrn