FPGA原理与结构——FIFO IP核原理学习

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

一、FIFO概述

1、FIFO的定义

        FIFO是英文First-In-First-Out的缩写是一种先入先出的数据缓冲器与一般的存储器的区别在于没有地址线 使用起来简单缺点是只能顺序读写数据其数据地址由内部读写指针自动加1完成不能像普通存储器那样可以由地址线决定读取或写入某个指定的地址。

2、FIFO的作用

1跨时钟域的数据传输

2对不同宽度的数据进行位宽转换

3数据缓存

3、FIFO的分类

        根据FIFO工作的时钟域的不同可以将FIFO分为以下两类

        1同步FIFO读时钟和写时钟为同一个时钟在时钟沿来临时同时发生读写操作。常用于对不同宽度的数据进行位宽转换

        2异步FIFO读写时钟不一致读写操作是互相独立的。常用于跨时钟域的数据传输

4、FIFO的一些重要参数

1FIFO宽度指的是FIFO读写的数据位就像MCU有8位和16位ARM 32位等等FIFO的宽度在单片成品IC中是固定的也有可选择的如果用FPGA自己实现一个FIFO其数据位也就是宽度是可以自己定义的。

2FIFO深度指的是FIFO可以存储多少个N位的数据假设FIFO宽度为N。

3满标志(full)FIFO已满或将要满时由FIFO送出的状态信号以阻止FIFO的写操作避免数据溢出。

4空标志emptyFIFO已空或将要空时由FIFO送出的状态信号以阻止FIFO的读操作避免数据读空。

5读时钟读操作的时钟在每个时钟沿来临时读数据。

6写时钟写操作的时钟在每个时钟沿来临时写数据。

7读指针指向下一个要读出的地址读完后自动加1。

8写指针指向下一个要写入的地址写完后自动加1。

读写指针其实就是读写的地址只不过这个地址不能任意选择而是连续的。

二、FIFO IP核

        xilinx官方提供了FIFO Generator IP核来帮助我们快速实现FIFO。

1、支持的接口

        FIFO Generator这个IP核支持两种接口Native原始接口和AXIAXI接口。

1.1 Native接口FIFO

        Native接口的FIFO可以被定制成通过BRAM或DRAM或一些系类有片上固定的FIFO资源来实现。支持 Standard 和 First Word Fall Through 两种操作模式。

 1.2 AXI接口FIFO

        AXI接口的FIFO是由Native接口的FIFO发展过来的它能支持3中存储器映射的接口AXI4,AXI3和AXI4-Lite。除了Native接口FIFO所具有的基本功能毕竟是从Native升级过来的带有AXI接口的FIFO还能用于AXI系统总线和点对点高速应用中。

        关于AXI的部分会在AMBA的文章中有深入讲解这里只要知道FIFO这个IP核可以支持AXI接口就行其实xilinx中非常多的IP核都能支持AXI接口这也是其设计时的一个特点与优势。本文接下来讨论的都是Native接口的情况。

2、Native FIFO的接口信号

         下图给出了一个具有独立读写时钟的FIFO的模块示意图标准的接口和可选接口都展现了

        这个图一看就挺恐怖的没办法学习嘛逃不过的不过饭要一口一口吃信号要一个一个看我们先来简单分个类

2.1 接口信号异步FIFOFIFOs With Independent Clocks

1特殊信号

        先来看2个特殊的信号

名称方向描述
rst输入

Reset复位一个异步复位信号能初始化所有的内部指针和输出寄存器。

对于UltraScale系类的嵌入式FIFO不适用。

sleep输入

动态功率门控如果sleep有效FIFO进入省电模式不懂低功耗叭

不重要了反正它只存在于UltraScale系类的嵌入式FIFO里。

2写接口信号

        我们来看一下和写操作相关的异步FIFO接口信号这些信号中有些是标准接口下的就是标配肯定有的还有一部分是可选的附加功能得加钱bushi。

名称方向描述
Required就是我们说的标准接口也是需要重点掌握的部分
wr_clk输入写时钟所有写时钟域下的信号都和这个信号同步
din[n:0]输入数据输入写FIFO时候的数据总线
wr_en输入写使能信号如果FIFO没满这个信号生效就会使得数据din写数据总线上的写进FIFO
full输出满标志这个信号生效时说明FIFO满了在FIFO满的时候写操作是直接忽视的反正不能再让你写进去了所以FIFO满的时候写操作不会对FIFO里面的数据产生破坏外面的数据我谢谢你啊。
Optional可选接口信号最后几个看看有个印象进行了又臭又长的看着就学不会
wr_rst输入写复位同步于写时钟。生效时初始化写时钟域下所有的指针和标志信号
almost_full输出将满信号生效时说明FIFO只能最多再允许一个写操作啦
prog_full输出

