IC学习笔记3——异步FIFO

异步FIFO的工作内容与同步FIFO类似,但是异步FIFO的控制并不像同步FIFO那么简单,因为异步FIFO工作在不同的时钟域,这将会带来一些问题,比如空满检测?是否还可以像同步FIFO通过计数器来判断?是否需要同步电路?这些问题将会在本章节一一讨论。

一、异步FIFO的空满检测

1. 同步FIFO的空满检测

因为同步FIFO工作在一个时钟域,可以通过一个计数器来判断空满。
当同步FIFO写入一次数据,计数器加1.
当同步FIFO读出一次数据,计数器减1.
当同步FIFO同时进行一次读写操作,计数器的值不变。
这时就可以通过计数器的值来判断空满,当计数器的值为0,则表示同步FIFO中没有可读的数据,此时同步FIFO为空。
当计数器的值等于同步FIFO的深度时,则表示同步FIFO中已经写满了。

2. 异步FIFO的空满检测

2.1 计数器检测空满

异步FIFO是否可以通过同步FIFO这种计数器的方式实现空满检测。假如可以,那么在异步FIFO中对计数器的描述
always@(posedge wclk or posedge rclk),这种代码综合过程中是没有实际的触发器与之对应的。
实际的触发器只有两种,一种是是对一个时钟边沿敏感—>always@(posedge clk)。另一种是除了对一个时钟边沿敏感,还有一个异步复位端—>always@(posedge clk or negedge rst_n)

2.2 指针比较检测空满

可以通过比较写指针和读指针来判断空满,如下图所示,先对异步FIFO写入数据1,写两次,然后对异步FIFO读两次,把之前写进去的数据1都读出来,已经没有数据可读,所以此时异步FIFO处于空状态。注意此时写指针和读指针相等,都是指向地址为2的存储空间。
然后对异步FIFO写数据0,写6次,此时写指针重新指向地址0所对应的存储空间,此时的状态不是满状态,因为之前写入两次数据1已经被读出,此时地址0和地址1还是可以写入数据的,再对异步FIFO写数据0,写两次,此时异步FIFO中所有的存储空间都写入数据,并且没有一个数据是被读出过的,所以此时是满状态,此时也是写指针和读指针相等。

所以可以总结当读指针追上写指针时,异步FIFO处于空状态。
写指针追上读指针时,异步FIFO处于满状态。但是这种方法处理后,仍然有一个问题就是读写指针相等时,难以区分是空状态还是满状态。

2.3 扩展指针比较检测空满

针对上面指针比较空满出现的问题,有人提出,对指针最高位进行扩展,即指针加宽一位,当写指针超出FIFO深度时,这额外的一位就会发生改变。FIFO的深度决定了指针扩展前的宽度,而这扩展的一位与FIFO深度无关,是为了标志指针多转了一圈。
因此,当读写指针完全相同时,此时FIFO为空状态。
当读写指针最高位不同,其余位宽相同时,FIFO为满状态。
用扩展指针的方式分析上面的例子,如下图所示,空状态时,rptr=0010,wptr=0010,读写指针完全相同,为空状态。
满状态时,rptr=0010,wptr=1010,读写指针最高位不同,其余位宽相同,为满状态。

经过指针扩展,可以进行空满检测。但是异步FIFO读写时钟不同,而读写指针又是分属各自的时钟域,在进行空满检测的时候,是需要将读写指针进行跨时钟域处理的。
使用二进制的方式很容易出现错误,在跨时钟域的时候,相邻二进制地址变化时,不止一位发生变化。比如写指针从0111到1000跳变时,4位地址都可以发生改变,这样读时钟在进行写指针同步后得到的写指针可能是0000~1111中任意一个值,这些都是不可控的,出错的概率非常大。

2.4 格雷码指针比较检测空满

直接扩展读写指针可能因为多位改变导致错误。因此采用格雷码的方式,利用格雷码每次只变化一位的特征,降低同步发生错误的概率。如下图所示,其中0~7为真实的FIFO地址,而8-15是指针多转一圈以后的地址,实际对应还是0-7对应的存储空间。此时应该注意,此时是按照格雷码方式编码,不能再用二进制的方式来判断空满。比如说位置6(0101)和位置9(1101),除最高位不同,其余位相同,应该是满状态,但是位置6(0101)对应的满状态应是14(1001)。

因此格雷码的检测标准为:
当最高位和次高位均相同,其余为相同,FIFO空
当最高位和次高位均相反,其余为相同,FIFO满

所以异步FIFO最终的空满检测方式为:将二进制指针转换为格雷码,用于另一时钟域接收,随后按照检测条件进行检测。

二、异步FIFO的模块端口和内部电路图

2.1 异步FIFO的模块端口


