当前位置:   article > 正文

基于xilinx的fifo IP核使用

基于xilinx的fifo IP核使用

一、FIFO IP 核简介

        FIFO(First In First Out,即先入先出),是一种数据缓冲器,用来实现数据先入先出的读写方式。与 ROM 或 RAM 的按地址读写方式不同,FIFO 的读写遵循“先进先出”的原则,即数据按顺序写入 FIFO,先被写入的数据同样在读取的时候先被读出,所以FIFO存储器没有地址线。FIFO 有一个写端口和一个读端口外部无需使用者控制地址,使用方便。

        FIFO存储器主要是作为缓存,应用在同步时钟系统和异步时钟系统中,在很多的设计中都会使用,后面实例中如:多比特数据做跨时钟域的转换前后带宽不同步等都用到了FIFO。FIFO 根据读写时钟是否相同,分为SCFIFO(同步FIFO)和 DCFIFO(异步FIFO),SCFIFO 的读写为同一时钟,应用在同步时钟系统中; DCFIFO 的读写时钟不同,应用在异步时钟系统中。

1.SCFIFO IP 核配置

        下面来看一下同步fifo的配置:

 ① 框中我们输入IP核的命名, 后面实例化IP 的时候都是使用的该名字,这里所取的名字最好是和该 IP 核相关,因为本节我们主要讲解同步 fifo,给该 IP 核取名为scfifo_256x8,让人一看名字就知道我们调用的 scfifo 是 256 个深度 8 位宽的。
② 框是选中 FIFO 的接口类型, 这里我们按默认选择“Native” 即可。
③ 框是选中 FIFO 的类型, 以及使用什么资源来实现。 这里我们选择“Common Clock Block RAM”使用块 RAM 来实现同步 FIFO;其中 Common Clock 表示是同步 FIFO,Block RAM 表示的是块 RAM 资源。

   ①框中是对模式的选择,这里我们选择标准 FIFO(Standard FIF0) 即可。
        ② 框中可设置存储数据的位宽和深度, 其中“Write Width”是设置写数据位宽,这里我们设置为 8 位; “Write Depth” 是设置数据深度,这里我们设置为 256; “Read Width”是设置读数据位宽,这里我们设置为 8 位;“Read Depth”为读数据深度,该选项会根据我们设置的读写位宽及写数据深度自动设置。
        ③ 框是对复位信号创建的设置, 大家可根据自己的设计需求进行选择是否创建, 这里我们按默认勾选, 进行创建。设置完之后切换到“Status Flags”页面。

        ①框中可勾选生成 FIFO 几乎满(Almost Full Flag) ,几乎空(Almost Empty Flag) 输
出信号;也就是说若勾选了这两个信号,当 FIFO 存储数据快满或者快空的时候,该信号就有效。这里大家可根据自己的实际需求进行勾选,这里我们选择都不勾选。
        ② 左框中可勾选生成写确认标志信号,用于报告写操作成功。 若勾选后可以配置为高电平有效或低电平有效,这里我们选择不勾选。
       ② 右框中可勾选生成溢出标志信号; 该标志信号可以指示 FIFO 内存储数据是否溢出,可以指示上一次写操作何时失败。若勾选后可以配置为高电平有效或低电平有效,这里我们选择不勾选。
        ③左 框中可勾选生成指示输出总线上数据何时有效的有效标志信号。 若勾选后可以配置
为高电平有效或低电平有,这里我们选择不勾选。
        ③右框中可勾选生成下溢标志信号;该标志信号可以指示 FIFO 内存储数据空了,可以指示上一次的读请求何时失败。 若勾选后可以配置为高电平有效或低电平有效,这里我们选择不勾选。
这些选项可以根据自己的设计需求进行勾选,这里我们按默认都不勾选,直接切换到“Data Counts”页面。

        可勾选“Data Count”生成 FIFO 内剩余个数输出信号, 该输出信号可根据自己设计是否需要进行生成,默认是不生成,这里我们勾选进行生成该信号。设置完之后切换到“summary”页面。

 然后点击OK。

1.1 SCFIFO IP 核例化     

         生成IP之后就可以将我们的同步fifo IP例化到我们的新建的同步fifo工程进行一个tb文件的编写。 

  1. module scfifo(
  2. input sys_clk , //
  3. input sys_rst_n , //
  4. input [7:0] din , //写数据
  5. input wr_en , //写使能
  6. input rd_en , //读使能
  7. output [7:0] dout , //读数据
  8. output full , //fifo满标志信号,高有效
  9. output empty , //fifo空标志信号,高有效
  10. output [7:0] data_count //fifo存在的数据个数
  11. );
  12. scfifo_256x8 scfifo_256x8_inst (
  13. .clk(sys_clk), // input wire clk
  14. .srst(~sys_rst_n), // input wire srst
  15. .din(din), // input wire [7 : 0] din
  16. .wr_en(wr_en), // input wire wr_en
  17. .rd_en(rd_en), // input wire rd_en
  18. .dout(dout), // output wire [7 : 0] dout
  19. .full(full), // output wire full
  20. .empty(empty), // output wire empty
  21. .data_count(data_count) // output wire [7 : 0] data_count
  22. );
  23. endmodule

