当前位置:   article > 正文

【FPGA】 Vivado FIFO IP核使用教程

vivado fifo ip核使用

目录

一、FIFO简介

二、FIFO的应用

三、Vivado FIFO创建

四、FIFO IP核实例化

五、对实例化顶层文件仿真

一、FIFO简介

       FIFO 的英文全称是 First In First Out ,即先进先出 FPGA 使用的 FIFO 一般指的是对数据的存储具有先进先出特性的一个缓存器,常被用于数据的缓存或者高速异步数据的交互,也即所谓的跨时钟域信号传递。它与 FPGA 内部的 RAM ROM 的区别是没有外部读写地址线,采取顺序写入数据,顺序读出数据的方式,使用起来简单方便,由此带来的缺点就是不能像 RAM 和 ROM 那样可以由地址线决定读取或写入某个指定的地址。
       FIFO 从输入时钟的角度来分,有两种类型: 单时钟 FIFO和双时钟 FIFO;单时钟 FIFO 具有一个独立的时钟端口 clock,因此,所有的输入输出信号都同步于 clock 信号。双时钟 FIFO 结构中,写端口 和读端口分别有独立的时钟,所有与写相关的信号都是同步于写时钟 wr_clk,所有与读相关 的信号都是同步于读时钟 rd_clk。

二、FIFO的应用

1. 单时钟 FIFO 常用于同步时钟的数据缓存;
2. 双时钟 FIFO 常用于跨时钟域的数据信号的传递,例如时钟域 A 下的数据 data1 传递 给异步时钟域 B ,当 data1 为连续变化信号时,如果直接传递给时钟域 B 则可能会 导致收到的数据不是发送的数据的情况,即在采集过程中会出现包括亚稳态(数据采样失真)问题在内的一系列问题,使用双时钟 FIFO 能够将不同时钟域中的数据同步到所需的时钟域中

三、Vivado FIFO创建

1、新建工程后进入以下界面,点击IP Catalog,在右侧界面搜索fifo,找到FIFO Cenerator打开。

2、在FIFO IP核配置界面,Component Name中可以更改命名,Fifo Impiementation中可以选择单时钟(Common Clock Block RAM)和双时钟(Independent Clocks Block RAM),这里我选择双时钟。

 

3、模式选择有标准模式和FWFT模式,标准模式中读取的数据滞后读信号一个时钟周期;FWFT模式中读信号有效时,读取的数据也立即有效。这里我选择标准模式,设置读写数据位宽为16,数据深度为512,根据需要自行设置。

 4、读写计数界面,Write Data Count表示FIFO已经写入多少数据,Read Data Count表示FIFO中有多少数据可以读。点击“OK”,完成异步FIFO 配置。

四、FIFO IP核实例化

