FPGA基础--【Altera】IP核(3)---FIFO先进先出存储器

本节文章主打Intel FPGA 开发工具Quartus中FIFO IP核的调用方法

系列文章目录

【Altera】IP核(1)—PLL锁相环
【Altera】IP核(2)—RAM随机存取存储器
【Altera】IP核(3)—FIFO先进先出存储器



前言

之前已经学习了Quartus 的PLL IP核、RAM IP核如何调用的过程。本节文章来学习FIFO IP核的调用方法。


一、FIFO是什么

FIFO(First In First Out),先进先出。常用于数据的缓存或者高速异步数据的交互,即跨时钟域信号传递。FIFO没有外部地址线,采用顺序写入数据又顺序读出数据的方式。

三种存储器的区别:
RAM 主要用来存放程序以及程序执行过程中产生的中间数据和运算结果。
ROM:只读储存器,只能读取数据,不能改变 ROM 中数值。
FIFO:先进先出存储器,数据缓冲和跨时钟域数据同步处理。
FIFO不能像RAAM和ROM那样由地址线决定读取或者写入某个指定地址

FIFO 从输入时钟的角度来分,有两种类型:单时钟 FIFO(SCFIFO)和双时钟 FIFO(DCFIFO);
其中,双时钟 FIFO 又可从输出数据的位宽的角度,分为普通双时钟(DCFIFO)和混合宽度双时钟 FIFO(DCFIFO_MIXED_WIDTHS)。
单时钟 FIFO 具有一个独立的时钟端口 clock,因此,所有的输入输出信号都同步于 clock 信号。
双时钟 FIFO结构中,写端口和读端口分别有独立的时钟,所有与写相关的信号都是同步于写时钟wrclk,所有与读相关的信号都是同步于读时钟 rdclk。
在这里插入图片描述
单时钟 FIFO 常用于同步时钟的数据缓存;
双时钟 FIFO 常用于跨时钟域的数据信号的传递,例如时钟域A下的数据data1传递给异步时钟域B,当data1为连续变化信号时,如果直接传递给时钟域B则可能会导致收非所送的情况,即在采集过程中会出现包括亚稳态(数据采样失真)问题在内的一系列问题,使用双时钟FIFO能够将不同时钟域中的数据同步到所需的时钟域中。


二、IP调用

本节文章以Quatrus为例,用文字加图片的方式展示调用FIFO的方法。

1.调用IP

(1)创建文件

创建FIFO IP测试文件夹,并且在prj中创建一个quartus的工程。(芯片类型自己选,我用的EP4CE6F17C8,芯片无所谓,本工程没用到开发板。)
doc:存放结果、图片等等
ip :存放IP核
prj :存放工程文件
rtl :存放主要代码
tb :存放testbench代码
在这里插入图片描述

(2)调用IP

在IP Catalog 搜索栏中搜索“FIFO”,然后选择“FIFO”。
在这里插入图片描述

将IP存入文件夹中ip内,点击OK。
在这里插入图片描述

(3)配置IP

接下来就是配置IP的步骤:
1、FIFO的位宽
2、FIFO的深度
3、是否设置成双时钟FIFO。
点击NEXT。
在这里插入图片描述

此页不改动
在这里插入图片描述

下图
设置读写的空满。
在这里插入图片描述

下图
1、选择FIFO 的工作模式,这两种工作模式的区别在于输出以及一些信号的相对延时。数据在读请求发出之前和之后有效。
首先是正常模式(normal mode),在此模式下,读使能有效,FIFO 会在下一个时钟输出有效的数据 q。
而前显模式(Show-Ahead)下空指示信号 empty 会滞后写使能两个时钟周期。
这里选前显模式。
2、选择默认就行。
在这里插入图片描述

把例化文件勾选上,可以看左边的简化图,点击finish完成配置。
在这里插入图片描述
具体可以去这里看,细节讲的好,我就是演示如何调用IP

2.代码

IP核配置完成后就直接在文件夹中的rtl中新建“.v”文件编写代码:
将inst文件例化进代码中,然后把文件加入工程并编译:

/*
 * @Proj: fifo_test
 * @Module: test
 * @Author: Yang.
 * @Date: 2023-12-12 17:35:46
 * @LastEditors: Yang.
 * @LastEditTime: 2023-12-13 11:41:58
 */

//---------<模块及端口声名>------------------------------------------
module fifo_test( 
    input   wire        wr_clk      ,//写时钟
    input   wire        rd_clk      ,//读时钟
    input   wire        rst_n       ,
    input   wire [7:0]  wr_din      ,//写入fifo数据
    input   wire        wr_en       ,//写使能
    input   wire        rd_en       ,//读使能
    output  reg  [7:0]  rd_dout     ,//读出的数据
    output  reg         rd_out_vld   //读有效信号       
);