1.2 SCFIFO IP 核仿真

        下面是 Testbench 仿真测试文件,和 SCFIFO 的仿真一样,我们也需要给输入信号测试激励, pi_flag 每 4 个时钟周期且没有读请求时产生一个数据有效标志信号也作为 FIFO 的写请求信号,因为需要 pi_data 伴随着 pi_flag 一起产生,所以每当 pi_data 检测到 pi_flag 标志信号有效时就自加 1,其值从 0~255 循环变化,这样我们就可以在 pi_flag 标志信号有效时将 pi_data 写入到 FIFO 中。而 FIFO 的读请求信号 rd_en 当 FIFO 的满标志信号 full 有效时拉高,当 FIFO 的空标志信号 empty 有效时拉低。

        SCFIFO 可以同时进行读写操作,但本例我们没有让 SCFIFO 同时进行读写,当我们真正使用 SCFIFO IP 核时一定要保证 FIFO 不被写满也不被读空。

  1. `timescale 1ns / 1ns
  2. module tb_scfifo();
  3. //reg define
  4. reg sys_clk ; //系统时钟
  5. reg [7:0] pi_data ; //写数据
  6. reg wr_en ; //写使能
  7. reg rd_en ; //读使能
  8. reg sys_rst_n ; //系统复位
  9. reg [1:0] cnt_baud ; //计数器
  10. //wire define
  11. wire [7:0] po_data ; //读数据
  12. wire empty ; //读空标志信号
  13. wire full ; //写满标志信号
  14. wire [7:0] data_count ; //数据计数器
  15. initial begin
  16. sys_clk = 1'b1;
  17. sys_rst_n <= 1'b0;
  18. #201
  19. sys_rst_n <= 1'b1;
  20. end
  21. always #10 sys_clk <= ~sys_clk;
  22. //数据读写之间产生一个间隔
  23. always@(posedge sys_clk or negedge sys_rst_n) begin
  24. if(!sys_rst_n)
  25. cnt_baud <= 2'd0;
  26. else if(&cnt_baud == 2'd1) //累计满清零
  27. cnt_baud <= 2'd0;
  28. else
  29. cnt_baud <= cnt_baud + 2'd1;
  30. end
  31. //写使能信号,也是fifo的写请求信号
  32. always@(posedge sys_clk or negedge sys_rst_n) begin
  33. if(!sys_rst_n)
  34. wr_en <= 1'b0;
  35. //每四个周期且没有读使能没有产生一个读使能信号
  36. else if(cnt_baud == 2'd0 && rd_en == 1'b0)
  37. wr_en <= 1'b1;
  38. else
  39. wr_en <= 1'b0;
  40. end
  41. //写数据模块,向fifo写入256个数据
  42. always@(posedge sys_clk or negedge sys_rst_n) begin
  43. if(!sys_rst_n)
  44. pi_data <= 8'd0;
  45. else if(pi_data == 8'd255 && wr_en == 1'd1)
  46. pi_data <= 8'd0;
  47. else if(wr_en == 1'b1)
  48. pi_data <= pi_data + 1'b1;
  49. end
  50. //fifo读请求信号
  51. always@(posedge sys_clk or negedge sys_rst_n) begin
  52. if(!sys_rst_n)
  53. rd_en <= 1'b0;
  54. //当fifo中的数据被读空时,停止读取fifo中的数据
  55. else if(empty == 1'b1)
  56. rd_en <= 1'b0;
  57. //当fifo中的数据被写满时,停止往fifo中写入数据
  58. else if(full == 1'b1)
  59. rd_en <= 1'b1;
  60. end
  61. scfifo scfifo_inst(
  62. .sys_clk (sys_clk),
  63. .sys_rst_n (sys_rst_n),
  64. .din (pi_data) , //写数据
  65. .wr_en (wr_en), //写使能
  66. .rd_en (rd_en), //读使能
  67. .dout (po_data), //读数据
  68. .full (full), //fifo满标志信号,高有效
  69. .empty (empty), //fifo空标志信号,高有效
  70. .data_count (data_count) //fifo存在的数据个数
  71. );
  72. endmodule

仿真结果:

 

 

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

闽ICP备14008679号