Xilinx FIFO IP中两种读模式的简单分析

Xilinx FIFO的两种读模式

目标

本文主要是对 Xilinx FIFO中的两种读模式:Standard 与 FWFT 模式进行简单的分析。弄清楚在设置不同的读写长度下,两种模式内部信号是如何变化的,有什么差异。便于后续使用这个IP

FWFT模式相比Strandard模式的特点

在First-Word-Fall-Through(FWFT)读模式下,用户可以预先的查看FIFO中下一个数据内容。读潜伏期为0

而在Standard模式下,用户在发起读使能后,经过1个或者2个读潜伏期后,才能读取数据。读潜伏期>1

实验配置

实验环境在Vivado 2021. 1 下进行,使用modelsim 作为仿真工具

本文设置FIFO数据宽度为 16 位,数据深度为256 , 同时设置了一些常用的信号,具体配置如下:

对于 FWFT模式的实验配置如下





对于 Standard模式的实验配置如下




从两种模式配置的总结页面可以看到二者的有
1. 对于FWFT模式 读潜伏期为0 ,而Standard模式 读潜伏期为1
2. 对于FWFT模式,数据深度相比设置的256, 增加至了258。而Standard模式没有发生改变

实验代码

在代码中,对FIFO的一些临界情况,以及普通情况进行了测试,具体如下

