异步fifo(1)

什么时异步fifo

FIFO,即First In First Out ,是一种先进先出的数据缓存器,异步FIFO 是指读写时钟不一致,读写时钟是互相独立的。数据从一个时钟域写入FIFO缓冲区,并从另一个时钟域的同一FIFO缓冲区中读取数据,使用异步FIFO可以将数据安全地从一个时钟域传递到另一个时钟域。

异步fifo的组成

异步FIFO的核心部件就是一个 Simple Dual Port RAM ;左右两边的长条矩形是地址控制器,负责控制地址自增、将二进制地址转为格雷码以及解格雷码;下面的两对D触发器 sync_r2w 和 sync_w2r 是同步器,负责将写地址同步至读时钟域、将读地址同步至写时钟域。

异步FIFO主要由以下几部分组成:双端口ram(即中心的部件)、左右两边的地址控制器,下面的两对D触发器。其中地址控制器负责控制地址自增加、将二进制地址转为格雷码以及解格雷码写指针产生逻辑、读指针产生逻辑及空满标志产生逻辑。两对D触发器 则负责将写地址同步至读时钟域、将读地址同步至写时钟域。我们知道,在异步FIFO,中读写操作是由两个完全不同时钟域的时钟所控制。在写时钟域部分,由写指针所产生逻辑生成写端口所需要的写地址和写控制信号;在读时钟域部分,由读指针产生逻辑生成读断口所需要的读地址和读控制信号。

FIFO的接口

宽度(width):FIFO一次读写操作的数据位,
深度(depth),FIFO可以存储多少个数据。
wfull:FIFO已满或将要满时由FIFO的状态电路送出的一个信号,以阻止FIFO的写操作继续向FIFO中写数据而造成溢出(overflow)。
rempty:FIFO已空或将要空时由FIFO的状态电路送出的一个信号,以阻止FIFO的读操作继续从FIFO中读出数据而造成无效数据的读出(underflow)。
wr_clk:写操作的工作时钟,在每个时钟沿来临时写数据。

rd_clk:读操作的工作时钟,在每个时钟沿来临时读数据。

w_en:异步FIFO的写使能

r_en:异步fifo的读使能
读指针:指向下一个读出地址,读完后自动加1。
写指针:指向下一个要写入的地址的,写完自动加1。
读写指针其实就是读写的地址,只不过这个地址不能任意选择,而是连续的。

如何判断空满?

我们知道,使用异步FIFO最重要的地方在于如何判断其空满。因为异步FIFO的读写使用了不同的时钟,因此不能采用常规的计数器方法来产生空满标志符。

当前的解决方法就是使用读写指针来判断,什么意思呢?当系统复位的时候读写指针全部清零,此时此刻读写指针相等时;当数据读出速率大于写入速率的时候,读指针赶上了写指针,FIFO为空,如图所示:
在这里插入图片描述

当读写指针指向了同一地址,但写指针超前整整一圈,这就说明整个fifo已经被写满了
在这里插入图片描述

为了区分到底是满状态还是空状态,我们可以在指针中添加在添加一位,这样的话,当写指针增加并越过最后一个FIFO地址时,将会直接进位,其他位置0;对读指针也进行同样的操作。因此对于深度为2^n的FIFO,其需要的地址宽度为n,需要的读写指针位宽为(n+1)位。举个例子:如对于深度为256的FIFO,需要采用8bit的地址宽度,读写指针则需要9位。

如果两个指针的最高位不同,其他位相同,说明写指针比读指针多折回了一次;如r_addr_ptr=0000,而w_addrr_ptr= 1000,为满。如果两个指针的MSB相同,其余位相等,则说明两个指针折回的次数相等,说明FIFO为空。

格雷码的使用

