Verilog功能模块——同步FIFO
前言
FIFO功能模块分两篇文章,本篇为同步FIFO,另一篇为异步FIFO,传送门:
Verilog功能模块——异步FIFO-CSDN博客
同步FIFO实现起来是异步FIFO的简化版,所以,本博文不再介绍FIFO实现原理,感兴趣的同学可以去看我异步FIFO的文章,基本看懂了异步FIFO,同步FIFO自然就懂了。
二. 模块功能框图与信号说明
信号说明:
| 分类 | 信号名称 | 输入/输出 | 说明 |
|---|---|---|---|
| 参数 | DATA_WIDTH | – | 数据位宽 |
| ADDR_WIDTH | – | 地址位宽,FIFO深度=2**ADDR_WIDTH | |
| FWFT_EN | – | First word fall-through输出模式使能,高电平有效 | |
| FIFO写端口 | din | input | FIFO数据输入 |
| wr_en | input | FIFO写使能 | |
| full | output | FIFO满信号 | |
| almost_full | output | FIFO快满信号,FIFO剩余容量<=1时置高 | |
| FIFO读端口 | dout | output | FIFO数据输出 |
| rd_en | input | FIFO读使能 | |
| empty | output | FIFO空信号 | |
| almost_empty | output | FIFO快空信号,FIFO内数据量<=1时置高 | |
| 时钟与复位 | clk | input | FIFO读时钟 |
| rst | input | FIFO读复位 |
注意:
- 信号的命名与Vivado中的FIFO IP核完全一致
- 复位均为高电平复位,与Vivado中的FIFO IP核保持一致
- 复位为异步复位
- FIFO深度通过ADDR_WIDTH来设置,所以FIFO的深度必然是2的指数,如2、4、8、16等
三. 部分代码展示
//++ 生成读写指针 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
reg [ADDR_WIDTH:0] rptr;
always @(posedge clk or posedge rst) beginif (rst)rptr <= 0;else if (rd_en & ~empty)rptr <= rptr + 1'b1;
endreg [ADDR_WIDTH:0] wptr;
always @(posedge clk or posedge rst) beginif (rst)wptr <= 0;else if (wr_en & ~full)wptr <= wptr + 1'b1;
endwire [ADDR_WIDTH-1:0] raddr = rptr[ADDR_WIDTH-1:0];
wire [ADDR_WIDTH-1:0] waddr = wptr[ADDR_WIDTH-1:0];wire [ADDR_WIDTH:0] rptr_p1 = rptr + 1'b1;
wire [ADDR_WIDTH:0] wptr_p1 = wptr + 1'b1;
//-- 生成读写指针 ------------------------------------------------------------//++ 生成empty与almost_empty信号 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
always @(*) beginif (rst)empty <= 1'b1;else if (rptr == wptr)empty <= 1'b1;elseempty <= 1'b0;
endalways @(*) beginif (rst)almost_empty <= 1'b1;else if (rptr_p1 == wptr || empty)almost_empty <= 1'b1;elsealmost_empty <= 1'b0;
end
//-- 生成empty与almost_empty信号 ------------------------------------------------------------//++ 生成full与almost_full信号 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
always @(*) beginif (rst)full <= 1'b1;else if ((wptr[ADDR_WIDTH] != rptr[ADDR_WIDTH])&& (wptr[ADDR_WIDTH-1:0] == rptr[ADDR_WIDTH-1:0]))full <= 1'b1;elsefull <= 1'b0;
endalways @(*) beginif (rst)almost_full <= 1'b1;else if (((wptr_p1[ADDR_WIDTH] != rptr[ADDR_WIDTH])&& (wptr_p1[ADDR_WIDTH-1:0] == rptr[ADDR_WIDTH-1:0]))|| full)almost_full <= 1'b1;elsealmost_full <= 1'b0;
end
//-- 生成full与almost_full信号 ------------------------------------------------------------
三. 功能仿真
比较以下情形中的fifo行为是否与FIFO IP核一致,
情形一:单次写单次读
情形二:写满后再读空
情形三:在读的过程中写,在写的过程中读
判断模块功能正常的依据:
- 写入数据是否按顺序正常读出
- 空信号和满信号是否正常输出。
为方便比较,编写了顶层文件,实例化了FIFO IP核与自编模块,部分代码如下:
vivado_sync_fifo vivado_sync_fifo_u0 (.clk (clk ), // input wire clk.rst (rst ), // input wire rst.din (din ), // input wire [7 : 0] din.wr_en (wr_en ), // input wire wr_en.rd_en (rd_en ), // input wire rd_en.dout (vivado_fifo_dout ), // output wire [7: 0] dout.full (vivado_fifo_full ), // output wire full.almost_full (vivado_fifo_almost_full ), // output wire almost_full.empty (vivado_fifo_empty ), // output wire empty.almost_empty (vivado_fifo_almost_empty)// output wire almost_empty
);syncFIFO # (.DATA_WIDTH (DATA_WIDTH),.ADDR_WIDTH (ADDR_WIDTH),.FWFT_EN (FWFT_EN )
) syncFIFO_inst (.din (din ),.wr_en (wr_en ),.full (full ),.almost_full (almost_full ),.dout (dout ),.rd_en (rd_en ),.empty (empty ),.almost_empty (almost_empty),.clk (clk ),.rst (rst )
);
testbench部分代码如下:
// 生成时钟
localparam CLKT = 2;
initial beginclk = 0;forever #(CLKT / 2) clk = ~clk;
end// 读写使能控制
initial beginrst = 1;#(CLKT * 2)rst = 0;wr_en = 0;rd_en = 0;#(CLKT * 2)wait(~full && ~vivado_fifo_full); // 两个FIFO都从复位态恢复时开始写// 写入一个数据wr_en = 1;#(CLKT * 1)wr_en = 0;// 读出一个数据wait(~empty && ~vivado_fifo_empty);// 两个FIFO都非空时开始读,比较读数据和empty信号是否有差异rd_en = 1;#(CLKT * 1)rd_en = 0;// 写满wr_en = 1;wait(full && vivado_fifo_full); // 两个FIFO都满时停止写,如果两者不同时满,则先满的一方会有写满的情况发生,但对功能无影响// vivado FIFO IP在FWFT模式时, 设定深度16时实际深度为17, 但仿真显示full会在写入15个数据后置高, 过几个时钟后后拉低,// 再写入一个数据, full又置高; 然后过几个时钟又拉低, 再写入一个数据置高, 如此才能写入17个数据// 所以这里多等待12个wclk周期, 就是为了能真正写满vivado FWFT FIFO#(CLKT * 12)wr_en = 0;// 读空wait(~empty && ~vivado_fifo_empty);rd_en = 1;wait(empty && vivado_fifo_empty); // 两个FIFO都空时停止读,如果两者不同时空,则先空的一方会有读空的情况发生,但对功能无影响rd_en = 0;#(CLKT * 10)$stop;
end// 使用以下代码时,先注释掉上面的读写使能控制initial
// 同时读写
// initial begin
// #(CLKT * 30)
// $stop;
// end// assign wr_en = ~full || ~vivado_fifo_full; // 未满就一直写
// assign rd_en = ~empty || ~vivado_fifo_empty; // 未空就一直读always @(posedge clk) beginif (rst)din <= 0;else if (wr_en && ~full && ~vivado_fifo_full)din <= din + 1;
endendmodule
8bit,16深度,FWFT FIFO仿真,波形如下:
可以看到模块输出的自编fifo与vivado fwft fifo的写端口和读端口行为是一致的,只是可能会超前或滞后一定的clk周期。
可以看到empty拉低时,数据已经有效了,所以自编模块实现了FWFT功能,Vivado FIFO的实际深度为17,所以它多读出了一个数据,空信号更晚拉高。
因篇幅问题,其它条件下的仿真不再展示,感兴趣的同学可通过更改testbench自行验证。
- FWFT_EN改为0,注意同步修改Vivado FIFO的配置
四. 工程分享
Verilog功能模块——同步FIFO,Vivado 2021.2工程。
欢迎大家关注我的公众号:徐晓康的博客,回复以下四位数字获取。
8302
建议复制过去不会码错字!
或者在我的码云仓库获取,传送门:
徐晓康/Verilog功能模块 - 码云 - 开源中国 (gitee.com)
徐晓康的博客持续分享高质量硬件、FPGA与嵌入式知识,软件,工具等内容,欢迎大家关注。
相关文章:
Verilog功能模块——同步FIFO
前言 FIFO功能模块分两篇文章,本篇为同步FIFO,另一篇为异步FIFO,传送门: Verilog功能模块——异步FIFO-CSDN博客 同步FIFO实现起来是异步FIFO的简化版,所以,本博文不再介绍FIFO实现原理,感兴趣…...
Unity ToLua热更框架使用教程(1)
从本篇开始将为大家讲解ToLua在unity当中的使用教程。 Tolua的框架叫LuaFramework,首先附上下载链接: https://github.com/jarjin/LuaFramework_UGUI_V2 这个地址的是UGUI的。 下载完之后导入项目,首先,我们要先让这个项目跑起…...
车载相关名词--车载数据中心方案
车载数据中心方案 参考链接:https://zhuanlan.zhihu.com/p/600031042?utm_id=0 下面这张图是小鹏汽车嵌入式系统高级专家 唐黾 在同ARM一起的一个演讲稿中发布的,是一张未来车载数据中心单芯片方案构想图。主要针对的是智驾域和座舱域融合方案,下面对如上图的内外部组件及…...
helm使用
前言 类似于 Linux 的 YUM、APT,Helm 是 K8S 的包管理工具。 Helm, 一个二进制工具,用来安装、升级、卸载 K8S 中的应用程序。 Helm Chart,一个 tgz 包,类似安卓的 APK。 K8S 应用打包成 Chart,通过 He…...
Python in Visual Studio Code 2023年10月发布
排版:Alan Wang 我们很高兴地宣布 Visual Studio Code 的 Python 和 Jupyter 扩展于 2023 年 10 月发布! 此版本包括以下公告: Python 调试器扩展更新弃用 Python 3.7 支持Pylint 扩展更换时的 Lint 选项Mypy 扩展报告的范围和守护程序模式G…...
Webmin远程命令执行漏洞复现报告
漏洞编号 CVE-2019-15107 漏洞描述 Webmin是一个基于Web的系统配置工具,用于类Unix系统。密码重置页面中存在此漏洞,允许未经身份验证的用户通过简单的 POST 请求执行任意命令。 影响版本 Webmin<1.920 漏洞评级 严重 利用方法(利…...
webstorm自定义文件模板(Vue + Scss)
最终效果如下: 具体配置如下: 新增文件代码如下: <!--* Description: ${COMPONENT_NAME} 页面* Author: mhf* Date: ${DATE} --> <template><div>${COMPONENT_NAME} </div> </template><script&g…...
楔子-写在之前
最近一年都在忙着一个项目,并且需要学习另一个领域的知识,从单片机过渡到了LINUX嵌入式,倒静不下心去写点东西。看了下之前写的东西,感觉已经过去了很久很久。现在项目快忙完了,准备把最近的心得给大家分享下。 前言 …...
第 5 章 数组和广义表(稀疏矩阵的三元组顺序表存储实现)
1. 背景说明 为了节省存储空间,可以对这类矩阵进行压缩存储。所谓压缩存储是指:为多个值相同的元只分配一个存储空间,对零元不分配空间。 2. 示例代码 1)status.h /* DataStructure 预定义常量和类型头文件 */ #include <string.h>#i…...
【RabbitMQ 实战】11 队列的结构和惰性队列
一、 队列的结构 队列的组成: 队列由 rabbit_amgqueue_process 和 backing_queue两部分组成。rabbit_amqqueue_process负责协议相关的消息处理,即接收生产者发布的消息、向消费者交付消息、处理消息的确认 (包括生产端的 confirm 和消费端的 ack) 等。…...
Python3-批量重命名指定目录中的一组文件,更改其扩展名
Python3-批量重命名指定目录中的一组文件,更改其扩展名 1.argparse模块2.vars内置函数3.os.listdir(path)4.os.path.splitext(filepath)5.os.path.join6.os.rename7.os.path.isfile8.批量重命名指定目录中的一组文件,更改其扩展名 1.argparse模块 argpa…...
渗透测试KAILI系统的安装环境(第八课)
KAILI系统的安装环境(第八课) Kaili是一款基于PHP7的高性能微服务框架,其核心思想是面向服务的架构(SOA),支持http、websocket、tcp等多种通信协议,同时还提供了RPC、Service Mesh、OAuth2等功能。Kaili框架非常适合构…...
如何正确方便的理解双指针?力扣102 (二叉树的层序遍历)
双指针,顾名思义就是指针的指针。 在此之前我们需要先理解单指针 (简称为指针)。指针很简单,直接上例子:例:现有两个变量,a10,b20. 要求:交换他们的值,输出的结果应为a20…...
Vue或uniapp引入自定义字体
一、为什么引入字体 对于大部分APP或网站而言,字体是很重要的一部分。在前端开发中,选用合适的字体往往会极大地提升网站的视觉体验。然而,网页中默认字体的种类和风格有限,且在不同的设备、浏览器上渲染效果不尽相同。因此&…...
力扣:LCR 122. 路径加密 题目:剑指Offer 05.替换空格(c++)
本文章代码以c为例! 力扣:LCR 122. 路径加密 题目: 代码: class Solution { public:string pathEncryption(string path) {for(int i0;i<path.size();i){if(path[i].){path[i] ;}}return path;} }; 难度升级(原…...
cJson堆内存释放问题
cJSON_Delete(),是用来释放json对象的,释放父JSON对象后,子JSON对象也会被释放。 CJSON_free(),是用来释放其他对象的。 int main(void) {cJSON* cjson_test NULL;cJSON* cjson_address NULL;cJSON* cjson_skill NULL;char* s…...
论文阅读/写作扫盲
第一节:期刊科普 JCR分区和中科院分区是用于对期刊进行分类和评估的两种常见方法。它们的存在是为了帮助学术界和研究人员更好地了解期刊的学术质量、影响力和地位。 JCR分区(Journal Citation Reports):JCR分区是由Clarivate Ana…...
一文拿捏对象内存布局及JMM(JAVA内存模型)
1 JMM(Java Memory Model) 1 概述 Java内存模型(Java Memory Model简称JMM)是一种抽象的概念,并不真实存在,它描述的一组规则或者规范。通过这些规则、规范定义了程序中各个变量的访问方式。jvm运行的程序的实体是线程,而每个线程运行时&am…...
Android组件通信——ActivityGroup(二十五)
1. ActivityGroup 1.1 知识点 (1)了解ActivityGroup的作用; (2)使用ActivityGroup进行复杂标签菜单的实现; (3)使用PopupWindow组件实现弹出菜单组件开发; 1.2 具体…...
js的继承的方式
1.对象冒充继承 使用 bind,call,apply 解决构造函数属性的继承 缺点:不能继承原型上的属性和方法 //-------------父类-------------function Person(name, age, sex) {this.name name;this.age age;this.sex sex;}Person.prototype.run function () {console.log(我${this…...
Linux驱动开发实战:为I.MX6ULL编写一个DS18B20的字符设备驱动(从设备树到应用测试)
Linux驱动开发实战:I.MX6ULL平台DS18B20字符设备驱动全流程解析 在嵌入式Linux开发领域,能够完整实现一个符合内核规范的设备驱动是工程师的核心能力之一。本文将带您深入探索如何为I.MX6ULL处理器开发DS18B20温度传感器的标准字符设备驱动,…...
Git Bisect 实战:用二分法快速找到引入 Bug 的提交
前言 项目跑了一段时间以后,最麻烦的 Bug 往往不是一眼能看出来的语法错误,而是那种“之前明明是好的,现在突然坏了”的回归问题。 比如某个接口在上个月还能正常返回数据,最近发版后开始报错;某个页面之前可以打开&am…...
PPTist免费在线演示文稿制作完全指南:从零到专业演示的终极教程
PPTist免费在线演示文稿制作完全指南:从零到专业演示的终极教程 【免费下载链接】PPTist PowerPoint-ist(/pauəpɔintist/), An online presentation application that replicates most of the commonly used features of MS PowerPoint, al…...
告别手动写Testbench!用Quartus II + ModelSim自动生成仿真模板的保姆级教程
Quartus II ModelSim自动化测试框架实战:从零构建高效数字电路验证流程 在数字电路设计领域,验证工作往往消耗工程师60%以上的开发时间。传统手动编写Testbench的方式不仅效率低下,还容易引入人为错误。Altera Quartus II内置的Test Bench T…...
3个步骤:彻底释放华硕笔记本性能的终极指南
3个步骤:彻底释放华硕笔记本性能的终极指南 【免费下载链接】g-helper Lightweight Armoury Crate alternative for Asus laptops with nearly the same functionality. Works with ROG Zephyrus, Flow, TUF, Strix, Scar, ProArt, Vivobook, Zenbook, Expertbook, …...
Zabbix 7.0 在 Ubuntu 上启用中文界面语言(zh_CN)
Zabbix 7.0 配置中文选项(zh_CN) 适用于 Zabbix 7.0 系统默认情况下语言文件不包含中文的情况。环境说明 Zabbix 版本:7.0.15(LTS)问题现象 Language 下拉框中 Chinese (zh_CN) 是灰色不可选;原因是系统未安…...
3分钟搞定Windows右键菜单:ContextMenuManager终极优化指南
3分钟搞定Windows右键菜单:ContextMenuManager终极优化指南 【免费下载链接】ContextMenuManager 🖱️ 纯粹的Windows右键菜单管理程序 项目地址: https://gitcode.com/gh_mirrors/co/ContextMenuManager 你是否曾经在Windows右键菜单中迷失方向&…...
别再傻傻用IO翻转了!用STM32的SPI+DMA驱动WS2812灯带,实测1920颗灯珠依然稳如老狗
STM32 SPIDMA驱动WS2812灯带:从时序优化到千级灯珠稳定控制实战 1. 为什么GPIO翻转方案在大型项目中频频翻车? 很多嵌入式开发者初次接触WS2812灯带时,都会尝试用GPIO翻转来实现控制——毕竟看起来只需要一根信号线,似乎用普通IO口…...
curtains.js数学工具详解:Vec2、Vec3、Mat4和Quat的使用方法
curtains.js数学工具详解:Vec2、Vec3、Mat4和Quat的使用方法 【免费下载链接】curtainsjs curtains.js is a lightweight vanilla WebGL javascript library that turns HTML DOM elements into interactive textured planes. 项目地址: https://gitcode.com/gh_m…...
UE5运行时动态调整游戏视口:解决UI遮挡导致物体位置偏移的实战方案
UE5运行时动态调整游戏视口:解决UI遮挡导致物体位置偏移的实战方案 当你在UE5项目中设计了一个精美的HUD界面,却发现那些半透明的UI元素正在悄悄改变游戏世界的坐标规则——原本应该出现在屏幕中心的角色突然偏离了位置。这不是视觉错觉,而是…...