异步FIFO相比较同步FIFO外部端口引脚类似。
wclk为写时钟,rclk为读时钟。
wrst_n为写复位信号,rrst_n为读复位信号。
winc为写使能信号,rinc为读使能信号。
wdata[7:0]为输入数据。
rdata[7:0]为输出数据。
wfull为写满信号。
rempty为读空信号。

2.2 异步FIFO的内部电路


异步FIFO的内部电路主要分为5个部分,会在下面部分一一详细介绍。在这里主要介绍一下内部的信号。
wptr为写指针,写指针的位数比写地址多一位。
rptr为读指针,读指针的位数比读地址多一位。
waddr为写地址,为具体把数据写入FIFO_Memory的地址。
raddr为读地址,为具体读出FIFO_Memory中数据的地址。
wq2_rptr为将读指针同步到写时钟域的信号。
rq2_wptr为将写指针同步到读时钟域的信号。

三、异步FIFO的电路设计

3.1 写指针&满信号&写地址

第一部分就是异步FIFO的写指针、满信号和写地址产生的电路设计,详细电路图如下所示。

代码如下:

     module wptr_wfull #(parameter ADDRSIZE=4)(  input                                        winc,input                                        wclk,input                                        wrst_n,input         [ADDRSIZE:0]                   wq2_rptr,output reg                                   wfull,output reg    [ADDRSIZE:0]                   wptr,output        [ADDRSIZE-1:0]                 waddr);wire              full_value;wire [ADDRSIZE:0] wbinnext , wgraynext;reg  [ADDRSIZE:0] wbin;//写地址产生     assign wbinnext=wbin+(winc&!wfull);                                              always@(posedge wclk or negedge wrst_n)  beginif(wrst_n==1’b0) wbin<=0;           elsewbin<=wbinnext;        endassign waddr=wbin[ADDRSIZE-1:0];        //写指针产生    assign wgraynext=wbinnext^(wbinnext>>1);always @(posedge wclk or negedge wrst_n) beginif(wrst_n==1’b0)wptr <=0;elsewptr<=wgraynext;end//满信号产生assign  full_value=wgraynext == ({~wq2_rptr[ADDRSIZE:ADDRSIZE-1],wq2_rptr[ADDRSIZE-2:0]});always@(posedge wclk or negedge wrst_n)beginif(wrst_n==1’b0)wfull<=1’b0;elsewfull<=full_value; endendmodule

3.2 读指针&空信号&读地址

第二部分就是异步FIFO的读指针、空信号和读地址产生的电路设计,电路图如第一部分类似,因此不再具体介绍。
代码如下:

     module rptr_rempty #(parameter ADDRSIZE=4)(  input                                        rinc,input                                        rclk,input                                        rrst_n,input        [ADDRSIZE:0]                    rq2_wptr,output reg                                   rempty,output reg   [ADDRSIZE:0]                    rptr,output       [ADDRSIZE-1:0]                  raddr);wire empty_value;wire [ADDRSIZE:0] rbinnext , rgraynext;reg  [ADDRSIZE:0] rbin;//读地址产生     assign rbinnext=rbin+(rinc&!rempty);always@(posedge rclk or negedge rrst_n)                   beginif(rrst_n ==1’b0)                   rbin <=0;            elserbin <=rbinnext;        endassign raddr=rbin[ADDRSIZE-1:0];//读指针产生    assign rgraynext=rbinnext^(rbinnext>>1);always@(posedge rclk or negedge rrst_n)beginif(rrst_n ==1’b0)           rptr <=0; elserptr<=rgraynext;end//空信号产生assign  empty_value=rgraynext == rq2_wptr;always@(posedge rclk or negedge rrst_n)beginif(rrst_n==1’b0)rempty<=1’b0;elserempty<=empty_value; endendmodule

3.3 读指针同步

第三部分是读指针的同步,将读指针打两拍同步到写时钟域去,具体电路如下图所示。
代码如下:

           module sync_r2w #(parameter ADDRSIZE=4)(  input                       wclk,input                       wrst_n,input       [ADDRSIZE:0]    rptr,output reg  [ADDRSIZE:0]    wq2_rptr);reg [ADDRSIZE:0] wq1_rptr;always@(posedge wclk or negedge wrst_n)beginif(wrst_n==1’b0){wq2_rptr, wq1_rptr}<=2’b0;else{wq2_rptr, wq1_rptr}<= {wq1_rptr, rptr} ;       endendmodule

3.4 写指针同步

