Verilog | FIFO简单实现
FIFO( First Input First Output)简单说就是指先进先出,也是缓存机制的一种,下面是我总结的 FIFO 的三大用途:
1)提高传输效率,增加 DDR 带宽的利用率。比如我们有 4 路视频数据缓存到 DDR 中去,比较笨的方法是,每个通道视频数据对应一颗 DDR。现在对于 DDR 来说非常浪费,因为现在的 DDR3 可以跑 1600Mbps DDR4 可以跑到2400Mbps,如果你还是把一路视频数据对应一颗 DDR 显然严重浪费了带宽。加入 FIFO 后,只要把 4 路数据先缓存进入 DDR,在缓存的过程中,快速得把数据从 FIFO 取出并且写入到 DDR 中,只要 FIFO 没有满就不会出现数据丢失。现在我们带宽够用,FIFO 给的足够大就可以确保数据不丢失。
2)数据位宽转换,比如我们有 32bit 的数据需要转换成 128bit 或者 32bit 的数据需要转换成 8bit,那么用 FIFO 来转换也是非常方便的。
3)跨时钟域的应用,比如数据是 2 个不同步的时钟,那么我们就可以用 FIFO 实现跨时钟域的传输。
以上总计的三点,很多时候是混合使用的。
FIFO的重点和难点是空满状态的判断。
同步FIFO
同步FIFO是指读写数据使用的是同一个时钟,所以不用进行跨时钟域处理。有两种设计方法:高位扩展法和计数器法
本程序设置了统计FIFO内部数据数量的计数器cnt,并根据计数器的大小判断空满。设FIFO的深度是DEPTH,如果cnt==0,说明FIFO内没有数据;如果cnt==DEPTH,说明FIFO已存满。
计数器根据读写信号自增或者自减。当读写同时进行时,计数器数值不变;当有效写入时计数器减1;当有效读取时,计数器加1。
`timescale 1ns/1ns
/**********************************RAM************************************/
module dual_port_RAM #(parameter DEPTH = 16,parameter WIDTH = 8)(input wclk,input wenc,input [$clog2(DEPTH)-1:0] waddr //深度对2取对数,得到地址的位宽。,input [WIDTH-1:0] wdata //数据写入,input rclk,input renc,input [$clog2(DEPTH)-1:0] raddr //深度对2取对数,得到地址的位宽。,output reg [WIDTH-1:0] rdata //数据输出
);reg [WIDTH-1:0] RAM_MEM [0:DEPTH-1];always @(posedge wclk) beginif(wenc)RAM_MEM[waddr] <= wdata;
end always @(posedge rclk) beginif(renc)rdata <= RAM_MEM[raddr];
end endmodule /**********************************SFIFO************************************/
module sfifo#(parameter WIDTH = 8,parameter DEPTH = 16
)(input clk , input rst_n ,input winc ,input rinc ,input [WIDTH-1:0] wdata ,output reg wfull ,output reg rempty ,output wire [WIDTH-1:0] rdata
);reg [$clog2(DEPTH)-1:0] waddr, raddr;reg [$clog2(DEPTH) :0] cnt;always@(posedge clk or negedge rst_n) beginif(~rst_n)waddr <= 0;elsewaddr <= winc&~wfull? waddr+1: waddr;endalways@(posedge clk or negedge rst_n) beginif(~rst_n)raddr <= 0;elseraddr <= rinc&~rempty? raddr+1:raddr;endalways@(posedge clk or negedge rst_n) beginif(~rst_n)cnt <= 0;else if(rinc&~rempty&winc&~wfull)cnt <= cnt;else if(winc&~wfull)cnt <= cnt + 1;else if(rinc&~rempty)cnt <= cnt - 1;elsecnt <= cnt;endalways@(posedge clk or negedge rst_n) beginif(~rst_n) beginwfull = 0;rempty = 0;endelse beginwfull = cnt == DEPTH;rempty = cnt == 0;endenddual_port_RAM #(.DEPTH(DEPTH ),.WIDTH(WIDTH ))myRAM(.wclk (clk ), .wenc (winc&~wfull ), .waddr(waddr ), .wdata(wdata ), .rclk (clk ), .renc (rinc&~rempty), .raddr(raddr ), .rdata(rdata ));
endmodule
异步FIFO
异步FIFO的与同步FIFO的核心区别是它的读时钟和写时钟是不同步的。所以用对比读写地址的方法产生空满信号时,要进行跨时钟域处理。为了降低亚稳态可能性,异步FIFO还引入了格雷码。同时,格雷码也更方便产生空满信号。
| 二进制 | 写地址 | 读地址 | 格雷码 | 写地址 | 读地址 |
|---|---|---|---|---|---|
| 空FIFO | 0 0000 | 0 0000 | 0 0000 | 0 0000 | |
| 写满 | 1 0000 | 0 0000 | 1 1000 | 0 0000 | |
| 读空 | 1 0000 | 1 0000 | 1 1000 | 1 1000 | |
| 写满 | 0 0000 | 1 0000 | 0 0000 | 1 1000 | |
| 读空 | 0 0000 | 0 0000 | 0 0000 | 0 0000 |
FIFO深度为16时,地址位宽位5,当最高位和次高位不相同,其余位相同认为是写满;当所有位相同认为是读空。


异步FIFO主要包含四部分:读写地址发生器、格雷码的产生与打拍、空满信号发生器以及RAM。
`timescale 1ns/1ns/***************************************RAM*****************************************/
module dual_port_RAM #(parameter DEPTH = 16,parameter WIDTH = 8)(input wclk,input wenc,input [$clog2(DEPTH)-1:0] waddr //深度对2取对数,得到地址的位宽。,input [WIDTH-1:0] wdata //数据写入,input rclk,input renc,input [$clog2(DEPTH)-1:0] raddr //深度对2取对数,得到地址的位宽。,output reg [WIDTH-1:0] rdata //数据输出
);reg [WIDTH-1:0] RAM_MEM [0:DEPTH-1];always @(posedge wclk) beginif(wenc)RAM_MEM[waddr] <= wdata;
end always @(posedge rclk) beginif(renc)rdata <= RAM_MEM[raddr];
end endmodule /***************************************AFIFO*****************************************/
module asyn_fifo#(parameter WIDTH = 8,parameter DEPTH = 16
)(input wclk , input rclk , input wrstn ,input rrstn ,input winc ,input rinc ,input [WIDTH-1:0] wdata ,output wire wfull ,output wire rempty ,output wire [WIDTH-1:0] rdata
);parameter addr_width = $clog2(DEPTH);//写指针--二进制reg [addr_width:0]wptr_bin,rptr_bin;always@(posedge wclk or negedge wrstn)beginif(!wrstn) wptr_bin <= 0;else if(winc && !wfull) wptr_bin <= wptr_bin +1;else ;end//读指针--二进制always@(posedge rclk or negedge rrstn)beginif(!rrstn) rptr_bin <= 0;else if(rinc && !rempty) rptr_bin <= rptr_bin +1;else ;end// 指针二进制转格雷码wire [addr_width:0]wptr_gray,rptr_gray;assign wptr_gray = wptr_bin ^ wptr_bin>>1;assign rptr_gray = rptr_bin ^ rptr_bin>>1;//reg [addr_width:0]wptr,rptr;always @(posedge wclk or negedge wrstn)beginif(!wrstn) wptr <= 0;else wptr <= wptr_gray;end// always @(posedge rclk or negedge rrstn)beginif(!rrstn) rptr <= 0;else rptr <= rptr_gray;end// 经两级锁存器进行时钟同步reg [addr_width:0]sync_r2w,rptr_temp,sync_w2r,wptr_temp;// 写时针同步always @(posedge wclk or negedge wrstn)beginif(!wrstn) beginsync_r2w <= 0 ;rptr_temp <= 0;endelse beginrptr_temp <= rptr;sync_r2w <= rptr_temp;endend// 读时针同步always @(posedge rclk or negedge rrstn)beginif(!rrstn) beginsync_w2r <= 0 ;wptr_temp <= 0;endelse beginwptr_temp <= wptr;sync_w2r <= wptr_temp;endend// 判断写满读空状态assign wfull = wptr == {~sync_r2w[addr_width:addr_width-1],sync_r2w[addr_width-2:0]};assign rempty = rptr == sync_w2r;// 读数据(调用ram)dual_port_RAM #(.DEPTH(DEPTH),.WIDTH(WIDTH))dual_port_RAM(.wclk(wclk),.wenc(winc && !wfull),.waddr(wptr_bin[addr_width-1:0]),.wdata(wdata),.rclk(rclk),.renc(rinc && !rempty),.raddr(rptr_bin[addr_width-1:0]),.rdata(rdata));endmodule
补充
- 空和满时,读写指针末尾不一定全是0哦。换句话说,fifo的工作过程不一定是:先写满再读空再写满再读空这样的,也可能是边读边写,甚至可能同时读写。因此假设读指针为10011,写指针为00011(二进制),这也是fifo满。
- 亚稳态是在时钟跳变时,寄存器采样到一个逻辑0和逻辑1参考电压的中间值,这是亚稳态的概念。而亚稳态经过一段时间逐渐恢复成逻辑0或1,而具体会成为0还是1这件事是无法预测的。说回来,出现亚稳态的原因根源是被采样信号在时钟沿发生了跳变。一般情况下,同步时钟在保证setup和hold的情况下不会出现亚稳态(这也同步时钟不需要转格雷码的原因),而异步时钟相位关系无法设定,有可能同步前的信号正好在目标时钟沿跳变,有概率出现亚稳态,使用格雷码降低这种概率。一旦格雷码在跳变时也出现亚稳态,因为亚稳态最终也会恢复成逻辑0或1嘛,所以亚稳态后的格雷码相比于跳变前也可能会出现两种情况:正常跳变或者没有跳变。对于正常跳变,当然不会对结果产生任何影响;对于非正常跳变也就是格雷码没有跳变,会使被同步的指针更加保守,而可能加剧假空或者假满的程度,但不会造成功能错误,这也是选择用格雷码跨时钟的重要原因。
相关文章:
Verilog | FIFO简单实现
FIFO( First Input First Output)简单说就是指先进先出,也是缓存机制的一种,下面是我总结的 FIFO 的三大用途: 1)提高传输效率,增加 DDR 带宽的利用率。比如我们有 4 路视频数据缓存到 DDR 中去,比较笨的方法是&#x…...
设计模式应用场景
设计模式简介 工厂模式(Factory Pattern):使用工厂方法创建对象,而不是使用new关键字直接实例化对象。 抽象工厂模式(Abstract Factory Pattern):提供一个创建一系列相关对象的接口,…...
还在老一套?STM32使用新KEIL5的IDE,全新开发模式RTE介绍及使用
Keil新版本出来了,推出了一种全新开发模式RTE框架( Run-Time Environment),更好用了。然而网上的教程资料竟还都是把Keil5当成Keil4来用,直接不使用这个功能。当前正点原子或野火的教程提供的例程虽有提到Keil5,但也是基本上当Kei…...
Java时间类(十一) -- Date类工具类 -- Java获取当天、本周、本月、本年 开始及结束时间
目录 1. 今天的日期如下: 2. DateUtils工具类的源代码: 3. 测试类 1. 今天的日期如下:...
Alma Linux 9.2、Rocky Linux 9.2现在是RHEL 9.2的替代品
随着Red Hat Enterprise Linux (RHEL) 9.2的发布,Alma Linux 9.2和Rocky Linux 9.2成为了RHEL 9.2的备选替代品。这两个Linux发行版旨在提供与RHEL兼容的功能和稳定性,以满足那些需要企业级操作系统的用户需求。本文将详细介绍Alma Linux 9.2和Rocky Lin…...
推荐5款提高生活和工作效率的好帮手
在这个数字化时代,软件工具已经深深地影响和改变了我们的生活和工作。有着各种各样的软件工具,它们都可以在特定的领域内让我们变得更加高效,完成复杂的任务。选择一款适合你的软件工具,不但可以极大地释放生产力,也可以让生活变得更加便捷。 1.桌面图标管理工具——TileIconi…...
美团小组长薪资被应届生员工倒挂7K,不把老员工当人?
一位美团的小管理爆出,无意中看到了整个部门薪资,本以为自己算比较高的,但看完之后整个人都傻眼了。小组长的职位月薪28K,而手下组员却是35K,当天晚上抽了一包烟也没想明白是为什么。 楼主表示,自己是美团的…...
【Java多线程案例】使用阻塞队列实现生产者消费者模型
前言 本篇文章讲解多线程案例之阻塞队列。主要讲解阻塞队列的特性、实际开发中常用的到的生产者消费者模型,以及生产者消费者模型解耦合、削峰填谷的好处。并且使用 Java 多线程模拟实现一个生产者消费者模型、阻塞队列版的生产者消费者模型。 文章从什么是阻塞队列…...
Spark 3:Spark Core RDD持久化
RDD 的数据是过程数据 RDD 的缓存 # coding:utf8 import timefrom pyspark import SparkConf, SparkContext from pyspark.storagelevel import StorageLevelif __name__ __main__:conf SparkConf().setAppName("test").setMaster("local[*]")sc SparkC…...
字节跳动五面都过了,结果被刷了,问了hr原因竟说是...
摘要 说在前面,面试时最好不要虚报工资。本来字节跳动是很想去的,几轮面试也通过了,最后没offer,自己只想到几个原因:1、虚报工资,比实际高30%;2、有更好的人选,这个可能性不大&…...
Python日期带时区转换工具类总结
文章目录 1.背景2. 遇到的坑3. 一些小案例3.1 当前日期、日期时间、UTC日期时间3.2 昨天、昨天UTC日期、昨天现在这个时间点的时间戳3.3 日期转时间戳3.4 时间戳转日期3.5 日期加减、小时的加减 4. 总结5. 完整的编码 1.背景 最近项目是国际项目,所以需要经常需要用…...
视频会议产品对比分析
内网视频会议系统如何选择?有很多单位为了保密,只能使用内部网络,无法连接互联网,那些SaaS视频会议就无法使用。在内网的优秀视频会议也有很多可供选择,以下是几个常用的: 1. 宝利通:它支持多种…...
每日一练 | 华为认证真题练习Day47
1、某台路由器输出信息如下,下列说法错误的是?(多选) A. 本路由器开启了区域认证 B. 本设备出现故障,配置的Router Id和实际生效的Router ID不一致 C. 本设备生效的Router Id为10.0.12.1 D. 本设备生效的Router Id为…...
ChatIE(LLM大模型用于信息抽取)
Zero-Shot Information Extraction via Chatting with ChatGPT paper:https://arxiv.org/abs/2302.10205 利用ChatGPT实现零样本信息抽取(Information Extraction,IE),看到零样本就能大概明白这篇文章将以ChatGPT作为…...
提升企业管理效率的利器——ADManager Plus
在当今信息时代,企业的规模和复杂性不断增长,管理各个方面变得愈发具有挑战性。而在企业管理中,活跃目录(Active Directory)起着至关重要的作用。它是一种用于组织内部的用户、计算机、组和其他对象进行集中管理的目录…...
《入侵的艺术》读书心得:第六章:渗透测试中的智慧与愚昧
第六章:渗透测试中的智慧与愚昧 这些想法是愚昧的 1.任何期待渗透测试结果是“毫无破绽”、“无懈可击”…都是极其愚昧的: 第一层含义:测试的不可穷尽性原理(同软件测试) 第二层含义:作为优秀甚至只是合…...
SAP-MM-采购申请-价值特性
采购申请审批在维护价值特性时要注意是抬头价值还是行价值,要确定选择哪个,配置时对应配置。 1、创建价值特性CT04 字段名称:CEBAN-GSWRT,和CEBAN-GFWRT 抬头总价值:CEBAN-GFWRT;如果选择的是抬头审批&am…...
设计模式 - 代理模式
基本介绍: 代理模式:为一个对象提供一个替身,以控制对这个对象的访问。即通过代理 对象访问目标对象.这样做的好处是:可以在目标对象实现的基础上,增强额外的 功能操作,即扩展目标对象的功能。被代理的对象可以是远程对象、创建开销大的对象或需要安全控…...
IOC初始化 IOC启动阶段 (Spring容器的启动流程)
[toc](IOC初始化 IOC启动阶段 (Spring容器的启动流程)) IOC初始化 IOC启动阶段 (Spring容器的启动流程) Resource定位过程:这个过程是指定位BeanDefinition的资源,也就是配置文件(如xml)的位置,并将其封装成Resource对…...
Java后端入职第四天,就被要求代码回退(Git回退实战)
一、需求背景 初入职场,由于自己的失误或者对git不熟悉,把被人的代码给冲突掉了,然后需要立马回滚,对于新手开发,应该比较常见吧!或者,比较多一种情况,错误把工程add了到了暂存区,比如一些本地配置,本来就不应该提交的,又或者,开发中只提交部分代码,又想最新的提…...
大语言模型如何处理长文本?常用文本分割技术详解
为什么需要文本分割? 引言:为什么需要文本分割?一、基础文本分割方法1. 按段落分割(Paragraph Splitting)2. 按句子分割(Sentence Splitting)二、高级文本分割策略3. 重叠分割(Sliding Window)4. 递归分割(Recursive Splitting)三、生产级工具推荐5. 使用LangChain的…...
MMaDA: Multimodal Large Diffusion Language Models
CODE : https://github.com/Gen-Verse/MMaDA Abstract 我们介绍了一种新型的多模态扩散基础模型MMaDA,它被设计用于在文本推理、多模态理解和文本到图像生成等不同领域实现卓越的性能。该方法的特点是三个关键创新:(i) MMaDA采用统一的扩散架构…...
视频字幕质量评估的大规模细粒度基准
大家读完觉得有帮助记得关注和点赞!!! 摘要 视频字幕在文本到视频生成任务中起着至关重要的作用,因为它们的质量直接影响所生成视频的语义连贯性和视觉保真度。尽管大型视觉-语言模型(VLMs)在字幕生成方面…...
uniapp中使用aixos 报错
问题: 在uniapp中使用aixos,运行后报如下错误: AxiosError: There is no suitable adapter to dispatch the request since : - adapter xhr is not supported by the environment - adapter http is not available in the build 解决方案&…...
聊一聊接口测试的意义有哪些?
目录 一、隔离性 & 早期测试 二、保障系统集成质量 三、验证业务逻辑的核心层 四、提升测试效率与覆盖度 五、系统稳定性的守护者 六、驱动团队协作与契约管理 七、性能与扩展性的前置评估 八、持续交付的核心支撑 接口测试的意义可以从四个维度展开,首…...
全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比
目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec? IPsec VPN 5.1 IPsec传输模式(Transport Mode) 5.2 IPsec隧道模式(Tunne…...
初学 pytest 记录
安装 pip install pytest用例可以是函数也可以是类中的方法 def test_func():print()class TestAdd: # def __init__(self): 在 pytest 中不可以使用__init__方法 # self.cc 12345 pytest.mark.api def test_str(self):res add(1, 2)assert res 12def test_int(self):r…...
Redis的发布订阅模式与专业的 MQ(如 Kafka, RabbitMQ)相比,优缺点是什么?适用于哪些场景?
Redis 的发布订阅(Pub/Sub)模式与专业的 MQ(Message Queue)如 Kafka、RabbitMQ 进行比较,核心的权衡点在于:简单与速度 vs. 可靠与功能。 下面我们详细展开对比。 Redis Pub/Sub 的核心特点 它是一个发后…...
NXP S32K146 T-Box 携手 SD NAND(贴片式TF卡):驱动汽车智能革新的黄金组合
在汽车智能化的汹涌浪潮中,车辆不再仅仅是传统的交通工具,而是逐步演变为高度智能的移动终端。这一转变的核心支撑,来自于车内关键技术的深度融合与协同创新。车载远程信息处理盒(T-Box)方案:NXP S32K146 与…...
免费数学几何作图web平台
光锐软件免费数学工具,maths,数学制图,数学作图,几何作图,几何,AR开发,AR教育,增强现实,软件公司,XR,MR,VR,虚拟仿真,虚拟现实,混合现实,教育科技产品,职业模拟培训,高保真VR场景,结构互动课件,元宇宙http://xaglare.c…...
