FPGA之FIFO详解,初识FIFO

这篇具有很好参考价值的文章主要介绍了FPGA之FIFO详解,初识FIFO。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

FIFO IP介绍

       在篇博客里引入FIFO IP核的概念,FIFO是FPGA中最常用的IP核,经常用在接口模块、串并转换、协议处理、数据缓存等很多场合,所以活学活用这个IP核对于后期项目开发很重要,并且灵活掌握FIFO,也是一名合格的FPGA工程师的一项基本功。

       FIFO顾名思义就是First In First Out的简称,相信学过严蔚敏版数据结构的同学都有队列和堆栈的概念吧。而这里FPGA中FIFO IP核,其本质就和数据结构中的队列很相似,先进先出起到暂缓数据的作用。其实笔者起初学习FPGA的时候,也没太想明白为什么要用FIFO,什么时候用FIFO,用FIFO的时候又要注意些什么,所以在这篇博客里举例说明之前,笔者想先带着大家真正去搞明白上面三个问题,这将会对后期的理解学习起到很大帮助,毕竟磨刀不误砍柴工嘛。

       首先为什么要用FIFO,可能绝大多数资料教程都会异口同声的说是为了缓冲数据,当然这样说肯定是没有问题的,但是对于很多新手朋友们来说,这个回答似乎没有任何意义,因为其中并没有包含有价值的信息。

       大家可以类比下想一想,在STM32或者ARM开发中,我们用到队列的情况多不多,如经典的Freertos,用过的朋友都知道有消息队列的概念,因为任务的时间片轮询,消息队列的引入可以很好地规避进程切换带来的数据丢失,但在写一个STM32裸机程序的时候,就几乎很少用到队列了,因为本身C语言是顺序执行,比如定义一个数组或者指针,用到的时候拿来、不用的时候放着,不会有任何影响,不存在任何干扰。那么类似的FPGA本身是时序逻辑,其程序是每个独立的功能模块,各个模块又通过信号的例化,把彼此相关的信号关联在一起,这里显然就有可能出现有的模块处理慢,有的模块处理快,而每个模块的时钟又是在一直给定,那么处理快的就需要缓一缓去等待处理慢的,因为可能处理慢的模块产生输出数据正好是处理快的模块输入数据。

        解决了第一个问题,大家再来思考下第二个问题即什么时候用FIFO,我们可以用上一节的“串口收发的八字节数据包文CRC校验”工程案例来说明这个问题,因为当时事先定义好包文长度是固定的八字节,所以在FPGA程序的设计当中,我们可以用一个位宽为64的rxd_package信号去保存收到和发送的八字节包文,但是随着串口之间数据量大,一个包文有很多内容比如100字节,显然那时候再去通过定义一个位宽为800的信号量作为收发缓存,是很不合适的,这将非常占用底层资源,并且人为的带来了程序设计上的复杂,大家不妨去设想一下,如果程序中要去对一个800位宽的数据进行组包、拆包以及做各种逻辑判断,那真的会让人很头疼,另外这样的程序上也很难去维护和修改。

        所以通俗地说,FPGA程序中模块与模块之间存在数据交互的不同步,并且数据量较大的时候,FIFO几乎为FPGA工程师提供了最佳的解决途径。当然在实际项目工程中,这种不同步可能是源于跨时钟域的数据交互、也可能是由于各个模块数据处理速度的不平衡等很多因素所造成的。

         最后笔者和大家聊一聊,FIFO IP核配置后各个信号接口的一些说明,这同样也是个很重要的内容,如图1是异步时钟FIFO IP核中各个信号接口的示意图,我们注意到FIFO IP核:1.分为读写独立的端口,即FIFO_READ和FIFO_WRITE;2. FIFO_WRITE写端口有一个full输出信号用于标记FIFO写满,FIFO_READ读端口有一个empty输出信号用于标记FIFO读空;3.读写两端都有各自的时钟和使能,即rd_clk和rd_en,wr_clk和wr_en,且相互独立不影响;4.写端口的输入数据din和读端口的输出数据dout,它们是相互独立的,其位宽的长度可以一样,也可以不一样;5.写端口有wr_data_count输出信号指示目前FIFO写端口有多少数据量,读端口有rd_data_count输出信号指示目前FIFO读端口有多少数据量,并且读写端口是相互隔离的。

        所以总体上概括来说,FIFO IP核读写两端是彼此独立的,从时钟、使能、输入输出等各个方面;同时FIFO的写满full信号以及读空empty信号作为两个重要的指示信号,显然在FPGA设计中起到关键的作用,另外FIFO IP还有一些不常使用的可选信号,关于更多Xilinx的FIFO IP核细节,感兴趣的同学可以查看官方手册pg057-fifo-generator。