讲到这里,大家可能认为就没有什么大问题了,其实不然,我们知道,将一个二进制的计数值从一个时钟域同步到另一个时钟域的时候很容易出现问题,因为采用二进制计数器时所有位都可能同时变化,在同一个时钟沿同步多个信号的变化会产生亚稳态问题。而使用格雷码只有一位变化,因此在两个时钟域间同步多个位不会产生问题。所以需要一个二进制到gray码的转换电路,将地址值转换为相应的gray码,然后将该gray码同步到另一个时钟域进行对比,作为空满状态的检测。

二进制转换为格雷码:二进制数的最高位保持不变, 后续位依次与前一位进行异或运算。判断读空时 :将写时钟域的写指针同步到读时钟,然后与读时钟域的读指针进行比较,每一位都完全相同才判断为读空;判断写满时:需要 写时钟域的格雷码wgray_next 和 被同步到写时钟域的读指针wr2_rp 高两位不相同,其余各位完全相同。

假空假满现象

这里有空两格问题需要讨论:使用格雷码进行空满判断一定正确么?如果不正确的话,是不是不应该使用该方法呢?我们一个一个问题来看。

首先我们先设想将读指针同步到写时钟域下:读指针同步到写时钟域需要时间T,在经过T时间后,可能原来的读指针会增加或者不变,也就是说同步后的读指针一定是小于等于原来的读指针的。写指针也可能发生变化,但是写指针本来就在这个时钟域,所以是不需要同步的,也就意味着进行对比的写指针就是真实的写指针。此时我们一定要记住,同步过来的读指针实际上是时间T之前的读指针,而并非此时此刻的读指针。如果我们进行写满判断的时候,此刻同步过来的读指针应该小于或等于此刻没有同步过来的读指针,就算出现了写满,那也是假满。还是可以往里面写的,但是我们不管真满假满,我们只知道满了。就不会往里面写数据了,那么这就不是一种错误设计。可以想象一下,假设一个深度为256的FIFO,在写到第254个数据的时候就报了“写满”,大不了FIFO的深度我少用一点点就是的。但是这是安全的
读空判断:如果我们在写时钟域下进行判空,即也就是同步后的读指针追上了写指针。但是原来的读指针是大于等于同步后的读指针的,所以实际上这个时候读指针实际上是超过了写指针。这种情况意味着已经发生了“读空”,却仍然有错误数据读出。所以这种情况就造成了FIFO的功能错误。这时候输出的是真空信号,但是会造成“读空”,所以不可取。因此万万不可以在写时钟域下进行判空。
接下来我们设想将写指针同步到读时钟域下:
  写指针同步到读时钟域需要时间T,在经过T时间后,可能原来的写指针会增加或者不变,也就是说同步后的写指针一定是小于等于原来的写指针的。读指针也可能发生变化,但是读指针本来就在这个时钟域,所以是不需要同步的,也就意味着进行对比的读指针就是真实的读指针。

读空判断:我们知道同步过来的写指针是小于此时此刻真实的写指针的,也就是说这种情况是“假读空”。。可以想象一下,假设某个FIFO,在读到还剩2个数据的时候就报了“读空”,大不了我先不读了,等数据多了再读,但是这也是安全的。
写满判断:也就是同步后的写指针超过了读指针一圈。我们知道同步过来的写指针是小于此时此刻真实的写指针的,所以实际上这个时候写指针已经超过了读指针不止一圈,这种情况意味着已经发生了“写满”,却仍然数据被覆盖写入。所以是不行的
  所以总结一下,判断读空在读时钟域,判断写满在写时钟域。那么假读空会不会造成有数据在FIFO里面读不出来?答案是不会,同步时虽然延迟了两个信号,但是最终还是会同步到跨时钟域,所以假读空信号不会一直有效,还是会在延后几个周期把数据读出来。
  

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/29204.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

博弈论--sg函数

sg函数------ 定义终止状态的SG函数值为0。如果游戏已经结束,即达到了终止状态,那么对应的SG函数值就是0。即先手的sg值为0,则先手必败,否则先手必胜。 如何求sg函数值--------对于每个可能的移动,将后续状态的SG函数…

Centos 7 使用国内镜像源更新内核

