1. fifo是什么?
FIFO:First in first out,先进先出的数据缓存器,没有外部读写地址线,使用简单,缺点是只能顺序写入数据,顺序读出数据,数据地址由内部读写指针自动加1完成,不能像普通存储器可以由地址线决定读取或者写入某个指定的地址
FIFO用于以下几个方面:
- 跨时钟域数据传输
- 将数据发送到芯片外之前进行缓冲
- 存储数据备用
2. FIFO重要参数
深度、宽度、空标志、满标志、读时钟、读指针、写时钟、写指针
- 深度:指可以存储多个宽度的数据;如一个8位的FIFO,若深度位8,可以存储8个8位的数据,深度为10就可以存10个8位的数据;
- 宽度:指FIFO一次读写操作的数据位;
- 空标志:FIFO已空或将要空时由FIFO的状态电路送出的一个信号,以阻止FIFO的读操作继续从FIFO中读出数据而造成无效数据的读出;
- 满标志:FIFO已满或将要满时由FIFO的状态电路送出的一个信号,以阻止FIFO的写操作继续向FIFO中写数据而造成溢出;
- 读时钟:读操作所遵循的时钟,时钟沿到来时读取数据;
- 读指针:指向下一个要读出的地址,读完自动加1;
- 写时钟:写操作所遵循的时钟,时钟沿到来时写入数据;
- 写指针:指向下一个要写入地址,写完自动加1;
读写指针就是读写的地址,这个地址不能任意选择,而是连续的
- FIFO基本接口
FIFO可分为读数据一端和写数据一端
wr_en和rd_en分别为写/读使能端,wr_data和rd_data分别是要写入FIFO的数据和要从FIFO中读取的数据,fifo_full和fifo_empty分别为FIFO的满/空标志位
3. FIFO设计的原则
- 任何FIFO都不要向满FIFO中写入数据(写溢出)
- 任何FIFO都不要从空FIFO中读取数据(读溢出)
FIFO设计的核心在于判断空满状态,为了保证数据正确的写入或读出,而不发生溢出或读空的状态出现,必须保证FIFO在满的情况下,不能进行写操作。在空的状态下不能进行读操作。
4. 同步FIFO
- 读空状态:读地址指针追上写地址指针
- 写满状态:写地址指针再次追上读地址指针
5. 异步FIFO
5.1 异步FIFO结构
- FIFO框图
异步FIFO由五部分组成:写控制端、读控制端、FIFO Memory和两个时钟同步端
写控制端用于判断是否可以写入数据
读控制端用于判断是否可以读取数据
FIFO Memory用于存储数据
两个时钟同步端用于将读写时钟进行同步处理
-
FIFO基本接口图
-
完整的异步FIFO简化框图
• 写操作时,写使能有效且FIFO未满
• 读操作时,读使能有效且FIFO未空
两个使能信号和空满判断信号都连接到控制端上,再加上时钟信号和复位信号
5.2 异步FIFO空满判断
异步FIFO中,读写是在不同的时钟信号下进行的,因此在进行比较之前,应当先进行跨时钟与同步
在时钟同步之前,先将二进制地址转换为格雷码,因为格雷码相邻的两个状态之间,只有1 bit数据发生翻转
格雷码在相邻的两个码元之间只由一位变换(二进制码在很多情况下是很多码元在同时变化)。这就会避免计数器与时钟同步的时候发生亚稳态现象。但是格雷码有个缺点就是只能定义2n的深度,而不能像二进制码那样随意的定义FIFO的深度,因为格雷码必须循环一个2n,否则就不能保证两个相邻码元之间相差一位的条件;
二进制数与格雷码的对照图:
假设内圈为读,外圈为写
- 读空状态:写指针与读指针指向同一个地址
读地址和写地址相同,都指向了0010
- 写满状态:写指针再次追上读指针
在写满时,写指针比读指针多走一圈,此时写地址是1010,1010的格雷码是1111,0010个格雷码是0011,此时两个格雷码的高两位相反,低两位相同,以此来判断是否写满
6. 时钟同步
6.1 同步FIFO
读写指针在同一个时钟下,可以直接进行比较
6.2 异步FIFO
读写指针在不同时钟下,需要将两个地址指针进行时钟同步操作,常用的同步方法是两级同步打拍延迟,
同步地址指针的大致过程:
写操作时,先将写地址指针转换成格雷码,然后通过两级同步(两级同步在读时钟下进行),将写地址指针同步到读时钟域下;读操作类似
根据这个过程图,也可以看出空满判断的方式:
- 写满在写时钟下判断,将写地址指针的格雷码与同步过来的读地址指针格雷码进行比较,符合写满条件,即FIFO虚满
- 读空在读时钟下判断,将读地址指针的格雷码与同步过来的写地址指针格雷码进行比较,符合读空条件,即FIFO虚空
附1:
-
亚稳态:指触发器无法在某个规定时间段内达到一个可确认的状态。当一个触发器进入亚稳态引时,既无法预测该单元的输出电平,也无法预测何时输出才能稳定在某个正确的电平上。在这个稳定期间,触发器输出一些中间级电平,或者可能处于振荡状态,并且这种无用的输出电平可以沿信号通道上的各个触发器级联式传播下去。
-
虚空:
先确定读空的判断,读空判断是在rd_clk下,读指针的格雷码与写指针同步过来的格雷码进行比较,实际上,读指针追的是wr_ptr_grr
而wr_ptr_grr又是写指针留在原地的残影(写指针经过两个读时钟周期后得来的),在两个读时钟周期的这段时间,写指针可能会原地不动,也可能继续前行,即虚空。
- 格雷码<==>二进制码
公式表达:
-
二进制码—>格雷码
n位二进制码字中直接得到n位格雷码码字,步骤如下:
a.对n位二进制的码字,从右到左,以0到n-1编号
b.如果二进制码字的第i位和i+1位相同,则对应的格雷码的第i位为0,否则为1(当i+1=n时,二进制码字的第n位被认为是0,即第n-1位不变) -
格雷码—>二进制码
从左边第二位起,将每位与左边一位解码后的值异或,作为该位解码后的值(最左边一位依然不变)。依次异或,直到最低位。依次异或转换后的值(二进制数)就是格雷码转换后二进制码的值。
公式:
例:格雷码:0100 转二进制
Always@(*) begin
Bin[3] = gray[3]
Bin[2] = gray[2]^bin[3]
Bin[1] = gray[1]^bin[2]
Bin[0] = gray[0]^bin[1]
End