fpga fifo,FPGA 基础知识,fpga开发

图1 异步时钟FIFO IP核中各个信号接口的示意图

       搞清楚异步时钟FIFO IP核中各个信号接口的意义和作用以后,我们和大家进一步去探讨下,使用FIFO的时候具体又有哪些注意要点。在这里大家不妨先去思考下面三个在实践FIFO当中可能遇到的问题:1.如何避免写满读空;2.何时读取何时写入;3.读写深度怎么选择,这是三个很普遍且具有代表性的问题,可能大部分同学在刚接触到FIFO的时候,都会有抱有这样类似的疑问。

        那么下面我们再逐一把上述三个问题搞清楚,首先为什么FIFO会出现写满或者读空的现象,大部分情况是因为在设计FPGA程序时,读写FIFO的机制本身存在一定的问题,比如不关心写端口处的full写满信号和wr_data_count写入多少数据的指示信号,也不关心读端口处的empty读空信号和rd_data_count可读多少数据的指示信号,一直向FIFO不断地写入数据,但是读出数据的速度又慢于写入数据的速度,在这里大家可以先直观地把FIFO理解成一个水池,写入FIFO好比向水池注水,读取FIFO好比向水池取水,所以如果不做任何限制,只要注水速度快于取水速度,那么FIFO一定会被写满,同样的道理只要注水速度慢于取水速度,那么FIFO一定会被读空。

        接着我们也去想想看应该什么时候写入或者读取FIFO呢,其实从理论上来说,只要缓冲数据到了都是可以去写入FIFO,但是最好在程序设计中需要添加一些必要的逻辑判断,比如当上游数据达到多少数量时再触发写FIFO操作,也可以从写端口wr_data_count信号进行判断,当目前已经写入FIFO的数据超过多少数量时不再写入FIFO避免写满溢出情况。在读取FIFO数据的时候,请大家一定要去注意读端口处的empty信号,并且根据empty信号用组合逻辑产生读FIFO的rd_en信号,如果这里去使用时序逻辑根据empty信号产生读FIFO的rd_en信号,则逻辑上会存在一定的延时,如图2所示,根据读端口的empty信号,我们分别用组合逻辑和时序逻辑去产生rd_en信号,可以看到当empty信号为高即此时FIFO中已经没有数据了,但是使用时序逻辑去产生rd_en信号,将会保持一个时钟周期,这样就会导致FIFO读空的误操作,而使用组合逻辑去产生rd_en信号,当empty信号为高时,就马上拉低rd_en信号,可以有效地防止FIFO读空的操作。

fpga fifo,FPGA 基础知识,fpga开发

图2 异步时钟FIFO IP核中读使能rd_en信号用组合和时序逻辑产生的示意图

         最后,我们再去思考在实际项目工程中FIFO的读写深度怎么选择,这个问题在很多大厂的FPGA岗笔试题中也屡次出现,题干中会给出各种各样的设计背景,让面试者去做出判断等等,其实这里说到底FIFO的读写深度选取多少合适,主要取决于其最坏的情况,通俗地说就是选择的FIFO深度能够保证在最极端的情况下仍不会溢出,所以通常背景也都是写时钟频率大于读时钟频率、写数据的速度大于读数据的速度,一般情况程序设计中读写FIFO都是突发brust型的,即一次性从FIFO中读写具体数目的数据量,因为如果程序设计中读写都是连续不断的数据流,那么即使给出很大深度的FIFO也都无法保证数据不溢出。

        笔者在这里举个例子,帮助大家更加方便地理解这个问题,也是一道大厂FPGA岗的笔试题,具体题干要求如下:一个8bit位宽的FIFO,输入时钟是100Mhz,输出时钟是20Mhz,设计一个读写包文的缓存是2Kbit,且两个包文之间的发送时间间隔足够大,问异步时钟FIFO应该选取多大的读写深度。

        我们来仔细分析下这个题目要求,发送一包文brust的突发长度是2Kbit,因为题干中说明了FIFO的位宽是1Byte,所以2Kbit换算过来也就是250Byte,上游模块发送一包文brust突发时间即写入FIFO的时间为:T=250*10ns=2500ns,在T这段时间内,下游模块接收的数据即从FIFO中读取的数据量为:Data= T/50ns=2500ns/50ns=50Byte,所以理论上需要异步时钟FIFO的最小读写深度为:250Byte-50Byte=200Byte,才能满足设计需求。