1、Sources里的fifo_ip.veo文件中是IP的例化模板。我们只需要将文件中内容复制粘贴到我们verilog程序中,对IP进行实例化。。

 2、我们在创建一个顶层设计文件来实例化这个FIFO IP, 编写pll_test.v代码如下。

  1. `timescale 1ns / 1ps
  2. //
  3. // Company:
  4. // Engineer:
  5. //
  6. // Create Date: 2023/03/31 14:59:11
  7. // Design Name:
  8. // Module Name: fifo_test
  9. // Project Name:
  10. // Target Devices:
  11. // Tool Versions:
  12. // Description:
  13. //
  14. // Dependencies:
  15. //
  16. // Revision:
  17. // Revision 0.01 - File Created
  18. // Additional Comments:
  19. //
  20. //
  21. module fifo_test(
  22. input wr_clk ,//写 FIFO 时钟
  23. input rd_clk ,//读 FIFO 时钟
  24. input rst_n ,//复位
  25. input [7:0] wr_din ,//写入 FIFO 的数据
  26. input wr_en ,//写使能
  27. input rd_en ,//读使能
  28. output reg [7:0] rd_dout,//从 FIFO 读出的数据
  29. output reg rd_out_vld //从 FIFO 读出的数据有效指示信号
  30. );
  31. //信号定义
  32. wire [7:0] wr_data ;
  33. wire [7:0] q ;
  34. wire wr_req ;
  35. wire rd_req ;
  36. wire rd_empty ;
  37. wire wr_full ;
  38. wire [7:0] wrusedw ;
  39. wire [7:0] rdusedw ;
  40. //FIFO 例化
  41. fifo_ip your_instance_name (
  42. .wr_clk (wr_clk ), // input wire wr_clk
  43. .rd_clk (rd_clk ), // input wire rd_clk
  44. .din (wr_data ), // input wire [15 : 0] din
  45. .wr_en (wr_req ), // input wire wr_en
  46. .rd_en (rd_req ), // input wire rd_en
  47. .dout (q ), // output wire [15 : 0] dout
  48. .full (wr_full ), // output wire full
  49. .empty (rd_empty ), // output wire empty
  50. .rd_data_count(rdusedw ), // output wire [8 : 0] rd_data_count
  51. .wr_data_count(wrusedw ) // output wire [8 : 0] wr_data_count
  52. );
  53. assign wr_data = wr_din;//输入的数据
  54. assign wr_req = (wr_full == 1'b0)?wr_en:1'b0;//非满才写
  55. assign rd_req = (rd_empty == 1'b0)?rd_en:1'b0;//非空才读
  56. always @(posedge rd_clk or negedge rst_n)begin
  57. if(!rst_n)begin
  58. rd_dout <= 0;
  59. end
  60. else begin
  61. rd_dout <= q;
  62. end
  63. end
  64. always @(posedge rd_clk or negedge rst_n)begin
  65. if(!rst_n)begin
  66. rd_out_vld <= 1'b0;
  67. end
  68. else begin
  69. rd_out_vld <= rd_req;
  70. end
  71. end
  72. endmodule

五、对实例化顶层文件仿真

1、我们在创建一个仿真激励文件来仿真这个fifo_test顶层文件, 编写fifo_test_tb.v代码如下。

  1. `timescale 1ns / 1ps
  2. //
  3. // Company:
  4. // Engineer:
  5. //
  6. // Create Date: 2023/03/31 15:11:44
  7. // Design Name:
  8. // Module Name: fifo_test_tb
  9. // Project Name:
  10. // Target Devices:
  11. // Tool Versions:
  12. // Description:
  13. //
  14. // Dependencies:
  15. //
  16. // Revision:
  17. // Revision 0.01 - File Created
  18. // Additional Comments:
  19. //
  20. //
  21. module fifo_test_tb();
  22. //时钟和复位
  23. reg wr_clk ;
  24. reg rd_clk ;
  25. reg rst_n ;
  26. //输入信号
  27. reg [7:0] wr_din;
  28. reg wr_en ;
  29. reg rd_en ;
  30. //输出信号
  31. wire rd_out_vld ;
  32. wire [7:0] rd_dout ;
  33. //参数定义
  34. parameter WR_CYCLE = 20;//写时钟周期,单位为 ns,
  35. parameter RD_CYCLE = 30;//读时钟周期,单位为 ns,
  36. parameter RST_TIME = 3 ;//复位时间,此时表示复位 3 个时钟周期的时间。
  37. //待测试的模块例化
  38. fifo_test u_fifo_test(
  39. .wr_clk (wr_clk ),//时钟
  40. .rd_clk (rd_clk ),
  41. .rst_n (rst_n ),//复位
  42. .wr_din (wr_din ),//写入 FIFO 的数据
  43. .wr_en (wr_en ),//写使能
  44. .rd_en (rd_en ),//读使能
  45. //输出信号定义
  46. .rd_dout (rd_dout ),//从 FIFO 读出的数据
  47. .rd_out_vld (rd_out_vld )//从 FIFO 读出的数据有效指示信号
  48. );
  49. integer i = 0;
  50. //生成本地时钟 50M
  51. initial wr_clk = 0;
  52. always #(WR_CYCLE/2) wr_clk=~wr_clk;
  53. initial rd_clk = 0;
  54. always #(RD_CYCLE/2) rd_clk=~rd_clk;
  55. //产生复位信号
  56. initial begin
  57. rst_n = 1;
  58. #2;
  59. rst_n = 0;
  60. #(WR_CYCLE*RST_TIME);
  61. rst_n = 1;
  62. end
  63. //输入信号赋值
  64. initial begin
  65. #1;
  66. //赋初值
  67. wr_din = 0;
  68. wr_en = 0;
  69. #(100*WR_CYCLE);
  70. //开始赋值
  71. for(i=0;i<500;i=i+1)begin
  72. wr_din = {$random};
  73. wr_en = {$random};
  74. #(1*WR_CYCLE);
  75. end
  76. #(100*WR_CYCLE);
  77. end
  78. initial begin
  79. #1;
  80. //赋初值
  81. rd_en = 0;
  82. #(120*RD_CYCLE);
  83. //开始赋值
  84. for(i=0;i<500;i=i+1)begin
  85. rd_en = {$random};
  86. #(1*RD_CYCLE);
  87. end
  88. #(100*RD_CYCLE);
  89. $stop;
  90. end
  91. endmodule

2、仿真结果如下,输出rd_dout[7:0]的结果和输入wr_din[7:0]一致。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/你好赵伟/article/detail/572636
推荐阅读
相关标签
  

闽ICP备14008679号