异步fifo_异步FIFO设计
由于知乎编辑器对markdown支持性问题,本文为直接上传markdown文档,格式混乱且图像不全,格式完整版请移步个人博客
异步FIFO设计qiankun214.github.io
1.设计目标
设计一个参数可配置的异步FIFO,要求:
- FIFO深度从4开始在2的幂次方连续可配(4、8、16、......)
- 读写时钟域相位差、频率差任意(同步器参数可配)
2.参数列表
| 名称 | 默认值 | 说明 | | --------- | ------ | -------------------------- | | DEPTH_LOG | 4 | FIFO容量为$2^{DEPTH_LOG}$ | | DATA_WIDTH | 8 | 数据位宽 |
3.端口
3.1.端口列表
3.1.1.系统端口
| 名称 | 类型 | 位宽 | 说明 | | --------- | ----- | ---- | -------------------- | | read_clk | input | 1 | 读时钟域时钟 | | write_clk | input | 1 | 写时钟域时钟 | | rst_n | input | 1 | 系统复位端口,低有效 |
3.1.2.读端口
| 名称 | 类型 | 位宽 | 说明 | | ---------- | ------ | --------- | -------------- | | read_req | input | 1 | 读完成信号 | | read_valid | output | 1 | 读数据有效信号 | | read_data | output | DEPTH_LOG | 读数据 | | fifo_empty | output | 1 | FIFO空信号 |
3.1.3.写端口
| 名称 | 类型 | 位宽 | 说明 | | ---------- | ------ | --------- | ---------- | | write_req | input | 1 | 写请求信号 | | write_data | input | DEPTH_LOG | 写数据 | | fifo_full | output | 1 | FIFO满信号 |
3.2.端口时序
3.2.1.读端口时序
read_req
信号拉高表示请求读数据,若此时FIFO非空(fifo_empty
为低),FIFO将会将数据置于read_data
上,同时拉高read_valid
信号。即当read_valid
有效时,对应的read_data
上的数据有效。fifo_empty
拉高表示FIFO已空,当前数据输出端口上的数据无意义, 再拉高read_req
将不会改变read_data
上的数据。
3.2.2.写端口时序
写端口如上所示,当且仅当write_req
信号高且fifo_full
信号低时将write_data
端口上的数据写入FIFO。
4.系统结构
4.1.结构框图
系统整体结构如上所示,分为两个时钟域——读时钟域和写时钟域。每个时钟域结构相互镜像:
- 读/写指针:二进制的读写指针,用于SRAM的读/写地址
- 二进制到格雷码转换器:将读/写指针从二进制转为格雷码,用于传递到下一个时钟域或生产空满信号
- 空/满信号生成:比对读指针和写指针的格雷码,生成空和满信号
其他还有跨时钟域的组件,分别为:
- 双口SRAM:一个端口使用写时钟和写时钟域下的信号,另一个使用读时钟和读时钟域的信号
- 同步器:两个同步器,分别将读指针同步到写时钟域和将写时钟同步到读时钟域
4.2.系统方法
4.2.1.二进制转格雷码
假设二进制码为每位为$bin[n]$,对应的格雷码每位为$gray[n]$,共N位,转换算法为: $$ begin{cases} gray[N-1] = bin[N - 1] gray[i] = bin[i] NOR bin[i+1] & i < N-1 end{cases} $$ 例如二进制码011
,共3位,则格雷码第2位为0
,其他几位为10
,对应格雷码为010
,在具体实现时,可以参考下图的实现方法:
4.2.2.格雷码判空判满
对读指针和写指针有以下含义:
- 读指针:指向当前正在读的地址
- 写指针:指向下一次写入操作需要写入的地址
二进制下,对于地址位宽为N的SRAM,可以使用位宽为N+1的地址——低N位为地址,MSB为标志位,用于标记满和空:
- 当低N位相等,MSB不相等时:FIFO满(写指针领先读指针“一圈”)
- 当低N为相等,MSB相等时:FIFO空(读指针“追上”写指针)
转换到格雷码域,做相同判断,判空条件为两个指针相等,相等的二进制码对应格雷码相等,条件不变。对于判满,需要两个二进制仅有最高位不同,参考二进制转格雷码条件,判满条件如下:
- 最高位不相等(格雷码MSB与二进制MSB相同)
- 次高位不相等(次高位由二进制码的最高位和次高位异或,两指针二进制下最高位不同,次高位相同)
- 其他位均相等(异或操作依赖的位数均相等)
由于同步器的同步需要消耗时钟周期,因此:
- 判满:在写时钟域下生成满信号,读指针通过同步器,为若干个时钟周期之前的读指针。若在FIFO满的情况下,读操作发生,读指针的变化延迟传递到写时钟域,在传递的若干个周期内状态为“假满”
- 判空:在读时钟域下生成空信号,写指针通过同步器,为若干个时钟周期之前的写指针。若在FIFO空的情况下,写操作发生,写指针的变化延迟传递到读时钟域,在传递的若干个周期内状态为“假空”
“假满”和“假空”状态均不影响异步FIFO的正常工作,仅为略微降低FIFO的工作效率
4.2.3.同步器
同步器是一种跨时钟域数据传输的方法,二级同步器结构如下所示:
从源时钟域下的源信号开始,依次通过多个时钟为目标时钟域时钟下的寄存器,即构成了多级同步器,寄存器的数量就是同步器的级数。一般的信号仅需要二级同步器,高速信号一般使用三级同步器。
5.实现细节
5.1.写FIFO部分
写FIFO部分包括以下几个组件:
- 同步器:将读指针从读时钟域同步到写时钟域,使用两级同步器
- 写指针:指示写入地址的指针,当满信号拉低且写请求拉高时加1
- 写指针二进制转格雷码:将写指针从二进制转为格雷码,送到判满部分判满和向读时钟域的同步器
- 满信号生成:当满足[4.2.2]的判满条件成立时,拉高满信号
5.1.1.需求
写FIFO部分的需求如下:
- 产生写SRAM的相关信号,包括写请求信号,写地址信号和写数据信号
- 同步内部读指针,配合写指针生成满信号。将写指针传递到读部分。
5.1.2.端口
| 名称 | 类型 | 位宽 | 说明 | | ---------------- | ------ | ----------- | -------------------- | | clk | input | 1 | 写部分时钟 | | rst_n | input | 1 | 系统复位 | | write_req | input | 1 | 写FIFO请求 | | fifo_full | output | 1 | FIFO满信号 | | write_addr | output | DEPTH_LOG | 写存储器地址 | | read_point_gray | input | DEPTH_LOG+1 | 读指针格雷码,未同步 | | write_point_gray | output | DEPTH_LOG+1 | 写指针格雷码 |
5.1.3.实现
上图为fifo_full
生成部分的结构图,为了保证保证fifo_full
拉高的及时性,设置next_write_point_gray
寄存器,指示下一个格雷码的写地址。当一次is_write
拉高时,每个部件的功能如下所示:
write_point
:自增1write_point_gray
:从next_write_point_gray
获取与write_point
同步的格雷码next_write_point_gray
:取现在write_point加2后对应的格雷码,获得与write_point+1
同步的格雷码
写产生FIFO满的波形如下所示:
当一次写请求使FIFO满时,由于写请求发生,因此使用next_write_point_gray
进行判满操作,此时该信号与read_point_gray
相等,因此在下一个时钟周期fifo_full
拉高(图中a,b->c),同时,write_point
和write_point_gray
均完成更新。下一个时钟周期,无写请求发生,因此使用write_point_gray
进行判满操作,此时write_point_gray
更新后与read_point_gray
相等,保持fifo满状态(图中e,d->f)。
对于数据部分,如下图所示:
该部分不包括在写控制模块中,系统输入的write_data
端口直接连接到SRAM的写数据端口,写请求端口为write_req
和fifo_full
的组合逻辑与信号(write_req && !fifo_full
)
5.2.读FIFO部分
读FIFO部分包括以下几个组件:
- 同步器:将写指针从写时钟域同步到读时钟域,使用两级同步器
- 读指针:指示读取地址的指针,当空信号拉低且读请求拉高时加1
- 读指针二进制转格雷码:将读指针从二进制转为格雷码,送到判空部分判空和向写时钟域的同步器
- 空信号生成:当满足[4.2.2]的判空条件成立时,拉高空信号
5.2.1.需求
读FIFO部分需要满足以下几个需求:
- 产生读SRAM的相关信号,包括地址信号,数据有效信号
- 同步内部写指针,配合读指针生成空信号。将读指针传递到读部分。
5.2.2.端口
| 名称 | 类型 | 位宽 | 说明 | | ---------------- | ------ | ----------- | -------------------- | | clk | input | 1 | 读时钟信号 | | rst_n | input | 1 | 系统复位信号,低有效 | | read_req | input | 1 | 读请求信号 | | fifo_empty | output | 1 | FIFO空信号 | | memory_read_addr | output | DEPTH_LOG | SRAM的读地址信号 | | read_point_gray | output | DEPTH_LOG+1 | 读指针格雷码 | | write_point_gray | input | DEPTH_LOG+1 | 写指针格雷码,未同步 | | read_valid | output | 1 | 读数据有效信号 |
5.2.3.实现
实现的方式与写部分类似,fifo_empty
信号和读指针生成如下所示:
主要部件的功能如下所示:
- read_point:读指针,产生读地址,每当读请求成立时自增1
- read_point_gray:读指针的格雷码,用于产生空逻辑和向写时钟域传递
- next_read_point_gray:下一个读指针的格雷码,用于空信号的及时性
读数据部分如上图所示,read_valid信号在read_req && !fifo_empty
为真时拉高,表示当前read_data
上的数据有效。read_data
为输出数据端口直接连接到SRAM的输出端口(SRAM输出端口自带寄存器)。
异步fifo_异步FIFO设计相关推荐
- 异步fifo_同步FIFO设计实现
在学习跨时钟域处理的时候,有一种方法是用异步FIFO来处理跨时钟域处理的.那么在这之前先看看同步FIFO实现. 所谓同步FIFO,就是读写时钟是同一个时钟频率.本次实现是通过计数器的形式来实现满空标志 ...
- 异步fifo_异步FIFO
本文使用 Zhihu On VSCode 创作并发布 概述 异步FIFO用来在两个异步时钟域间传输数据. 如上图所示,两个系统"System X" 和 "System Y ...
- 异步fifo_【推荐】数字芯片异步FIFO设计经典论文
之前有一篇文章我已经推荐过了数字芯片跨时钟域设计的经典论文 ([推荐]数字芯片跨时钟域设计经典论文 ),希望看过的读者都有一定的收获.不过有点遗憾的是那片论文中虽然提到了异步FIFO,却没有讲具体的原 ...
- 基于FPGA的异步FIFO设计
今天要介绍的异步FIFO,可以有不同的读写时钟,即不同的时钟域.由于异步FIFO没有外部地址端口,因此内部采用读写指针并顺序读写,即先写进FIFO的数据先读取(简称先进先出).这里的读写指针是异步的, ...
- 异步FIFO设计:各个模块的作用及Verilog代码详解
实现原理参考:异步FIFO---Verilog实现_alangaixiaoxiao的博客-CSDN博客_异步fifo 代码参考:IC基础(一):异步FIFO_MaoChuangAn的博客-CSDN博客 ...
- 异步FIFO设计原理及Verliog源代码
1.什么是FIFO? FIFO是英文First In First Out 的缩写,是一种先进先出的数据缓存器,他与普通存储器的区别是没有外部读写地址线,这样使用起来非常简单,但缺点就是只能顺序写入数据 ...
- 基于 FPGA 的高级数字电路设计(7)单口 RAM、同步 FIFO、异步 FIFO 设计
一.单口 RAM 设计 module BRAM_PORTA( input clka, input ena, input wea, input [3:0] addra, input [15:0] din ...
- 异步fifo设计及验证verilog代码
论文参考:The Design and Verification of a Synchronous First-In First-Out 博客参考:[原创]异步FIFO设计原理详解 (含RTL代码和T ...
- IC设计 — 同步FIFO和异步FIFO设计实现(一)
文章目录 1. FIFO介绍 1.1 FIFO参数 1.2 full/empty 检测 1.3 同步FIFO和异步FIFO 2. FIFO设计 2.1 二进制和格雷码 2.2 同步FIFO 2.3 异 ...
最新文章
- oracle数据库详细性能参数,ORACLE数据库性能参数的优化
- tensorflow学习入门笔记
- js中cookie操作
- java 8 排序反转_Java 8 排序小结
- C++中比较两个浮点数是否相等
- python十进制转换_Python方法如何将普通IP转换为十进制IP
- c语言合法常量e8,c语言合法常量定义
- html5学习笔记---05.JavaScript 中的面向对象,继承和封装
- java学习--基础知识阶段性总结--JDK5新特性
- 箭头函数写法_初探ES6:箭头函数
- CAD测量图纸时数据显示不出来怎么办?
- springboot Could not resolve placeholder
- ESP32|基于ESP32制作的低成本、可拓展性高的NES游戏机(1)(开源ESP32 NES模拟器)-效果演示及介绍
- Html中怎么用CSS让ul中多个li标签不换行横排显示
- 嵩天-Python语言程序设计程序题--第六周:组合数据类型
- Android Studio中模拟器如何输入中文、将模拟器语言设置为中文
- 2022年黄石市高企申报奖励补贴以及认定奖励补贴汇总!
- 【安全】Shellshock漏洞
- HTML5相关的知识。
- C++剑指offer:解题报告之DP优化学习记 (二) ——浅论DP斜率优化 (Print Article 【HDU - 3507】 )
热门文章
- 《Lua程序设计》第6章 深入函数 学习笔记
- 用Eclipse进行java学习的步骤
- VMware vSphere开发(1)安装配置VMware vSphere Web Services SDK的运行环境
- Linux下mysql主从配置
- 打开PDF文件弹出阅读未加标签文档的解决方法
- pytorch 常用问题解决
- webpack项目代理异常解决
- 构建ASP.NET MVC4+EF5+EasyUI+Unity2.x注入的后台管理系统(13)-系统日志和异常的处理③
- windows安装TensorFlow和Keras遇到的问题及其解决方法
- Git问题Everything up-to-date解决