FIFO IP配置

      通过前面的介绍,相信大家对于FIFO的使用已经有初步的了解,在本小节中我们会和大家动手去完成四个经典的FIFO设计从而进一步地加深理解,在此之前我们会先在Vivado环境下打开FIFO IP核如图3所示,去熟悉FIFO IP核的配置,其配置界面包括多个项目,我们需要逐一地去按顺序配置,通俗地说也就是初始化FIFO IP核。

fpga fifo,FPGA 基础知识,fpga开发

图3 在Vivado环境下打开FIFO IP核

         如图4所示是FIFO IP核的基本配置界面,从实际工程应用出发大家一般都选择Independent Clocks Block RAM,通常这种配置也是项目工程中应用最多的,其读和写是异步时钟控制的,使用起来也非常灵活,用户可以根据需求例化成相同的读写时钟也可以通过MMCM/PLL IP核分频倍频出不同的读写时钟。

       如图5所示是FIFO IP核的读写位宽和初始化配置界面,在该界面的Read Mode项目中,大家可以看到有Standard FIFO和First Word Fall Through两个选项,刚刚接触到FIFO设计的时候,其实相信任何人看到这里也都是一头雾水,Xilinx对于两个选项官方的说明如下:The standard read mode provides the user data on the cycle after it was requested. The First Word Fall Through read mode provides the user data on the same cycle in which it is requested.

        这里英语好的同学可以单纯从字面上理解这段说明,大概意思就是说选项Standard FIFO会在rd_en读使能信号后一个时钟周期给出用户数据,选项First Word Fall Through则会在rd_en读使能信号的当前周期给出用户数据,笔者在这里推荐大家去选择First Word Fall Through选项,即读数据和读使能是相互对齐的,这样可以更加方便地例化使用FIFO IP去设计FPGA程序,在Data Port Parameters项目中可以支持读写位宽不同步的情况,这里可以根据实际的工程需求来进行选择,并且配置相应的读写深度,最后在Initialization项目中一般不去勾选Enable Safety Circuit选项。

        如图6所示是FIFO IP核配置读端口数据量和写端口数据量的输出信号,一般情况下会选择勾选上,方便FPGA的程序设计上有效避免写满或者读空。配置完毕后单击OK,如图7所示是FIFO IP核生成后选择综合方式,去选择Out of context per IP即可。

fpga fifo,FPGA 基础知识,fpga开发

图4 FIFO IP核的基本配置界面

fpga fifo,FPGA 基础知识,fpga开发

图5 FIFO IP核的读写位宽和初始化配置界面

fpga fifo,FPGA 基础知识,fpga开发

图6 FIFO IP核配置读端口数据量和写端口数据量的输出信号

fpga fifo,FPGA 基础知识,fpga开发

图7 FIFO IP核生成后选择综合方式

