Vivado FIFO IP核

  • 1、创建同步FIFO IP核
  • 1.2 设置同步FIFO IP核相关参数
  • 1.2.1 Basic选项卡
  • 1.2.2 Native Ports选项卡
  • 1.2.3 Status Flags选项卡
  • 1.2.4 Data Counts选项卡
  • 1.2.5 Summary选项卡
  • 1.3 生成FIFO
  • 1.4 例化FIFO
  • 1.4.1 打开.veo文件
  • 1.4.2 复制例化模板
  • 1.5、编写testbench文件对同步fifo仿真
  • 2、创建异步FIFO IP核
  • 2.2 设置异步FIFO IP核相关参数
  • 2.2.1 Basic选项卡
  • 2.2.2 Native Ports选项卡
  • 2.2.3 Status Flags选项卡
  • 2.2.4 Data Counts选项卡
  • 2.2.5 Summary选项卡
  • 2.3 生成FIFO
  • 2.4 例化FIFO
  • 2.5、编写testbench文件对异步fifo仿真
  • 1、创建同步FIFO IP核

    1.2 设置同步FIFO IP核相关参数

    1.2.1 Basic选项卡

  • 上图中标注数字1处为IP核的名称,可以根据自己需求修改。
  • 上图中标注数字2处为IP核总线类型,Native类型用于非SOC逻辑设计,其它两种用于SOC逻辑设计,通常选择Native类型。
  • 上图中标注数字3处为FIFO的时钟组成和存储结构,从上到下依次为单时钟块RAM、单时钟分布式RAM、单时钟移位寄存器、单时钟内建FIFO、双时钟块RAM、双时钟分布式RAM、双时钟内建FIFO。其中的单时钟即同步FIFO,双时钟即异步FIFO。同步FIFO 是指读时钟和写时钟为同一个时钟,异步FIFO 是指读写时钟不一致,读写时钟是互相独立的。
  • 1.2.2 Native Ports选项卡

  • 上图中Read Mode处用于设置读FIFO时的读模式。当FIFO配置为单时钟块RAM时,选择Standard FIFO时的仿真波形如图2.2.1所示。选择First Word Fall Through时的仿真波形如图2.2.2所示。即选择Standard FIFO时当读使能信号rd_en拉高时,下一个时钟周期才会输出数据,而选择First Word Fall Through时,当读使能信号rd_en拉高时,数据就会输出,不用等待一个时钟周期。
  • 上图中Data Port Parameters处用于设置读写端口的数据总线的宽度以及FIFO的深度。从上到下依次是写数据宽度、写数据深度、读数据宽度 、读数据深度(自动生成)。
  • 上图中Reset Pin处为是否采用复位引脚。
  • 上图中Reset Type处为是否为异步复位。
  • 上图中Full Flags Reset Value处为复位时Full Flags的状态为0还是为1。
  • 上图中Dout Reset Value处为复位时Dout数据线的状态。
    图2.2.1
    2.2.1Standard FIFO
    图2.2.2
  • 1.2.3 Status Flags选项卡

    1.2.4 Data Counts选项卡

  • “Data Counts”选项卡用于设置FIFO 内数据计数的输出信号,此信号表示当前在FIFO 内存在多少个有效数据。
  • 1.2.5 Summary选项卡

  • 该选项卡为FIFO最终的配置以及资源占用情况。
  • 1.3 生成FIFO

  • 设置好上面的参数后,点击Generate生成FIFO即可。
  • 1.4 例化FIFO

    1.4.1 打开.veo文件

    1.4.2 复制例化模板

  • 将红框里的文字复制到.v文件即可。
  • 1.5、编写testbench文件对同步fifo仿真

     `timescale 1ns / 1ps
    
    module tb();
        parameter PERIOD = 20;
        reg clk;
        reg rst_n;
        reg wr_en;
        reg rd_en;
        wire full;
        wire empty;
        reg [1:0] din;
        wire [1:0] dout;
        initial begin
            clk = 0;
            forever begin
                #(PERIOD / 2) clk = ~clk;
            end
        end
        initial begin
            rst_n = 0;
            #(PERIOD) rst_n = 1;
        end
    
        always @(posedge clk or negedge rst_n) begin
            if (!rst_n) begin
                din <= 2'd0;
            end
            else begin
                din <= din + 1;
            end
        end
    
        initial begin
            wr_en = 0;
            #(PERIOD *2 + PERIOD / 2)  wr_en = 1;
        end
    
        initial begin
            rd_en = 0;
            #(PERIOD *4 + PERIOD / 2)  rd_en = 1;
        end
    
        fifo_generator_0 your_instance_name (
          .clk(clk),      // input wire clk
          .srst(~rst_n),    // input wire srst
          .din(din),      // input wire [1 : 0] din
          .wr_en(wr_en),  // input wire wr_en
          .rd_en(rd_en),  // input wire rd_en
          .dout(dout),    // output wire [1 : 0] dout
          .full(full),    // output wire full
          .empty(empty)  // output wire empty
        );
    endmodule
    

    仿真结果如下图所示:

  • 注意FIFO IP核为高电平复位。
  • 当写使能wr_en拉高时,数据便被写入FIFO中,没有时钟周期的延迟。
  • 当读使能rd_en拉高后,下一个时钟周期才会读出数据。
  • 2、创建异步FIFO IP核

    2.2 设置异步FIFO IP核相关参数

    2.2.1 Basic选项卡

    2.2.2 Native Ports选项卡

    同上述同步fifo设置。

    2.2.3 Status Flags选项卡

    同上述同步fifo设置。

    2.2.4 Data Counts选项卡


    此处勾选了两个计数器来分别计算写入和读出了多少个数据。

    2.2.5 Summary选项卡

    同上述同步fifo设置。

    2.3 生成FIFO

    同上述同步fifo设置。

    2.4 例化FIFO

    同上述同步fifo设置。

    2.5、编写testbench文件对异步fifo仿真

    module tb();
        parameter PERIOD = 2;
    
        reg             clk             ;
        reg             rst_n           ;
        reg             wr_en           ;
        reg             rd_en           ;
        reg  [17:0]     din             ;
    
        wire            full            ;
        wire            empty           ;    
        wire [17:0]     dout            ;
        wire [9:0]      rd_data_count   ;
        wire [9:0]      wr_data_count   ;
        wire            wr_rst_busy     ;
        wire            rd_rst_busy     ;
    
        initial begin
            clk = 0;
            forever begin
                #(PERIOD / 2) clk = ~clk;
            end
        end
    
        initial begin
            rst_n = 0;
            #(PERIOD * 2) rst_n = 1;
        end
    
        always @(posedge clk or negedge rst_n) begin
            if (!rst_n) begin
                din <= 18'd0;
            end
            else begin
                din <= din + 1;
            end
        end
    
        initial begin
            wr_en = 0;
            #(PERIOD *30 + PERIOD / 2)  wr_en = 1;
        end
    
        initial begin
            rd_en = 0;
            #(PERIOD *40 + PERIOD / 2)  rd_en = 1;
        end
    
        fifo_generator_0 your_instance_name (
          .rst(~rst_n),                      // input wire rst
          .wr_clk(clk),                // input wire wr_clk
          .rd_clk(clk),                // input wire rd_clk
          .din(din),                      // input wire [17 : 0] din
          .wr_en(wr_en),                  // input wire wr_en
          .rd_en(rd_en),                  // input wire rd_en
          .dout(dout),                    // output wire [17 : 0] dout
          .full(full),                    // output wire full
          .empty(empty),                  // output wire empty
          .rd_data_count(rd_data_count),  // output wire [9 : 0] rd_data_count
          .wr_data_count(wr_data_count),  // output wire [9 : 0] wr_data_count
          .wr_rst_busy(wr_rst_busy),      // output wire wr_rst_busy
          .rd_rst_busy(rd_rst_busy)      // output wire rd_rst_busy
        );
    
    endmodule
    

    仿真结果如下图所示:

    如上图所示,复位完成后,wr_rst_busy和rd_rst_busy会有短暂的拉高过程,需要等待wr_rst_busy和rd_rst_busy均拉低时才能进行正常的读写。


    如上图所示,在wr_en拉高后,empty信号会有几个周期的延时,如果在empty拉低之前就拉高读使能信号,则数据只会在empty拉低后才输出。如下图所示,在empty拉低之后拉高读使能信号,则数据在读使能信号拉高的下一个周期便输出了出来。

    物联沃分享整理
    物联沃-IOTWORD物联网 » 使用Vivado中的FIFO IP核

    发表评论