可编程满信号可以和上面一个将满做个对比这个信号的存在允许我们设置一个阈值来判断FIFO还有多少空间它在FIFO剩余空间大于等于生效阈值时生效小于等于失效阈值时失效。

wr_data_count[d:0]输出

写数据计数更高级了这条总线直接告诉我们FIFO里写进了多少字这家伙保证绝对不少报多报问题还不大顶多我不写了少报数据还在写直接寄了这样就保证了我们永远不会溢出overflow。此行为的例外情况是当一个写操作发生在wr_clk/ clk的上升缘时该写操作将只反映在下一个上升时钟边缘的wr_data_count上。如果D小于log2(FIFO depth)-1总线通过删除最不重要的位而被截断。

说了这么多这条总线只在UltraScale系类里通过一个common clock Block RAM-based 实现的还要用上了Asymmetric Port Width端口FIFO里有效。

wr_ack输出写确认这个信号表示上一个时钟周期的写请求成功。
overflow输出溢出信号这个信号表示上一个时钟周期的写请求被拒绝因为FIFO已经满了。FIFO溢出不会破坏已经在FIFO里的内容
prog_full_thresh
输入可编程满阈值这个信号用来输入阈值可动态调控
prog_full_thresh_assert
输入可编程阈值生效信号这个信号定义了可编程满的上阈值什么时候生效可动态设置
prog_full_thresh_negate
输入可编程阈值失效信号这个信号定义了可编程满的下阈值什么时候生效可动态设置
injectsbiterr
输入使用ECC的时候插入inject注射一位错误
injectdbiterr
输入使用ECC的时候插入inject注射两位错误
wr_rst_busy
输出

生效时表示整个写时钟域处于复位状态

仅存在于UltraScale系类的嵌入式FIFO里

3读接口信号

        有写就有读很多地方都和写接口有着异曲同工之妙。

名称方向描述
Required就是我们说的标准接口也是需要重点掌握的部分
rd_rst输入读复位信号同步于读时钟生效时初始化读时钟域内所有的内部指针标志信号输出寄存器
rd_clk输入读时钟所有读时钟域下的信号都同步于这个信号
dout[m:0]输出数据输出读FIFO时输出数据总线被驱动
rd_en输入读使能如果FIFO不是空的这个信号生效的时候会使得数据从FIFO中被读出通过dout
empty输出空标志生效时说明FIFO已经空了当FIFO空的时候读请求会被忽视
Optional可选接口信号最后几个看看有个印象进行了又臭又长的看着就学不会
almost_empty输出将空信号生效时表示FIFO就快要空了只剩下最后一个数据可以读
prog_empty输出可编程空当FIFO中的数据数小于或等于生效阈值时就会生效该信号。当FIFO中的数据数超过失效阈值时它即被取消生效。
rd_data_count [c:0]
输出读数据计数这个总线告诉我们在FIFO中还有多少个数据可读这条总线只在UltraScale系类里通过一个common clock Block RAM-based 实现的还要用上了Asymmetric Port Width端口FIFO里有效。
vaild输出有效信号生效时表示输出总线上的数据有效
underflow输出下溢出由于FIFO是空的上一个时钟周期的读操作被拒绝
prog_empty_thresh
输入可编程空阈值此信号用于输入可编程空prog_empty标志的确认和取消。
prog_empty_thresh_assert
输入可编程空阈值生效此信号用于设置可编程空标志的下阈值
prog_empty_thresh_negate
输入可编程空阈值失效此信号用于设置可编程空标志的上阈值
sbiterr
输出单位错误表示ECC解码器检测到并修复了块RAM或内置的FIFO宏上的单位错误。
dbiterr
输出双位错误表示ECC解码器在块RAM或内置的FIFO宏上检测到双位错误并且FIFO核心中的数据已损坏。
rd_rst_busy
输出

当生效时该信号表示读取域处于复位状态。

仅存在于UltraScale系类的嵌入式FIFO里

2.2 接口信号同步FIFOInterface Signals: FIFOs with Common Clock

        看完了异步FIFO的接口信号我们来看一看同步FIFO的接口信号在理解了上一部分的基础上这部分的内容就简单很多了。

        对于同步FIFO来说所有的信号异步复位信号除外都同步于时钟对于用DRAM或BRAM构成的FIFO来说用户可以选择使用同步复位还是异步复位。