C 复制代码
`timescale 1ns/1ps
module tb_fifo();

reg      i_clk     ;
reg      i_rst     ;

initial begin
    i_clk = 0;
end

always #5 i_clk = ~i_clk;


reg   [15:0]        i_din       ;
reg                 i_din_valid ;
reg                 i_rd_en     ;

wire  [15:0]        w_fifo_fwft_dout   ;
wire                w_fifo_fwft_empty  ;
wire                w_fifo_fwft_full   ;
wire  [8:0]         w_fifo_fwft_count  ;
wire                w_fifo_fwft_wrbusy ;
wire                w_fifo_fwft_rdbusy ;
wire                w_fifo_fwft_almost_full ;
wire                w_fifo_fwft_almost_empty;

wire  [15:0]        w_fifo_standard_dout   ;
wire                w_fifo_standard_full   ;
wire                w_fifo_standard_empty  ;
wire  [7:0]         w_fifo_standard_count  ;
wire                w_fifo_standard_wrbusy ;
wire                w_fifo_standard_rdbusy ;
wire                w_fifo_standard_almost_full ;
wire                w_fifo_standard_almost_empty;

initial begin
    gen_rst(10);
end

initial begin
    i_din = 0;
    i_din_valid  = 0;
    i_rd_en = 0;
    wait(~i_rst);
    @(posedge i_clk);
    //读写一个数据
    gen_din(1);
    repeat(2) @(posedge i_clk);
    gen_rd_en(1);

    //读写两个数据
    repeat(5) @(posedge i_clk);
    gen_din(2);
    repeat(2) @(posedge i_clk);
    gen_rd_en(2);

    //读写255个数据
    repeat(5) @(posedge i_clk);
    gen_din(255);
    repeat(2) @(posedge i_clk);
    gen_rd_en(255);

    //读写256个数据
    repeat(5) @(posedge i_clk);
    gen_din(256);
    repeat(2) @(posedge i_clk);
    gen_rd_en(256);

    //读写257个数据
    repeat(5) @(posedge i_clk);
    gen_din(257);
    repeat(2) @(posedge i_clk);
    gen_rd_en(257);

    //读写258个数据
    repeat(5) @(posedge i_clk);
    gen_din(258);
    repeat(2) @(posedge i_clk);
    gen_rd_en(258);

    //读写259个数据
    repeat(5) @(posedge i_clk);
    gen_din(259);
    repeat(2) @(posedge i_clk);
    gen_rd_en(259);
end

task gen_rst(input [15:0] Tcnt);
begin
    i_rst = 1;
    repeat(Tcnt) @(posedge i_clk);
    i_rst = 0; 
end
endtask

task gen_rd_en(input [15:0] Tcnt);
begin
    i_rd_en = 1  ;
    repeat(Tcnt) @(posedge i_clk);
    i_rd_en = 0  ;
end
endtask

task gen_din(input [15:0] data);
integer i;
begin
   for(i = 1 ; i <= data ; i = i + 1)
   begin
        i_din = i;
        i_din_valid = 1;
        @(posedge i_clk); 
    end 
   i_din = 0;
   i_din_valid = 0;
end
endtask



FIFO_16x256_FWFT FIFO_16x256_FWFT_U0 (
    .clk                               (i_clk                     ),// input wire clk
    .srst                              (i_rst                     ),// input wire srst
    .din                               (i_din                     ),// input wire [17 : 0] din
    .wr_en                             (i_din_valid               ),// input wire wr_en
    .rd_en                             (i_rd_en                   ),// input wire rd_en
    .dout                              (w_fifo_fwft_dout          ),// output wire [17 : 0] dout
    .full                              (w_fifo_fwft_full          ),// output wire full
    .almost_full                       (w_fifo_fwft_almost_full   ),// output wire almost_full
    .empty                             (w_fifo_fwft_empty         ),// output wire empty
    .almost_empty                      (w_fifo_fwft_almost_empty  ),// output wire almost_empty
    .data_count                        (w_fifo_fwft_count         ),// output wire [10 : 0] data_count
    .wr_rst_busy                       (w_fifo_fwft_wrbusy        ),// output wire wr_rst_busy
    .rd_rst_busy                       (w_fifo_fwft_rdbusy        ) // output wire rd_rst_busy
);


FIFO_16x256_Standard FIFO_16x256_Standard_U0 (
    .clk                               (i_clk                        ),// input wire clk
    .srst                              (i_rst                        ),// input wire srst
    .din                               (i_din                        ),// input wire [17 : 0] din
    .wr_en                             (i_din_valid                  ),// input wire wr_en
    .rd_en                             (i_rd_en                      ),// input wire rd_en
    .dout                              (w_fifo_standard_dout         ),// output wire [17 : 0] dout
    .full                              (w_fifo_standard_full         ),// output wire full
    .almost_full                       (w_fifo_standard_almost_full  ),// output wire almost_full
    .empty                             (w_fifo_standard_empty        ),// output wire empty
    .almost_empty                      (w_fifo_standard_almost_empty ),// output wire almost_empty
    .data_count                        (w_fifo_standard_count        ),// output wire [9 : 0] data_count
    .wr_rst_busy                       (w_fifo_standard_wrbusy       ),// output wire wr_rst_busy
    .rd_rst_busy                       (w_fifo_standard_rdbusy       ) // output wire rd_rst_busy
);

endmodule

实验分析


i_din_valid 作为两个FIFO的写入使能,可以观察到写入一个数据后,对于Standard模式 empty信号立即拉低,而对于FWFT模式empty信号并不会立即拉低。当写入三个数据后,FWFT模式下的empty信号才拉低,也可以理解为FWFT模式下,写入数据后延迟两个时钟周期empty才会拉低

将读写的周期加大后,可以看到确实如此。

写入两个数据后,对于Standard模式,almost_empty 会拉低,说明几乎空信号 最低的阈值是1。对于FWFT模式,almost_empty 在延迟一个周期后才会拉低,说明几乎空信号 最低的阈值也是1,或者可以理解为在连续写入的过程中,FWFT模式下,几乎空信号 最低的阈值是2

对于count信号 ,两种模式下写入时都会开始自增,读出数据时开始自减。

同时也可以看到在FWFT模式下,dout 输出与i_rd_en 读使能是同步的

而在Standard模式下,dout 输出与i_rd_en 读使能相差一个时钟周期。

配置完成时,在IP的总结页面上可以看到Standard模式下最大的数据深度为256 ,在波形图中可以看到当写入257个数据时,full信号 在256处被拉高了,而almost_full信号 在255处被拉高。

在FWFT模式下最大的数据深度为258 ,在波形图中可以看到当写入258个数据时,full信号 在258处被拉高了,而almost_full信号 在257处被拉高。

两种模式下,full信号 都是在写入数据最大深度后立即拉低,almost_full信号阈值都是1

总结

信号 FWFT模式 Standard模式 备注
读潜伏期 0 1 一般详细的数值可以看配置界面的总结部分
dout 用户可以提前看到下一个数据的值,数据相较读使能没有延迟 需要等待读使能的触发,数据相较读使能延迟一个时钟周期 无
full 在写入数据最大深度后立即拉低 在写入数据最大深度后立即拉低 无
empty 写入数据后 ,延迟两个时钟周期拉低或写入三个数据后拉低 数据写入后,信号立即拉低 无
almost_full 阈值为1,写入最大数据深度-1时拉高 阈值为1,写入最大数据深度-1时拉高 无
almost_empty 阈值为1,写入两个数据后延迟一个周期后才会拉低或连续写入下,阈值为2 阈值为1,写入两个数据后信号拉低 无
data_cout 写时自增,读时自减 写时自增,读时自减 无

FIFO Generator v13.2 Product Guide (PG057)

相关推荐
ALINX技术博客11 分钟前
8 通道同步采样 ADC!AN706 波形显示实验 【FPGA黑金云课堂】
fpga开发
szxinmai主板定制专家8 小时前
RK3568+FPGA+CODESYS异构控制方案:赋能半导体设备与工业自动化升级
人工智能·fpga开发·自动化·rk3576·半导体设备
辰丁电子9 小时前
allegro入门教程-菜单栏Logic
fpga开发·pcb设计·pcb工艺·layout·pcb layout
FPGA小徐1 天前
数字IC/FPGA设计基础_ILA原理与使用
fpga开发
FPGA小徐1 天前
FPGA 部署 YOLO 完整指南:从模型量化到 Zynq PS+PL 硬件加速
yolo·fpga开发
dadaobusi1 天前
学习:chiesel,scala
学习·fpga开发·scala
爱吃汽的小橘1 天前
异步FIFO核心揭秘:格雷码与指针同步
fpga开发
璞致电子1 天前
基于 P201Pro | 接收端基础知识——Costas环锁定后为何仍会错?DQPSK与前导码相位校正(6)
经验分享·fpga开发·ad9361·软件无线电·sdr·qpsk·pzsdr
璞致电子2 天前
基于 AD9361 (PZSDR‑P201Pro) 软件无线电实战综述:从板卡选型、硬件平台升级到 GNU Radio QPSK 完整收发链路
经验分享·嵌入式硬件·fpga开发·软件无线电·sdr·璞致电子
炎龙铠甲会合体2 天前
从 SPEC 到上板:在 Zynq-7020 上用 RTL 手写一个 YOLO 卷积加速器(完整教程)
yolo·fpga开发·axi·芯片验证