FIFO IP练习之读写位宽相同

        下面通过一个例子去具体说明FIFO的使用方法,设计一个模块包含读写位宽是8bit、读写深度是32的异步时钟FIFO,其中输入数据信号din和输入数据指示信号din_vld是属于clk_in时钟域的,上游模块会负责写数据到本模块的FIFO中,当本模块FIFO写端口已写入了30个数据,也就是FIFO快要写满溢出的时候,这时上游模块仍有数据要写入FIFO则直接丢弃该数据。下游模块负责从本模块的FIFO中读数据,当下游模块输入rdy信号时表示下游模块已准备好可以接收FIFO中的数据了,这时如果FIFO中有数据,那么就把FIFO中的数据赋值给输出数据信号dout送至下游模块并同时拉高dout_vld输出数据指示信号,其中输出数据信号dout和输出数据指示信号dout_vld则是属于clk_out时钟域的,上游模块din信号的写位宽以及下游模块dout信号的读位宽均是8bit,表1为练习的信号列表,这里为了方便仿真观察波形,把fifo_empty信号也例化出来。

信号列表

信号名

I/O

位宽

clk_in

I

1

rst_n

I

1

rdy

I

1

din

I

8

din_vld

I

1

clk_out

I

1

dout

O

8

dout_vld

O

1

fifo_empty

O

1

表1 FIFO IP练习设计中的信号列表

        我们来思考下练习功能模块的代码设计,首先我们用上面所介绍的方法,在Vivado下初始化一个读写位宽是8bit、读写深度是32的异步时钟FIFO,FIFO的写使能fifo_wren和写数据fifo_din建议大家都使用时序逻辑去产生,当然都使用组合逻辑产生也是没问题的,但是在这里fifo_wren和fifo_din需要统一使用同一种逻辑产生,使得两者同步避免延时,FIFO的读使能fifo_rden,根据题干要求,只需要FIFO的读空信号为低,即FIFO中仍有数据,同时下游模块输入rdy信号,即其已经做好了接收FIFO中数据的准备,这时读使能fifo_rden为高,根据前面的分析fifo_rden我们用组合逻辑去产生,从而去避免读FIFO延迟而造成读空FIFO的情况,并且本模块的输出数据dout和输出数据指示信号dout_vld都用时序逻辑根据读使能fifo_rden和读数据fifo_dout去产生。FIFO IP练习的详细代码设计如图8所示。

      对于FIFO IP练习1的Testbench,笔者编写得也非常简单明了,先是给出30个时钟周期的上游模块输入信号din和din_vld,并且din用随机数进行了赋值操作,再给出下游模块准备好的rdy输入信号15个时钟周期,这是因为FIFO写端口的输入时钟是50Mhz,而读端口的输出时钟是100Mhz,如图9是FIFO IP练习1的输入信号激励设计。

       大家打开Vivado环境,添加好功能文件和测试文件后,启动Modelsim进行仿真,如图10是FIFO IP练习1的仿真结果,可以清楚地观察到当fifo_empty为高时,即FIFO当前已经没有数据了,此时恰好dout输出FIFO中的最后一个数据,且dout_vld被拉高,完全符合我们的设计预期,而这里又因为dout和dout_vld在功能文件中使用了时序逻辑去产生,所以产生了一个时钟周期的延迟。

fpga fifo,FPGA 基础知识,fpga开发fpga fifo,FPGA 基础知识,fpga开发fpga fifo,FPGA 基础知识,fpga开发 fpga fifo,FPGA 基础知识,fpga开发 

图8 FIFO IP练习的代码设计

fpga fifo,FPGA 基础知识,fpga开发fpga fifo,FPGA 基础知识,fpga开发 

图9 FIFO IP练习的输入信号激励设计

fpga fifo,FPGA 基础知识,fpga开发

图10 FIFO IP练习的仿真结果文章来源地址https://www.toymoban.com/news/detail-807097.html

