IC学习笔记3——异步FIFO
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相关推荐
- Python学习笔记:异步IO(3)
前言 最近在学习深度学习,已经跑出了几个模型,但Pyhton的基础不够扎实,因此,开始补习Python了,大家都推荐廖雪峰的课程,因此,开始了学习,但光学有没有用,还要和大家讨论一下,因此,写下这些帖 ...
- Python学习笔记:异步IO(2)
前言 最近在学习深度学习,已经跑出了几个模型,但Pyhton的基础不够扎实,因此,开始补习Python了,大家都推荐廖雪峰的课程,因此,开始了学习,但光学有没有用,还要和大家讨论一下,因此,写下这些帖 ...
- IC学习笔记1——建立时间和保持时间
IC学习笔记1--建立时间和保持时间 前言 为了自己以后需要这些知识的时候,可以方便查阅,仅仅代表自己的观点,不一定正确. 一.建立时间和保持时间 1.1 触发器 建立时间.保持时间和传输延迟时间都是 ...
- SwiftUI学习笔记之异步数据请求
SwiftUI学习笔记之异步数据请求 方法一 方法描述: 结合使用 ObservableObject @Published @ObservedObject ObservableObject 定义自己的 ...
- Python学习笔记:异步IO(1)
前言 最近在学习深度学习,已经跑出了几个模型,但Pyhton的基础不够扎实,因此,开始补习Python了,大家都推荐廖雪峰的课程,因此,开始了学习,但光学有没有用,还要和大家讨论一下,因此,写下这些帖 ...
- linux pipe 命名管道,linux 进程学习笔记-named pipe (FIFO)命名管道
与"无名管道"不同的是,FIFO拥有一个名称来标志它,所谓的名称实际上就是一个路径,比如"/tmp/my_fifo",其对应到磁盘上的一个管道文件,如果我们用f ...
- 学习笔记 线程异步请求过程
记录学习线程异步请求的过程 版本1 不使用线程时,正常情况下执行过程. # -*- coding:utf-8 -*- # 日期:2018/5/27 14:50 # Author:小鼠标 import ...
- 多路选择器MUX总结-IC学习笔记(八)
多路复用器是一种组合电路,它从许多输入信号中选择一个作为输出,本文先介绍两个MUX的简单应用,主要关于如何将verilog与物理实现对应:第二当MUX作为时钟切换电路时如何避免毛刺(glitch). ...
- IC学习笔记20——VCS的使用(一)仿真事件队列
一.VCS的Verilog仿真事件队列 1.1 仿真队列介绍 数字仿真工具VCS是如何处理我们叫给他们的代码,如下图所示: 第一步:将所有initial和always块和连续赋值语句读进去,将这些语句 ...
最新文章
- easypoi必填项_GitHub - wangjingting/poi-utils: help you more easy read or write excel file
- python函数的定义域_python中多线程的变量定义域问题
- Android模拟器访问pc与网络的问题
- 华为手机鸿蒙系统名单,鸿蒙系统:前三批升级名单曝光,有荣耀手机!
- 2019年清华自主招生部分试题
- 水星mw310r虚拟服务器,水星MW310R静态网络(IP)设置教程
- python怎么清除代码_Python如何清空列表?清空列表的4种方法(代码示例)
- mysql主从架构升级_实战项目——mysql主从架构的实现
- Lighttpd 的安装配置(web服务器软件)
- D. Magic Breeding
- 一套代码在不同的电脑执行快慢_电脑如何选配之硬盘篇
- 20150430 调试分析之 根据内核报错信息栈信息分析错误
- 利用maven的resources、filter和profile实现不同环境使用不同配置文件
- html静态网页设计实训总结,网页设计实训心得体会范文
- 关于Android直接连MySQL获取数据的真机测试的一些坑
- 装配区5s管理制度推行办法
- html5 h5是什么,H5和HTML的区别是什么
- 免费Web托管公司000Webhost被黑 1350万明文密码泄露
- 胶囊网络用于推荐系统问题(MIND,CARP)
- HBuilderX连接苹果手机iPhone预览移动端页面
热门文章
- 小程序开发效率提升(持续更新)
- 解决win10内存占用逐渐变大(亲测有效)
- android 软件备份工具,android备份软件 知乎 备份软件 知乎
- 【自】2014会计准则科目和主要账务处理对照
- DPU芯片头部企业云豹智能加入龙蜥社区,共同推动新一代数据中心基础设施蓬勃发展
- 淘宝滞销宝贝怎么处理?面对滞销宝贝怎么正确处理?
- 微信发布4条新规!再也不用帮好友拼团砍价了,网友纷纷称赞
- 小程序开发API之监听加速计wx.startAccelerometer
- ​【交通标志识别】基于BP神经网络实现交通标志识别matlab代码
- 小明身高180cm,小刚身高165cm,计算两人的身高差