第四部分是写指针的同步,将写指针打两拍同步到读时钟域去,电路图如第三部分类似,不再具体介绍。
代码如下:

      module sync_w2r #(parameter ADDRSIZE=4)(  input                                    rclk,input                                    rrst_n,input         [ADDRSIZE:0]               wptr,output reg    [ADDRSIZE:0]               rq2_wptr);reg [ADDRSIZE:0] rq1_wptr;always@(posedge rclk or negedge rrst_n)beginif(rrst_n==1’b0){rq2_wptr, rq1_wptr}<=2’b0;else{rq2_wptr, rq1_wptr}<= {rq1_wptr, wptr};       endendmodule

3.5 数据读取

第五部分是数据的读取,具体电路如2.2异步电路中标记为5的部分所示。
代码如下:

         module fifomem #(parameter ADDRSIZE=4,parameter DATASIZE=8)(input                                   winc,input                                   wclk,input                                   wfull,input   [ADDRSIZE-1:0]   waddr , raddr,input   [DATASIZE-1:0]   wdata ,  output  [DATASIZE-1:0]   rdata);localparam DEPTH=1<<ADDRSIZE;reg [DATASIZE-1:0] mem [0:DEPTH-1];assign rdata=mem[raddr];always@(posedge wclk)beginif(! wfull & winc)mem[waddr]<= wdata;endendmodule

3.6 整合

将上述5个部分整合在一起就形成一个完整的异步FIFO。

         module afifo #(parameter ADDRSIZE=4,parameter DATASIZE=8)(input   wclk,input   rclk,input   wrst_n,input   rrst_n,input   winc,input   rinc,input    [DATASIZE-1:0]  wdata,output   [DATASIZE-1:0]  rdata,output   rempty,output   wfull);wire [ ADDRSIZE:0] wq2_rptr;wire [ ADDRSIZE:0] wptr;wire [ ADDRSIZE-1:0] waddr;wire [ ADDRSIZE:0] rq2_wptr;wire [ ADDRSIZE:0] rptr;wire [ ADDRSIZE-1:0] raddr;wptr_wfull u1(.winc(winc),.wclk(wclk),.wrst_n(wrst_n),.wq2_rptr(wq2_rptr),.wfull(wfull),.wptr(wptr),.waddr(waddr));rptr_rempty u2(  .rinc(rinc),.rclk(rclk),.rrst_n(rrst_n),.rq2_wptr(rq2_wptr),.rempty(rempty),.rptr(rptr),.raddr(raddr));sync_r2w  u3(  .wclk(wclk),.wrst_n(wrst_n),.rptr(rptr),.wq2_rptr(wq2_rptr));sync_w2r u4(.rclk(rclk),.rrst_n(rrst_n),.wptr(wptr),.rq2_wptr(rq2_wptr));fifomem u5(.winc(winc),.wclk(wclk),.wfull(wfull),.waddr(waddr), .raddr(raddr),.wdata(wdata),  .rdata(rdata));endmodule

四、仿真验证

4.1 仿真代码

  module afifo_tb();reg        wclk;reg        rclk;reg        wrst_n;reg        rrst_n;reg        winc;reg        rinc;reg  [7:0] wdata;wire [7:0] rdata;wire       rempty;wire       wfull;afifo u6(.wclk(wclk),.rclk(rclk), .wrst_n(wrst_n),.rrst_n(rrst_n),.winc(winc),.rinc(rinc),.wdata(wdata),.rdata(rdata),.rempty(rempty),.wfull(wfull));initial begin                    //设置写时钟,写周期是20ns,50Mhzwclk=0;forever    #10     wclk=~wclk;endinitial begin                    //设置读时钟,读周期是10ns,100Mhzrclk=0;forever    #5      rclk=~rclk;endinitial beginwrst_n=1'b0;     //写复位rrst_n=1'b0;     //读复位winc =1'b0;     //写无效rinc =1'b0;     //读无效wdata=0;        //初始写数据为0#28     wrst_n=1'b1;    //松开写复位rrst_n=1'b1;    //松开读复位winc =1'b1;     //写有效wdata=1;        //输入数据为1@(posedge wclk);//写入数据     repeat(7)       //接着写入2,3,4,5,6,7,8这些数据begin#18;wdata=wdata+1'b1;@(posedge wclk);  end#18    wdata=wdata+1'b1;  //此时异步FIFO已经写满了,在往同步FIFO中写数据8//8这个数据不会被写进@(posedge rclk);   #8      rinc=1’b1;      //读使能,写无效 winc=1'b0;@(posedge rclk);     //第一个读出的数为1repeat(7)        //读取剩余的数begin@(posedge rclk);   end#2;rinc=1‘b0;        //结束读操作end
endmodule

4.2 仿真波形