到了这里,关于FPGA之FIFO详解,初识FIFO的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • FPGA中FIFO的应用(三)——Vivado FIFO IP核的调用

    ⭐️作者简介: 小瑞同学 ,一个努力精进的 FPGA 和通信学习者。 🍎个人主页:小瑞同学的博客主页 🌻个人信条:越努力,越幸运! ⏰日期:2023.12.6 🔍来源:自学经历 📖文章内容概述:简单介绍了 FIFO IP核 常用参数的配置,通过仿真分析了异步IP的 读写数据 过程。 连载

    2024年01月18日
    浏览(42)
  • FPGA——FIFO

    FIFO FIFO(First In First Out,即先入先出),是一种数据缓冲器,用来实现数据先入先出的读写方式。FIFO 根据读写时钟是否相同,分为 SCFIFO(single-clock FIFO)和 DCFIFO(duabl-clock FIFO),SCFIFO 的读写为同一时钟,应用在同步时钟系统中;DCFIFO 的读写时钟不同,应用在异步时钟系统

    2024年02月05日
    浏览(40)
  • FPGA — FIFO学习笔记

    使用软件: Vivado 参考文档 :FIFO Generator v13.2 FIFO(Fist In Fist Out),即为先进先出,常被用于数据的缓存或高速异步数据的交互,与普通存储器区别是没有外部读写地址线,使用简单,缺点是只能顺序写入数据,顺序的读出数据,其数据地址由内部读写指针自动加1完成,不能像

    2024年02月16日
    浏览(38)
  • 【LabVIEW FPGA入门】FIFO

            要在 FPGA VI 的不同部分之间或 FPGA 目标中的 VI 之间传输缓冲数据,可使用 FIFO。FIFO 是一种先进先出的缓冲器,第一个写入内存的数据项就是第一个从内存中读取和删除的数据项,类似于队列。         FPGA FIFO 的功能类似于一个固定长度的队列,可将多个数据

    2024年03月27日
    浏览(49)
  • FPGA学习笔记——FIFO读写

    【实验任务】向FIFO中以50MHz的频率按顺序写入0~254,再从FIFO中以5Hz的频率按顺序读出0~254,输出到LED中点亮。 FIFO全称为“First-In-First-Out”,是FPGA内部的存储数据的缓冲器,读写数据具有先入先出的特点,与数据结构中的“队列”有异曲同工之妙。 本博客例化紫光同创官方提

    2024年02月15日
    浏览(35)
  • FPGA学习笔记(3):FIFO

    FIFO是First Input First Output的英文简写 代表先进的数据先出 ,后进的数据后出。 FIFO存储器是系统的缓冲环节,如果没有FIFO存储器,整个系统就不可能正常工作。 FIFO的功能可以概括为 (1)对连续的数据流进行缓存,防止在进机和存储操作时丢失数据; (2)数据集中起来进行

    2024年01月19日
    浏览(40)
  • 【FPGA】UART串口通信---基于FIFO

    我们在上一章完成了UART串口通信的收发模块,这一章我们将FIFO引入进来,使用FIFO进行缓存数据,来连接串口通信的收发模块 FIFO即First In First Out,是一种先进先出数据存储、缓冲器,我们知道一般的存储器是用外部的读写地址来进行读写,而FIFO这种存储器的结构并不需要外

    2023年04月14日
    浏览(85)
  • 【FPGA IP系列】FIFO的通俗理解

    FPGA厂商提供了丰富的IP核,基础性IP核都是可以直接免费调用的,比如FIFO、RAM等等。 本文主要介绍FIFO的一些基础知识,帮助大家能够理解FIFO的基础概念。 FIFO全称是First In First Out,即先进先出。 FIFO是一个数据缓存队列,主要特点就是数据顺序写入,再按照同样的顺序输出数

    2024年02月15日
    浏览(49)
  • FPGA的Verilog设计(二)——异步FIFO

    阅读本文前,建议先阅读下面几篇文章: 同步FIFO 二进制转格雷码的实现   在上篇文章同步FIFO中简要介绍了FIFO的基本概念以及同步FIFO的实现。本篇文章将重点介绍异步FIFO的工作原理以及硬件实现。   异步FIFO的读写时钟不同,FIFO的读写需要进行异步处理, 异步FIFO常用

    2024年02月04日
    浏览(50)
  • <FPGA>异步FIFO的Verilg实现方法

            在上篇文章:同步FIFO的两种Verilog设计方法(计数器法、高位扩展法)中我们介绍了FIFO的基本概念,并对同步FIFO的两种实现方法进行了仿真验证。而异步FIFO因为读写时钟不一致,显然无法直接套用同步FIFO的实现方法,所以在本文我们将用Verilog实现异步FIFO的设计。

    2024年02月07日
    浏览(67)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包