vivado fifo原语使用详解

1.首先介绍使用xilinx fifo 原语优势:

       在设计或大或小的工程时,尤其是视频项目,往往会使用许多异步fifo作为数据缓存,xilinx fifo使用需要调用IP设置开发,较为麻烦,而且过多fifo命名也会导致重复或则不便于修改,因此需要寻找一种便捷管理方法。

      xilinx内部提供了一种fifo原语,用户可以通过原理例化,参数匹配即可完成在线自定义FIFO深度以及引出需要的信号,灵活性可谓是得到大幅度提升。

2.XMP fifo使用:

首先在例化模板内找到:

上图所示,async为异步FIFO,suync为同步fifo。

以异步fifo为例,本设计更改异步fifo原语后将其自定义,后续只需对该头文件例化后即可作为FIFO ip使用,更改后的fifo.v代码如下所示:

`timescale 1ns / 1ps
//
// Company: Nuist
// Engineer: jia yu chen
// 
// Create Date: 2023/05/16 13:00:18
// Design Name: 
// Module Name: async_fifo
// Project Name: async_fifo
// Target Devices: 
// Tool Versions: 
// Description: 

//


module async_fifo #(
parameter integer    FIFO_TYPES            =   0                 ,//‘0’fwft,‘1’为标准fifo延迟一个时钟,需要更改模式
parameter integer    FIFO_WRITE_DEPTH      =   2048              ,//fifo写深度
parameter integer    READ_DATA_WIDTH       =   32                ,//读数据位宽
parameter integer    WRITE_DATA_WIDTH      =   32                ,//写数据位宽
parameter integer    PROG_EMPTY_THRESH     =   10                ,
parameter integer    PROG_FULL_THRESH      =   10                ,
parameter integer    WR_WIDTH              =   10                ,
parameter integer    RD_WIDTH              =   10                

)
(
    input       wire                                 fifo_rst          ,
    input       wire                                 wr_clk            ,
    input       wire                                 wr_en             ,
    input       wire   [WRITE_DATA_WIDTH-1:0]        wr_data           ,
    
    input       wire                                 rd_clk            ,
    input       wire                                 rd_en             ,
    output      wire   [READ_DATA_WIDTH-1:0]        rd_data           ,
    
    output      wire   [WR_WIDTH-1:0]                wr_data_count     ,
    output      wire   [RD_WIDTH-1:0]                rd_data_count     ,
    output      wire                                 empty             ,
    output      wire                                 full              ,
    output      wire                                 prog_empty        ,
    output      wire                                 prog_full                
    );
  
	function integer clogb2 (input integer bit_depth);              
		begin                                                           
			for(clogb2=0; bit_depth>0; clogb2=clogb2+1)                   
				bit_depth = bit_depth >> 1;                                 
		end                                                           
	endfunction  

 localparam          FIFO_READ_LATENCY    =  FIFO_TYPES;  //fifo读写延迟值
 localparam          RD_DATA_COUNT_WIDTH  =  clogb2( WRITE_DATA_WIDTH*FIFO_WRITE_DEPTH/WRITE_DATA_WIDTH-1)+1     ;  //读侧fifo计数器位宽.总容量÷读位宽-1求位宽 + 1
 localparam          WR_DATA_COUNT_WIDTH  =  clogb2(FIFO_WRITE_DEPTH-1)+1  ;  //写侧fifo计数器位宽,用写侧深度-1求位宽即可     
// localparam          TYPE                 =  FIFO_TYPES?   "std"  :"fwft"            ;//模式先入先出或者标准
 
    xpm_fifo_async #(
      .CDC_SYNC_STAGES(2),       // DECIMAL
      .DOUT_RESET_VALUE("0"),    // String
      .ECC_MODE("no_ecc"),         //string; "no_ecc" or "en_ecc";
      .FIFO_MEMORY_TYPE("auto"),  //string; "auto", "block", or "distributed";
      .FIFO_READ_LATENCY(FIFO_READ_LATENCY),     // 读延时   
      .FIFO_WRITE_DEPTH(FIFO_WRITE_DEPTH),   //integer 写fifo深度
      .FULL_RESET_VALUE(0),      // positive integer; 0 or 1
      .PROG_EMPTY_THRESH(PROG_EMPTY_THRESH),    // fifo快空水线
      .PROG_FULL_THRESH(PROG_FULL_THRESH),     //fifo快满水线
      .RD_DATA_COUNT_WIDTH(RD_DATA_COUNT_WIDTH),   //读侧fifo计数器位宽
      .READ_DATA_WIDTH(READ_DATA_WIDTH),      // fifo读侧读数据位宽
      .READ_MODE("fwft"),       //string; "std" or "fwft";先入先出或者标准模式
      .RELATED_CLOCKS(0),         //positive integer; 0 or 1
      .SIM_ASSERT_CHK(0),        // DECIMAL; 0=disable simulation messages, 1=enable simulation messages
      .USE_ADV_FEATURES("0707"), //string; "0000" to "1F1F"; 
      .WAKEUP_TIME(0),           // positive integer; 0 or 2;
      .WRITE_DATA_WIDTH(WRITE_DATA_WIDTH),         //integer 写数据位宽
      .WR_DATA_COUNT_WIDTH(WR_DATA_COUNT_WIDTH)    //integer 写数据计数器位宽
   )
   xpm_fifo_async_inst (
      .almost_empty(),   // 1-bit output: Almost Empty : When asserted, this signal indicates that
      .almost_full(),     // 1-bit output: Almost Full: When asserted, this signal indicates that
      .data_valid(),       // 1-bit output: Read Data Valid: When asserted, this signal indicates
      .dbiterr(),             // 1-bit output: Double Bit Error: Indicates that the ECC decoder detected
      .dout(rd_data),                   // READ_DATA_WIDTH-bit output: Read Data: The output data bus is driven
      .empty(empty),                 // 1-bit output: Empty Flag: When asserted, this signal indicates that the
      .full(full),                   // 1-bit output: Full Flag: When asserted, this signal indicates that the
      .overflow(),           // 1-bit output: Overflow: This signal indicates that a write request
      .prog_empty(prog_empty),       // 1-bit output: Programmable Empty: This signal is asserted when the
      .prog_full(prog_full),         // 1-bit output: Programmable Full: This signal is asserted when the
      .rd_data_count(rd_data_count), // RD_DATA_COUNT_WIDTH-bit output: Read Data Count: This bus indicates the
      .rd_rst_busy(),     // 1-bit output: Read Reset Busy: Active-High indicator that the FIFO read
      .sbiterr(),             // 1-bit output: Single Bit Error: Indicates that the ECC decoder detected
      .underflow(),         // 1-bit output: Underflow: Indicates that the read request (rd_en) during
      .wr_ack(),               // 1-bit output: Write Acknowledge: This signal indicates that a write
      .wr_data_count(wr_data_count), // WR_DATA_COUNT_WIDTH-bit output: Write Data Count: This bus indicates
      .wr_rst_busy(),     // 1-bit output: Write Reset Busy: Active-High indicator that the FIFO
      .din(wr_data),                     // WRITE_DATA_WIDTH-bit input: Write Data: The input data bus used when
      .injectdbiterr(1'b0), // 1-bit input: Double Bit Error Injection: Injects a double bit error if
      .injectsbiterr(1'b0), // 1-bit input: Single Bit Error Injection: Injects a single bit error if
      .rd_clk(rd_clk),               // 1-bit input: Read clock: Used for read operation. rd_clk must be a free
      .rd_en(rd_en),                 // 1-bit input: Read Enable: If the FIFO is not empty, asserting this
      .rst(fifo_rst),                     // 1-bit input: Reset: Must be synchronous to wr_clk. The clock(s) can be
      .sleep(1'b0),                 // 1-bit input: Dynamic power saving: If sleep is High, the memory/fifo
      .wr_clk(wr_clk),               // 1-bit input: Write clock: Used for write operation. wr_clk must be a
      .wr_en(wr_en)                  // 1-bit input: Write Enable: If the FIFO is not full, asserting this
   );
   
    
    
    
    
    
    
    
    
endmodule

 3.新建仿真tb文件对该模块仿真,仿真代码如下所示:

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2023/05/16 14:15:52
// Design Name: 
// Module Name: async_fifo_tb
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module async_fifo_tb(

    );
reg               wr_clk  ;//100m
reg               rd_clk  ;//50m
reg               wr_en   = 0;
wire  [31:0]       wr_data  ;
reg   [15:0]       cnt1     =  16'd0;
reg               rd_en   = 0 ;
wire [15:0]       rd_data  ;
assign   wr_data = {cnt1,cnt1};
initial begin
       wr_clk = 1'b0;
       rd_clk = 1'b0;

end
always # 10   wr_clk = ~wr_clk ;
always # 5   rd_clk = ~rd_clk ;


always@(posedge wr_clk)begin
      if(32'd50<cnt1 & cnt1<32'd550)begin
             wr_en <= 1'b1; 
      end   
      else begin
             wr_en <= 1'b0;
      end  
end
always@(posedge wr_clk)begin
       cnt1 <= cnt1+1'b1;
end

reg      [31:0]    cnt  =  32'd0;  

always@(posedge rd_clk)begin
      if(32'd500<cnt&cnt<32'd1500)begin
             rd_en <= 1'b1; 
      end   
      else begin
             rd_en <= 1'b0;
      end  
end

always@(posedge rd_clk)begin
       cnt <= cnt+1'b1;
end

 async_fifo #(
. FIFO_TYPES          (0    )              ,//‘0’fwft,‘1’为标准fifo延迟一个时钟,需要更改模式
. FIFO_WRITE_DEPTH    (2048 )              ,//fifo写深度
. READ_DATA_WIDTH     (16   )              ,//读数据位宽
. WRITE_DATA_WIDTH    (32   )              ,//写数据位宽
. PROG_EMPTY_THRESH   (10   )              ,
. PROG_FULL_THRESH    (10   )              ,
. WR_WIDTH          (12)                  ,
. RD_WIDTH          (12)                              

)async_fifo_inst
(
  .fifo_rst       (1'b0)  ,
  .wr_clk         (wr_clk)  ,
  .wr_en          (wr_en)  ,
  .wr_data        (wr_data)  ,

  .rd_clk         (rd_clk)  ,
  .rd_en          (rd_en)  ,
  .rd_data        (rd_data)  ,

  .wr_data_count   () ,
  .rd_data_count   () ,
  .empty          ()  ,
  .full           ()  ,
  .prog_empty     ()  ,
  .prog_full      ()         
    );
    
    
    
    
    
    
    
    
    
    
    
endmodule

50M时钟下一次写数据开始第一个:(写入的为32位数据,wrdata = {cnt1,cnt1})

50M时钟下一次写数据的最后一个:

100M时钟下一次读出的数据16位数据开始:

从上可以开出,连续读两个一样的数据,因为写是一次写了两个一样的16bit数据。

100M时钟下一次读出的数据16位数据结束:

由此验证完毕,输入输出异步FIFO没有出错。 

  • 3
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值