编程语言异步FIFO总结+Verilog实现

编程语言异步FIFO总结+Verilog实现

异步FIFO简介

异步FIFO(First In First Out)可以很好解决多比特数据跨时钟域的数据传输与同步问题。异步FIFO的作用就像一个蓄水池,用于调节上下游水量。

FIFO

FIFO是一种先进先出的存储结构,其与普通存储器的区别是,FIFO没有读写地址总线,读写简单,但相应缺点是无法控制读写的位置,只能由内部的读写指针自动加,顺序读写数据。FIFO示意图如下:

图1

如图1所示,输入信号有读写时钟、读写复位信号、读写使能信号、写数据;输出信号有空满信号、读数据

异步时序电路

异步时序逻辑指电路时序逻辑没有接在统一的时钟脉冲上,或者电路中无时钟脉冲,如SR锁存器构成的时序电路,电路中各存储单元的状态不是同时发生的。

图2

如上图所示,常见的异步时序电路有不同的时钟。
相应地,同步时序电路指电路中所有受时钟控制的单元都接在统一的全局时钟源上,存储电路状态的转换在同一时钟源的同一脉冲边沿下同步进行。
异步时序电路触发器状态刷新不同步,信号延迟可能会累积导致输出结果异常,应当避免。
目前ASIC与FPGA的设计中,通常是全局异步,局部同步的设计方法,但需注意异步信号与同步电路的交互问题。
常用的异步时序逻辑同步的方法有:

  • 单比特信号同步:结绳法
  • 多比特信号同步:SRAM异步FIFO

注意,时钟域是否相同针对的是时钟源点,如果不同时钟都是从同一个PLL生成,则这些时钟相位和倍数都可控,认为是同步时钟;若不同时钟是由不同PLL生成,则即使这些时钟为相同频率,也认为是异步时钟,因为这些时钟间的相位关系无法确定。

亚稳态

亚稳态指触发器无法在某个规定的时间内到达一个可确定的状态。当一个触发器进入亚稳态时,无法确定该单元的输出电平,也无法确定其何时能稳定在正确的电平。在此期间,触发器输出的一些不确定电平,可能沿着信号通道上的各个触发器传递下去。

设计详解

思路

如图1,

  • 异步FIFO是一个存储结构,并且可读可写,因此需要一个双口RAM;
  • 其次异步FIFO读写时钟域分别控制读写地址,因此需要读写地址生成模块;
  • 异步FIFO需要判断是否已写满,或已读空,且读写时钟为异步时钟,因此需要同步逻辑与判断空满逻辑

图3

如图3所示,DualRAM为双口RAM模块,sync_w2r模块用于控制写地址,判断写满信号,sync_r2w模块用于控制读地址,判断读空信号。

细节

双口RAM

双口RAM设计较为简单,主要为生成一块memory,将写数据写入写地址对应内存空间,从读地址对应内存空间读取读数据,原理图如下:

图4

小细节,已知地址宽度ASIZE,求FIFO深度DEPTHDEPTH = 2 ^ ASIZE,可用移位实现:

DEPTH = 1 << ASIZE;

判断空满

上文提到,FIFO只能通过内部地址指针自动加,因此需要有空满判断逻辑,以免写数据溢出,读数据已空。本设计中判断空满采用的方法是比较读地址与写地址。读写时钟为异步时钟,在判断空满时需要用格雷码比较读写读写地址,因此需要对读写地址进行同步。

同步

同步使用打一拍的方法,即将待同步信号延时一个时钟周期,原理图如下:

图5

在写时钟域同步读地址,在读时钟域同步写地址。

格雷码

上述提到的打一拍的同步方法适合于单比特信号,但显然读写地址都大概率不为单比特信号。我们知道格雷码的特征为相邻格雷码间只有一位不同。将读写地址转换为格雷码即可应用打一拍的同步方法。

BinaryGray
000000
001001
010011
011010
100110
101111
110101
111100

图6

上图为三位二进制码与格雷码的转换。可以看出,二进制向格雷码转换时,格雷码最高位为二进制码最高位,格雷码次高位为二进制码最高位与次高位的异或,其余各位规律一致。

assign graynext = (binnext >> 1) ^ binnext;                                      `

本设计为地址位宽为4位,利用格雷码判断空满时需扩展1位.

判断空

判断FIFO是否为空,在读时钟域同步转换为格雷码的写地址,与转换为格雷码的写地址比较,如果读写地址的格雷码完全相等,则说明FIFO已空。

//判断空信号
assign empty = (graynext == rq2_wptr);
always @(posedge rclk or negedge rrst_n) begin
    if (!rrst_n) begin
       rempty <= 1'b1;
    end
    else begin
       rempty <= empty;
    end
end

判断满

判断FIFO是否已满也是比较读写地址。在二进制地址中,FIFO已满时,读写地址相等,与已空时一样,无法判断。上述说到判断空满时地址需扩展一位,实际上如果已写满,说明写比都快,那写地址比读地址多走一轮,此时扩展的最高位不相同,如4'b00004'b1000,最高位扩展位,4'b1000说明比4'b0000多走一轮。转换为格雷码分别为4'b00004'b1100。可知FIFO已满时,读写地址格雷码最高位与次高位相反,其余位相同。

//判断满信号
assign full = (graynext == {~wq2_rptr[ASIZE: ASIZE - 1],
                wq2_rptr[ASIZE - 2: 0]});
always @(posedge wclk or negedge wrst_n) begin
    if (!wrst_n) begin
        wfull <= 1'b0;
    end
    else begin
        wfull <= full;
    end
end

控制读写地址

控制读写地址时,若读写使能为0,则不读写,读写地址不变;若读写使能为1,则读写地址加1。
小技巧,可将读写地址加读写使能信号,则可巧妙实现上述功能。

assign binnext = !wfull? (wbin + write_en): wbin;
assign binnext = !rempty? (rbin + read_en): rbin;

仿真

VCS仿真结果如下

图7

完整代码

top.v

点击查看代码

sync.v

点击查看代码

sync_w2r.v

点击查看代码

sync_r2w.v

点击查看代码

DualRAM.v

点击查看代码

top_tb.sv

点击查看代码

参考链接
Verilog描述——异步时序电路与同步时序电路浅析_我要变强Wow-CSDN博客_同步时序电路和异步时序电路差异
同步时序电路和异步时序电路_ltfysa的博客-CSDN博客_同步时序电路和异步时序电路差异
芯动力——硬件加速设计方法_中国大学MOOC(慕课) (icourse163.org)
异步FIFO设计 - 知乎 (zhihu.com)
异步FIFO总结 - 乔_木 - 博客园 (cnblogs.com)

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值