IC学习笔记3——异步FIFO相关推荐

  1. Python学习笔记:异步IO(3)

    前言 最近在学习深度学习,已经跑出了几个模型,但Pyhton的基础不够扎实,因此,开始补习Python了,大家都推荐廖雪峰的课程,因此,开始了学习,但光学有没有用,还要和大家讨论一下,因此,写下这些帖 ...

  2. Python学习笔记:异步IO(2)

    前言 最近在学习深度学习,已经跑出了几个模型,但Pyhton的基础不够扎实,因此,开始补习Python了,大家都推荐廖雪峰的课程,因此,开始了学习,但光学有没有用,还要和大家讨论一下,因此,写下这些帖 ...

  3. IC学习笔记1——建立时间和保持时间

    IC学习笔记1--建立时间和保持时间 前言 为了自己以后需要这些知识的时候,可以方便查阅,仅仅代表自己的观点,不一定正确. 一.建立时间和保持时间 1.1 触发器 建立时间.保持时间和传输延迟时间都是 ...

  4. SwiftUI学习笔记之异步数据请求

    SwiftUI学习笔记之异步数据请求 方法一 方法描述: 结合使用 ObservableObject @Published @ObservedObject ObservableObject 定义自己的 ...

  5. Python学习笔记:异步IO(1)

    前言 最近在学习深度学习,已经跑出了几个模型,但Pyhton的基础不够扎实,因此,开始补习Python了,大家都推荐廖雪峰的课程,因此,开始了学习,但光学有没有用,还要和大家讨论一下,因此,写下这些帖 ...

  6. linux pipe 命名管道,linux 进程学习笔记-named pipe (FIFO)命名管道

    与"无名管道"不同的是,FIFO拥有一个名称来标志它,所谓的名称实际上就是一个路径,比如"/tmp/my_fifo",其对应到磁盘上的一个管道文件,如果我们用f ...

  7. 学习笔记 线程异步请求过程

    记录学习线程异步请求的过程 版本1 不使用线程时,正常情况下执行过程. # -*- coding:utf-8 -*- # 日期:2018/5/27 14:50 # Author:小鼠标 import ...

  8. 多路选择器MUX总结-IC学习笔记(八)

    多路复用器是一种组合电路,它从许多输入信号中选择一个作为输出,本文先介绍两个MUX的简单应用,主要关于如何将verilog与物理实现对应:第二当MUX作为时钟切换电路时如何避免毛刺(glitch). ...

  9. IC学习笔记20——VCS的使用(一)仿真事件队列

    一.VCS的Verilog仿真事件队列 1.1 仿真队列介绍 数字仿真工具VCS是如何处理我们叫给他们的代码,如下图所示: 第一步:将所有initial和always块和连续赋值语句读进去,将这些语句 ...

最新文章

  1. easypoi必填项_GitHub - wangjingting/poi-utils: help you more easy read or write excel file
  2. python函数的定义域_python中多线程的变量定义域问题
  3. Android模拟器访问pc与网络的问题
  4. 华为手机鸿蒙系统名单,鸿蒙系统:前三批升级名单曝光,有荣耀手机!
  5. 2019年清华自主招生部分试题
  6. 水星mw310r虚拟服务器,水星MW310R静态网络(IP)设置教程
  7. python怎么清除代码_Python如何清空列表?清空列表的4种方法(代码示例)
  8. mysql主从架构升级_实战项目——mysql主从架构的实现
  9. Lighttpd 的安装配置(web服务器软件)
  10. D. Magic Breeding
  11. 一套代码在不同的电脑执行快慢_电脑如何选配之硬盘篇
  12. 20150430 调试分析之 根据内核报错信息栈信息分析错误
  13. 利用maven的resources、filter和profile实现不同环境使用不同配置文件
  14. html静态网页设计实训总结,网页设计实训心得体会范文
  15. 关于Android直接连MySQL获取数据的真机测试的一些坑
  16. 装配区5s管理制度推行办法
  17. html5 h5是什么,H5和HTML的区别是什么
  18. 免费Web托管公司000Webhost被黑 1350万明文密码泄露
  19. 胶囊网络用于推荐系统问题(MIND,CARP)
  20. HBuilderX连接苹果手机iPhone预览移动端页面

热门文章

  1. 小程序开发效率提升(持续更新)
  2. 解决win10内存占用逐渐变大(亲测有效)
  3. android 软件备份工具,android备份软件 知乎 备份软件 知乎
  4. 【自】2014会计准则科目和主要账务处理对照
  5. DPU芯片头部企业云豹智能加入龙蜥社区,共同推动新一代数据中心基础设施蓬勃发展
  6. 淘宝滞销宝贝怎么处理?面对滞销宝贝怎么正确处理?
  7. 微信发布4条新规!再也不用帮好友拼团砍价了,网友纷纷称赞
  8. 小程序开发API之监听加速计wx.startAccelerometer
  9. ​【交通标志识别】基于BP神经网络实现交通标志识别matlab代码
  10. 小明身高180cm,小刚身高165cm,计算两人的身高差