//------------<参数说明>--------------------------------------------

wire   [7:0]    wr_data  ;
wire   [7:0]    q        ;
wire            wr_req   ;//写请求
wire            rd_req   ;//读请求
wire            wr_empty ;//写空
wire            wr_full  ;//写满
wire            rd_empty ;//读空
wire            rd_full  ;//读满
wire   [7:0]    wr_usedw ;//在写时钟域下,FIFO 中剩余的数据量;
wire   [7:0]    rd_usedw ;//在读时钟域下,FIFO 中剩余的数据量。

fifo	fifo_inst (
	.data     ( wr_data      ),
	.rdclk    ( rd_clk       ),
	.rdreq    ( rd_req       ),
	.wrclk    ( wr_clk       ),
	.wrreq    ( wr_req       ),
	.q        ( q            ),
	.rdempty  ( rd_empty     ),
	.rdfull   ( rd_full      ),
	.rdusedw  ( rd_usedw     ),
	.wrempty  ( wr_empty     ),
	.wrfull   ( wr_full      ),
	.wrusedw  ( wr_usedw     )
	);
assign wr_data = wr_din;
assign wr_req = (wr_full == 1'b0)?wr_en:1'b0;
assign rd_req = (rd_empty == 1'b0)?rd_en:1'b0;

always @(posedge rd_clk or negedge rst_n)begin
    if(!rst_n)begin
        rd_dout <= 0;
    end
    else begin
        rd_dout <= q;
    end
end
always @(posedge rd_clk or negedge rst_n)begin
    if(!rst_n)begin
        rd_out_vld <= 1'b0;
    end
    else begin
        rd_out_vld <= rd_req;
    end
end

endmodule

3.仿真

`timescale 1 ns/1 ns
module tb_fifo();
//时钟和复位
   reg       wr_clk;
   reg       rd_clk;
   reg       rst_n ;
//输入信号
   reg [7:0] wr_din;
   reg       wr_en ;
   reg       rd_en ;
//输出信号
   wire       rd_out_vld;
   wire [7:0] rd_dout;

parameter WR_CYCLE = 20;//写时钟周期,单位为 ns,
parameter RD_CYCLE = 30;//读时钟周期,单位为 ns,
parameter RST_TIME = 3 ;//复位时间,此时表示复位 3 个时钟周期的时间。
//待测试的模块例化


fifo_test  fifo_test_inst( 
    /*input   wire        */.wr_clk     ( wr_clk     ) ,//写时钟
    /*input   wire        */.rd_clk     ( rd_clk     ) ,//读时钟
    /*input   wire        */.rst_n      ( rst_n      ) ,
    /*input   wire [7:0]  */.wr_din     ( wr_din     ) ,//写入fifo数据
    /*input   wire        */.wr_en      ( wr_en      ) ,//写使能
    /*input   wire        */.rd_en      ( rd_en      ) ,//读使能
    /*output  reg  [7:0]  */.rd_dout    ( rd_dout    ) ,//读出的数据
    /*output  reg         */.rd_out_vld ( rd_out_vld )  //读有效信号       
);

    integer i = 0;
//生成本地时钟 50M
    initial wr_clk = 0;
    always #(WR_CYCLE/2) wr_clk=~wr_clk;
    initial rd_clk = 0;
    always #(RD_CYCLE/2) rd_clk=~rd_clk;
//产生复位信号
    initial begin
        rst_n = 1;
        #2;
        rst_n = 0;
        #(WR_CYCLE*RST_TIME);
        rst_n = 1;
    end
//输入信号赋值
    initial begin
        #1;
        wr_din = 0;//赋初值
        wr_en = 0;
        #(10*WR_CYCLE);
        for(i=0;i<500;i=i+1)begin//开始赋值
            wr_din = {$random};
            wr_en = {$random};
            #(1*WR_CYCLE);
        end
        #(100*WR_CYCLE);
    end
    initial begin
        #1;
        rd_en = 0;//赋初值
        #(12*RD_CYCLE); 
        for(i=0;i<500;i=i+1)begin//开始赋值
            rd_en = {$random};
            #(1*RD_CYCLE);
        end
        #(100*RD_CYCLE);
        $stop;
    end
endmodule

总结

在写使能有效时将数据写入,读使能有效时将数据读出。空满信号没用到,因为数据还没填满FIFO就读出来了。
在这里插入图片描述

已经学完了Quartus的基础IP核的调用,接下来就是Vivado的这些IP的调用以及基础协议的学习。继续关注。
有问题网站发私信,就是网站回复可能不及时,或者加qq:35二4291零六5 qq回复及时。
具体工程去百度网盘:

链接:https://pan.baidu.com/s/1a4yQaC2YQ6U9hMK5QWfgZA?pwd=aysz
提取码:aysz

压缩包和具体工程都有,资源里就是一些万能代码。
加油学习吧家人们。

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: Quartus FIFO IP核用于实现先进先出FIFO)功能的设计。它可以存储一系列数据并保证按照它们被写入到FIFO中的顺序依次读取。Quartus FIFO IP核在许多数字系统设计中应用广泛,比如数据缓存、视频图像缓冲、有限状态机和数据流控制等方面。 ### 回答2: Quartus是一种FPGA设计软件,其可以方便地构建和设计FPGA芯片。在FPGA设计中有许多经典的模块,其中之一就是FIFO(First-In-First-Out,先进先出)模块。在Quartus中,我们可以调用FIFO IP核来创建一个FIFO模块。 第一步骤,我们需要打开Quartus软件,并创建一个FIFO IP核。打开Quartus,在工程管理器中右键单击Design,然后选择“New”,此时弹出“New Project Wizard”对话框,我们可以创建一个所需的工程管理器模板。 第二步是在新的工程中添加FIFO IP核。首先,单击工具栏中的“Library”按钮,然后选择“New Library”。接着,打开“IP Catalog”(IP目录),选择“On-chip Modules(OCMs)”,然后选择模块的类型,并将其拖到新的工程中。 第三步是设置FIFO IP核的属性。我们可以通过右键单击FIFO IP核,选择“Properties”(属性)来设置它的属性(如深度、宽度、时钟频率等)。在设置这些属性时,我们应该仔细考虑所需的FIFO特性以及目标FPGA的规格。 第四步骤涉及到设计代码。我们需要将FIFO IP核添加到设计通过添加相应例化代码。这将告诉Quartus将生成的IP核用于设计中。一旦代码添加完毕,我们就可以对FIFO进行仿真和验证。 最后一步是实现。Quartus会将设计实现到FPGA上,并将FIFO模块加载到FPGA中。一旦实现成功,我们就可以通过GUI或者其他接口与FIFO交互。 总之,我们可以通过调用Quartus的FIFO IP核来轻松地创建FIFO模块。需要注意的是,在设置FIFO的属性和设计代码时需仔细考虑目标FPGA的规格,以避免出现错误和不兼容问题。 ### 回答3: Quartus是目前最流行的FPGA设计软件之一,它广泛应用于电子设计自动化(EDA)领域,在FPGA设计中拥有极高的知名度和使用率。其中,FIFO IP核是Quartus中一个非常常用的模块,它用于实现FIFO缓冲器,其优势在于具有存储容量大、数据读写速度快等特点,可以有效地改善数据传输的稳定性和效率。 使用Quartus中的FIFO IP核并不复杂。首先,在Quartus软件的工程管理器中打开自己的工程,在该工程的设计中添加FIFO IP核模块。在添加FIFO IP核模块的时候,需要设置FIFO的各种参数,比如:存储深度、读写接口宽度、时钟速率等。这些参数可以根据实际需求进行调整,以满足具体项目的要求。 接着,将FIFO IP核模块的输入接口和输出接口正确地连接到其他模块中。一般来说,FIFO IP核模块的输入和输出都要连接到一个时钟模块,以确保数据的同步传输。此外,还需要将其他模块的数据信号连接到FIFO IP核模块的输入端口,以实现数据的写入;将FIFO IP核模块的输出端口连接到其他模块的数据输入端口,以实现数据的读取。在连接模块配置完成后,需要根据具体的项目要求,进行特定的数学计算和综合分析,以确保整个设计的正确性和可行性。 最后,实现对Quartus中的FIFO IP核的验证工作。验证是FIFO IP核FPGA系统中正常运行的必要条件,需要对设计的FIFO IP核模块进行仿真和调试等工作,以便最终得到FIFO的功效和最优的性能。当验证通过后,即可生成需要的bit文件,将其下载到目标FPGA芯片中,从而使整个设计工程得以运行及完美工作。 总而言之,在FIFO IP核的设计和调用过程中,需要考虑到多个因素,包括参数设置、模块连接、信号配置、仿真验证等,才能够成功实现系统设计的目标。因此,对于需要在FPGA系统中使用FIFO缓冲器的应用,建议根据实际需要,结合个人的应用场景以及项目需求进行全面综合考虑,并通过不断地实践和优化,实现最佳效果。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值