内核选择参考 此博文 :https://blog.csdn.net/alwaysbefine/article/details/108931626 elrepo官网介绍的内核升级方式为: 一、按文档执行引入 elrepo库; # 1、引入公钥 rpm --import https://www.elrepo.org/RPM-GPG-KEY-elrepo.org# 2、安…

JVM学习之内存与垃圾回收篇1

文章目录 1 JVM与Java体系结构1.0 Java发展重大事件1.1 虚拟机和Java虚拟机1.3 JVM整体结构1.4 Java代码执行流程1.5 JVM架构模型1.6 JVM的生命周期1.7 JVM发展历程 2 类加载子系统2.1 ClassLoader2.2 用户自定义类加载器2.2.1 为什么需要自定义类加载器2.2.2 自定义类加载器的…

go初识iris框架(二) - get,post请求和数据格式

继初步了解iris后 文章目录 获取url路径获取数据get请求post请求获取JSON数据格式JSON返回值获取XML数据格式XML返回值 获取url路径 package mainimport "github.com/kataras/iris/v12"func main(){app : iris.New()app.Get("/hello",func(ctx iris.Conte…

blender 建模马拉松

效果展示 蘑菇模型创建: 创建蘑菇头 shift A ,创建立方体; 右下工具栏添加细分修改器(视图层级:2,渲染:2);tab键进入编辑模式,alt z 进入透显模式&…

Java:输入与输出

目录 输入输出args 输入Scanner 输入格式化输出文件输入与输出 输入输出 args 输入 利用main函数中的参数args,当然也可以起别的名字。其他语言也是一样的。输入时空格分隔。 args的作用:在程序启动时可以用来指定外部参数 Scanner 输入 需要import j…

[Linux] 守护进程介绍、服务器的部署、日志文件...

守护进程 我们使用的系统中, 一般以服务器的方式工作 对外提供服务的服务器, 都是以守护进程的方式在系统中工作的. 比如, 我们使用Linux服务器时, 大多都会使用一些终端软件通过ssh远程连接服务器使用. 这就是因为, Linux服务器中 通常默认运行着 ssh服务器的守护进程: 守护…

vue数组对象快速获取最大值和最小值(linq插件各种常用好用方法),提高开发效率

需求:因后端传入的数据过多,前端需要在数组中某一值的的最大值和最小值计算,平常用的最多的不就是遍历之后再比对吗,或者用sort方法等实现,同事交了我一招,一句话就可以获取到数组对象中最大值和最小值&…

【Jenkins】Jenkins构建前端流水线

目录 一、前言二、新建前端流水线1、点击新建任务2、填写流水线名称(这里我选择的是自由风格的软件项目),任务名称一般格式为:项目名称-前后端3、创建成功后的结果 三、配置前端流水线1、进入刚创建好的任务页面中,点击…

133、仿真-基于51单片机太阳能热水器水温水位智能监控仪报警设计(Proteus仿真+程序+配套资料等)

方案选择 单片机的选择 方案一:STM32系列单片机控制,该型号单片机为LQFP44封装,内部资源足够用于本次设计。STM32F103系列芯片最高工作频率可达72MHZ,在存储器的01等等待周期仿真时可达到1.25Mip/MHZ(Dhrystone2.1)。内部128k字节…

基于FPGA的一维卷积神经网络算法实现(1D-CNN、BNN的FPGA加速实现)

文章目录 概要网络结构一维卷积介绍(科普性质)FPGA架构FPGA端口定义操作步骤结果演示总结 概要 本文介绍一种基于FPGA的1维卷积神经网络算法加速实现的方案,其中为了进一步提升运算速度,除了第一层卷积采用的是普通卷积运算&…

在Redis主从系统中使用哨兵

一、什么是哨兵 Redis的哨兵(Sentinel)是Redis分布式系统中的一种特殊角色,用于监控和管理Redis主从复制架构中的主节点(master)和从节点(slave)。 哨兵的主要功能是确保Redis系统的高可用性。它…