名称方向描述
Required就是我们说的标准接口也是需要重点掌握的部分
rst输入一个异步复位信号能初始化所有的内部指针和输出寄存器。对于UltraScale系类的嵌入式FIFO不适用。
srst输入一个同步复位信号能初始化所有的内部指针和输出寄存器。
clk输入时钟读写时钟域的所有信号都同步于它。
din[n:0]输入数据输入写入FIFO时使用的输入数据总线
wr_en输入写使能如果FIFO未满则生效此信号会导致数据在din上被写入FIFO。
full输出满标志生效时该信号表示FIFO已满。当FIFO满时写入请求被忽略在FIFO满时启动写入不会对FIFO的内容造成破坏。
dout[m:0]输出数据输出读取FIFO时驱动的输出数据总线。
rd_en输入读使能如果FIFO不为空生效此信号会导致从FIFO读取数据dout上。
empty输出空标志在生效时此信号表示FIFO为空。当FIFO为空时读取请求被忽略在空时启动读取对FIFO没有破坏性。
Optional可选接口信号
data_count [c:0]
输出数据计数此总线表示在FIFO中存储的单词数。如果C小于log2(FIFO深度-1总线通过删除最小显著位来截断。
almost_full
输出将满生效时此信号表示在FIFO满之前只能执行一次写入。
prog_full
输出可编程满当FIFO中的数据数大于或等于生效阈值时即会生效该信号。当FIFO中的单词数小于失效阈值时则取消失效。
wr_ack
输出写确认此信号表示前一个时钟周期中的写入请求wr_en已成功
overflow
输出溢出此信号表示在前一个时钟周期中的写入请求wr_en被拒绝因为FIFO已满。溢出FIFO对FIFO没有破坏性。
prog_full_thresh
输入可编程满阈值此信号用于设置可编程满PROG_FULL标志的阈值。
prog_full_thresh_assert
输入可编程满阈值生效此信号用于设置可编程全标志的上阈值它定义了信号的生效时间。
prog_full_thresh_negate
输入可编程满阈值生效此信号用于设置可编程满标志的较低阈值
almost_empty
输出将空的标志当生效时该信号表示FIFO几乎为空的并且有一个字保留在FIFO中。
prog_empty
输出可编程空该信号在FIFO中的单词数小于或等于可编程的阈值后被生效。当FIFO中的单词数超过可编程阈值时它即被失效。
valid
输出有效此信号表示在输出总线dout上有有效的数据可用。
underflow
输出下溢出表示前一个时钟周期中的读取请求被拒绝rd_en。注入FIFO对FIFO没有破坏性。
prog_empty_thresh
输入可编程空阈值此信号用于设置可编程空prog_empty标志的生效和失效的阈值
prog_empty_thresh_assert
输入可编程空阈值生效此信号用于设置可编程空标志的下阈值
prog_empty_thresh_negate
输入可编程空阈值失效此信号用于设置可编程空标志的上阈值
sbiterr
输出单位错误表示ECC解码器检测到并修复了一个单位错误
dbiterr
输出双位错误表示ECC解码器检测到一个双位错误并且FIFO IP中的数据已损坏。
injectsbiterr
输入如果使用了ECC特性则会输入单个比特错误。
injectdbiterr
输入如果使用了ECC特性则会出现双位错误。有关详细信息
sleep
输入动态关机节能。如果休眠状态处于激活状态则FIFO将处于省电模式。注仅适用于内置的UltraScale设备的FIFOs
wr_rst_busy
输出

当生效时该信号表示写入域处于重置状态。

仅适用于UltraScale设备内置的FIFOs以及具有同步重置的公共时钟块RAM/分布式RAM/移位寄存器FIFOs。

rd_rst_busy
输出当生效时该信号表示读取域处于重置状态。仅适用于UltraScale设备内置的FIFOs以及具有同步重置的公共时钟块RAM/分布式RAM/移位寄存器FIFOs。

三、FIFO操作

1、写操作

        当写使能生效并且FIFO没有满的时候输入总线din上的数据写入FIFO写确认信号生效。如果FIFO被连续写入而没有被读取那么它被写满。只有当FIFO未满时写操作才会成功。当FIFO已满再启动写入时将忽略请求生效溢出标志并且FIFO的状态没有变化FIFO溢出是非破坏性的。

        接下来我们通过一个例子来看看FIFO的写操作

        我们一步一步来看

1图中①处wr_en写使能信号低未开始写操作.

2图中②处wr_en拉高开始写操作此时的full为低说明FIFO没有满写操作有效。

3图中③处首先发现wr_ack有效说明上一个时钟周期的D1成功写入本周期和上一周期一样正常写数据进FIFO。

4图中④处基本同上一周期但是发现almost_full信号拉高说明FIFO将满了。

5图中⑤处full拉高了FIFO满写数据失败但是对FIFO内的数据没有影响。

6图中⑥处wr_ack拉低证明了上一个周期写失败此时FIFO依然满。

7图中⑦处同上

8图中⑧处full拉低almost_full拉高说明FIFO有了一个写入的空间此时写入数据D12

9图中⑨处ack表示D12成功写入从full看出FIFO此时可以正常写入数据。

2、读操作

        当读使能有效并且FIFO不空的时候数据通过输出数据总线dout从FIFO中被读出valid(有效)信号生效。如果FIFO被连续读取而没有被写入则FIFO将清空。当FIFO不为空时读取操作将会成功。当FIFO为空并请求读取时将忽略读取操作生效下溢出标志并且FIFO的状态没有变化下溢出FIFO是非破坏性的。

2.1 Common Clock Note同步FIFO一些值得注意的地方

        当FIFO空(empty生效)的时候当同时进行写和读操作时则接受写操作忽略读操作。在下一个时钟周期中empty失效underflow生效。

2.2 读操作模式

        FIFO Generator IP核支持两种读模式标准读模式standard read operation和前显模式FWFTfirst-word fall-through读操作。

        标准模式也即是默认模式发出一个指令在一定的时间延迟后才会读到第一个数据。而前显模式在请求它的同一周期中提供用户数据。但是不是所有的FIFO都支持前显模式的

         看起来前显模式似乎更加好用但是一般来说还是推荐使用标准模式前显模式的特殊性会使得很多地方违反我们的常规认知。

1标准模式读操作

        和读操作的原理其实差别不大这里不做详细解读了读者可根据波形自行分析。

2前显模式读操作

         最初FIFO不是空的下一个可用的数据被放在输出总线dout上有效信号vaild生效。当您生效rd_en时在rd_clk的下一个上升时钟沿将下一个数据字放到dout上。在最后一个数据字放在dout上后一个额外的读取请求导致dout上的数据无效如失效vaild和生效empty所示。任何进一步从FIFO读取的尝试都会导致下溢出状态。

        与标准读取模式不同第一个单词通过的空标志是在从FIFO读取最后一个数据之后生效的。当empty生效时将失效vaild。在标准读取模式中当empty生效时vaild还将保持一个周期的有效。FWFT特性还增加了FIFO的有效读深度。

四、非对称读写位宽

        非对称读写位宽允许FIFO的输入和输出深度不同。支持以下写读位宽比18、14、12、11、21、41、81。在使用Vivado IP目录自定义FIFO时可以通过选择唯一的写和读宽度来启用此功能。默认情况下写和读宽度设置为相同的值提供11的高宽比但支持18到81之间的任何比例并根据输入深度和写和读宽度自动计算FIFO的输出深度。我们知道FIFO可以实现对不同宽度的数据进行位宽转换就可以通过这个方式实现。
        在这种情况下我们需要明确数据的排序问题

1、写位宽<读位宽

        下图是具有14位宽比的FIFO的一个例子写宽度=2读宽度= 8。在此图中在执行读操作之前先执行四个连续的写操作。第一个写操作是01然后是00、11最后是10。内存从左到右被填满MSB到LSB。当执行读取操作时接收到的数据为01_00_11_10。

         接下来我们来看一下输入信号输出信号和握手信号之间的关系

        简单说就是empty(空信号)只有当FIFO内数据足以满足一次读才会失效。 不难理解空是要指示读的都不满一个数据这里就是8位就读肯定是不行的。

2、写位宽>读位宽

        下图显示了一个高宽比为41的FIFO写入宽度为8读取宽度为2。在本例中执行单个写操作之后执行四个读操作。写操作是11_00_01_11。当执行一个读取操作时将数据被从左到右接收MSB到LSB。如图所示第一次读取的结果为11其次是00、01然后是11。

         接下来我们来看一下输入信号输出信号和握手信号之间的关系

         这里就是empty信号还是要满足有能够读的数据就不为空这里是2位不是8位。

        其实都是符合我们常规认知的很容易想通。

五、总结

        本文对于xilinx的FIFO Generator IP核进行了一个简单的介绍解释了IP核中各个类型信号的具体功能。介绍了FIFO的读写操作其中读操作又可以分成2种模式推荐使用标准模式最后介绍了FIFO的非对称读写位宽。关于这个IP核的具体使用和示例操作将在后续的文章中带来。

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6