异步FIFO的设计思路及verilog代码

一:设计要点

1.结构框图

在这里插入图片描述
如上图所示的同步模块synchronize to write clk,其作用是把读时钟域的读指针rd_ptr采集到写时钟(wr_clk)域,然后和写指针wptr进行比较从而产生或撤消写满标志位wfull;类似地,同步模块synchronize to read clk的作用是把写时钟域的写指针wptr采集到读时钟域,然后和读指针rptr进行比较从而产生或撤消读空标志位rempty。
另外还有写指针wptr和写满标志位wfull产生模块,读指针rptr和读空标志位rempty产生模块,以及双端口存储RAM模块。

2.对读写指针的计数比较得出写满、读空

当FIFO为满或为空时,写入指针和读取指针都是相等的。但我们需要将“满”与“空”区分,当FIFO工作时,写指针在前,读指针紧跟写指针。当FIFO为满时,写指针往前移动,返回并等于后面跟随的读指针,这就是所谓的套圈。这个时候我们再增加1bit给读写指针,可以通过这个bit为0还是1来显示“满”或“空”。

2.1 二进制计数

异步FIFO读写指针需要在数学上的操作和比较才能产生准确的空满标志位,但由于读写指针属于不同的时钟域及读写时钟相位关系的不确定性,同步模块采集另一时钟域的指针时,此指针有可能正处在跳变的过程中在这里插入图片描述
上图中,rd_ptr2sync 3和4以及4和5之间的中间态是由于到各寄存器的时钟rd_clk存在偏差而引起的。二进制的递增操作,在大多数情况下都会有两位或者两以上的bit位在同一个递增操作内发生变化,但由于实际电路中会存在时钟偏差和不同的路径延时,二进制计数器在自增时会不可避免地产生错误的中间结果。

2.2格雷码计数

格雷码一个最大的特点就是在递增或递减的过程中,每次只变化一位,这是它最大的优点。同时它也有自己的局限性,那就是循环计数深度必须是2的n次幂,否则就失去了每次只变化一位的特性。
通过观察格雷码相邻位每次只有1位发生变化,上下两部分,除最高位相反,其余镜像对称。
在这里插入图片描述
7 --> 8 ,格雷码从 0100 --> 1100 ,只有最高位发生变化其余位相同
6 --> 9 , 格雷码从 0101 --> 1101 , 只有最高位发生变化其余位相同
那么进行空满判断的时候,就不是看最高位了,因为7-8的最高位不同,而其他位相同,在之前的判断中就会被判断为“满”,这就出现误判了。所以,用格雷码来判断时,还要考虑次高位。
当最高位和次高位相同,其余位相同认为是读空。
当最高位和次高位不同,其余位相同认为是写满。

2.3 跨时钟域的同步解决

读指针是属于读时钟域的,写指针是属于写时钟域的,而异步FIFO的读写时钟域不同,是异步的。如果将rclk的读指针和wclk的写指针直接比较肯定是错误的,我们需要进行同步处理进行比较。
方案格雷码+两级寄存器同步
(1)将写时钟域的写指针同步到读时钟域,将同步后的写指针与读时钟域的读指针进行比较产生读空信号
(2)将读时钟域的读指针同步到写时钟域,将同步后的读指针与写时钟域的写指针进行比较产生写满信号
两点注意
1.打两拍(两级寄存器同步):输入信号来自异步时钟域(比如FPGA芯片外部的输入),必须寄存两拍。第一拍将输入信号同步化,同步化后的输出可能带来建立/保持时间的冲突,产生亚稳态。需要再寄存一拍,减少(注意是减少)亚稳态带来的影响。
2.同步的指针和两者比较的指针都是格雷码指针!

2.4 二进制转化格雷码

二进制数 1 0 1 1 0
二进制数右移1位,空位补0 0 1 0 1 1
异或运算 1 1 1 0 1
这样就可以实现二进制到格雷码的转换了,总结就是移位并且异或,代码实现如下:
assign wgraynext = (wbinnext >> 1) ^ wbinnext
assign rgraynext = (rbinnext >> 1) ^ rbinnext

3.代码实现

6个module
1.顶层模块fifo.v

//异步FIFO 宽度8,深度16,地址4bit,多加1bit判断空满
//顶层模块 fifo.v
module fifo
#(parameter DSIZE = 8, parameter ASIZE = 4)
(
 output [DSIZE-1:0] rdata,
 output wfull,
 output rempty,
 input [DSIZE-1:0] wdata,
 input wclk,wrst,wr_en,
 input rclk,rrst,rd_en
);
//

wire [ASIZE-1:0] waddr,raddr;
wire [ASIZE:0] rptr,wptr,rq2_wptr,wq2_rptr;

// 

fifomem i1(
 .wdata(wdata),
 .waddr(waddr),
 .raddr(raddr),
 .wr_en(wr_en),
 .wclk(wclk),
 .wfull(wfull),
 .rdata(rdata)
);

sync_r2w i2(
 .wclk(wclk),
 .wrst(wrst),
 .rptr(rptr),
 .wq2_rptr(wq2_rptr)
);

sync_w2r i3(
 .rclk
  • 10
    点赞
  • 93
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值