精华内容
下载资源
问答
  • IP核FIFO

    千次阅读 2021-01-03 16:20:30
    FIFO:First Input First Output,即先入先出队列,在计算机中,先进先出队列是一种传统的按序执行方法,先进入的指令先完成并引退,跟着才执行第二条指令。 主要功能包括: (1)数据的缓冲。如果数据的写入速率高,...

    部分转载~
    FIFO:First Input First Output,即先入先出队列,在计算机中,先进先出队列是一种传统的按序执行方法,先进入的指令先完成并引退,跟着才执行第二条指令。
    主要功能包括:
    (1)数据的缓冲。如果数据的写入速率高,但间隔大,且会有突发;读出速率小,但相对均匀。则通过设置相应深度的FIFO,可以起到数据暂存的功能,且能够使后续处理流程平滑,避免前级突发时,后级来不及处理而丢弃数据。
    (2)时钟域的隔离。对于不同时钟域的数据传递,则数据可以通过FIFO进行隔离,避免跨时钟域的数据传输带来的设计与约束上的复杂度。
    (3)不同宽度的数据接口。例如单片机8位数据输出,而DSP是16位数据输入,在单片机和DSP连接时就可以使用FIFO来达到数据匹配的目的。

    example:
    当模块A要发送数据给模块B,其中模块A的工作时钟是100MHz,模块B的工作时钟是80MHz。若要直接讲A数据送给B,由于时钟不同,B模块势必会丢失数据或多采集数据。
    解决问题的方案:使用FIFO,由于FIFO内部可以做跨时钟域处理,读写时钟可以不同,因此非常适合解决这类问题。
    在这里插入图片描述
    如图所示,模块C的功能如下:
    a. 模块内部包含一个FIFO,该FIFO数据位宽16bit,深度是64,有rdusedw、wrusedw、empty等指示信号。
    b. 输入数据data_in和data_in_vld都是输入clk_in时钟域的,模块首先将数据写入到内部FIFO中,等待被模块B读取。
    c. 如果内部FIFO快满时(wrusede>=61),仍然有数据要写入,为了防止FIFO溢出,丢弃该数据,不再写入FIFO。
    d. Data_out、data_out_vld和b_rdy都属于clk_out时钟域的。
    e. b_rdy是模块B产生的接收数据准备好信号,当此信号为1时,表示模块B已经准备好接收数据,本模块可以将数据发送给模块B。如果为0,表示未准备好,不能将数据发送给模块B。
    f. 当b_rdy为1时,且FIFO内有数据(rdempey==0)时,将数据送给模块B。
    使用FIFO时要保证当FIFO已经处于满状态时,就不再往FIFO里写数据;当FIFO处于空状态时,不再读FIFO的数据。

    基于Vivdao的FIFO IP核使用实例
    1、打开IP Catalog–>搜索fifo—>选择FIFO Generator
    在这里插入图片描述

    2、打开FIFO IP核的配置界面
    在这里插入图片描述
    Vivado的IP一般分为以下几个步骤:

    • Component Name:IP名称
    • Basic:基本设置
    • Native Ports:本地端口
    • Status Flags:标志位
    • Data Counts:数据数量
    • Summary:总结

    一、Basic 基本设置
    (1)IP核的一般命名规则:同步/一般_fifo_数据位宽_数据深度
    (2) Interface Type:端口类型。一般选择第一个,AXI是Xilinx特有的高速接口。
    (3)Fifo Implementation:FIFO的实现方式。
    FIFO实现方式有Common Clock同步和Independent Clocks异步两种,每种FIFO下有四种存储形式:

    1. Block RAM:使用FGPA内部的RAM。
    2. Distributed RAM:分布式RAM,使用内部的LUT和逻辑电路组成的fifo。
    3. Shift Register:移位寄存器形式,深度不大于32时可以使用。
    4. Build-in:内部自带的fifo,深度大于128可以使用。

    二、Native Ports本地接口
    在这里插入图片描述
    在这里插入图片描述

    1.Read Mode读模式

    • Standard FIFO:标准FIFO。选择这个模式,读出的数据会之后使能信号1个时钟周期,第1个数据先暂存在存储单元中,当信号变为高电平后,下1个时钟周期输出;

    • First Word Fall Through:简称FWFT FIFO。第1个数据直接送入输出缓冲区,并保持在输出总线上,当读信号变为高电平后,当前周期输出第1个数据,第2个周期输出第2个数据。
      第1个写入数据将被从ram中提前读出到读数据线,第1个数据有效与empty无效同时,即当信号有效后,读数据线将显示下一个数据地址(读出的数据与读使能信号同一个时钟周期)
      在这里插入图片描述

    • Data Port Parameters 数据接口参数
      write width 写宽度
      write depth 写深度
      read width 读宽度
      read depth 读深度
      (后面读的设置通常与写的设置相同)

    • Initialization 初始化
      Reset Pin 复位引脚
      Enable Safety Circuit 启用安全电路,一般都要选上
      Reset Type 复位类型,有两种:异步复位和同步复位
      Full Flag Reset Value 复位的值,0为低电平复位,1为高电平复 位

    三、Status Flag 标志位设置
    在这里插入图片描述
    在这里插入图片描述

    • Optional flag 选择的标志
      Almost Full Flag 几乎满标志位
      Almost Empty Flag 几乎空标志
    • Handshakiing Options 握手选项,用于设置什么时候读,什么时候写
      write port handshaking 写握手选项
      write acknowledge 写标志位 分为高有效和低有效
      overflow 溢出标志 分为高有效和低有效
      read port handshaking 写握手选项
      valid flag 有效读 分为高有效和低有效
      underflow flag 读空标志位 分为高有效和低有效
    • Programmable Flags 自定义标志位 用于自定义什么时候写满和什么时候读空的标准,可编程满或空,推荐使用可编程满或空指示信号,用于保证整包数据写入,避免数据包内的数据丢失。为保证fifo运行的可靠性,尽量多保留些阈值。
      (1)Programmable Full Type 可编程写满类型
    • No Programmable Full Threshold 不采用可编程满
    • Single Programmable Full Threshold Constant 单个门限值,将门限确认和失效门限设置为同一个值
    • Multiple Programmbale Full Threshold Constants 单独控制PROG_FULL_THRESH_ASSERT和PROG_FULL_THRESH_NEGATE
      (2)Full Threshold Assert Value 可编程满门限确认,可选端口,用于设置可编程满标记使用的确认门限,可以在复位时动态设置;拉高prog_full信号当FIFO中数据的数量大于这个值的时候。
      (3) Full Threshold Negate Value 可编程满门限失效,可选端口,用于设置可编程满标记使用的失效门限,可以在复位时动态设置;拉低prog_full信号当FIFO中数据的数量小于这个值的时候。
      (4)Programmable Empty Type 可编程空门限,可选端口,这个信号用于输出使可编程空标记(prog_empty)确认或失效的门限值,门限值可以在复位期间动态设置。
    • No Programmalbe Empty Threshold 不采用可编程读空
    • Single Programmable Empty Threshold Constant 可编程空门限,将确认门限和失效门限设置为同一个值,用PROG_EMPTY_THRESH
    • Multiple Programmbale Empty Threshold Constants 单独控制PROG_EMPTY_THRESH_ASSERT和PROG_EMPTY_THRESH_NEGATE
      (5) Empty Threshold Assert Value 可编程空门限确认,可选端口,用于设置可编程空标记使用的确认门限,可以在复位时动态设置;prog_empty拉高,当FIFO中存的数据数量小于这个值。
      (6) Empty Threshold Negate Value可编程空门限失效,可选端口,用于设置可编程满标志使用的失效门限,可以在复位时动态设置;prog_empty拉低,当FIFO中存的数据数量大于这个值。

    四、Data Counts:数据数量
    尽量不采用读/写计数,因为它采用二级制划分存储容量,会导致区分的颗粒度较大。
    在这里插入图片描述

    五、Summary 总结
    在这里插入图片描述

    对FIFO进行读写的逻辑设计:

    module fifo_read_write(
    input	wire		sclk	,
    input	wire		rst_n	,
    input	wire [7:0]  datain	,
    input	wire		data_v	,
    input	wire		r_flag	,
    output	wire [7:0]	dout
    );
    wire	almost_full,wr_ack,overflow,almost_empty,valid,underflow,prog_full,prog_empty;
    wire	w_full,r_empty;
    wire	wr_en;
    wire	rd_en;
    
    assign	wr_en = (~w_full) & data_v;
    assign	rd_en = (~r_empty) & r_flag;
    
    
    fifo_generator_0  U1(
      .clk				(		sclk				)		,
      .srst				(		rst_n			)		,
      .din				(		datain				)		,
      .wr_en			(		wr_en			)		,
      .rd_en			(		rd_en			)		,
      .dout				(		dout			)		,
      .full				(		w_full			)		,
      .almost_full		(		almost_full		)		,
      .wr_ack			(		wr_ack			)		,
      .overflow			(		overflow		)		,
      .empty			(		r_empty			)		,
      .almost_empty		(		almost_empty	)		,
      .valid			(		valid			)		,
      .underflow		(		underflow		)		,
      .prog_full		(		prog_full		)		,
      .prog_empty		(		prog_empty		)		
    );
    
    
    endmodule
    

    testbench

    `timescale	1ns/1ns
    module	tb_fifo_read_write;
    reg			sclk,rst_n;
    reg			data_v;
    reg			r_flag;
    reg	[7:0]	datain;
    wire [7:0]	dout;
    
    initial	begin
    	sclk = 0;
    	rst_n = 1;
    	#10000;
    	rst_n = 0;
    end
    
    initial	begin
    	data_v = 0;
    	datain = 0;
    	r_flag = 0;
    	#20000;
    	send_data();
    	#60;
    	read_data();
    end
    
    always	#10 sclk = ~sclk;
    
    fifo_read_write tb_fifo_read_write(
    		.sclk		(	sclk			)	,
    		.rst_n		(	rst_n			)	,
    		.datain		(	datain			)	,
    		.data_v		(	data_v			)	,
    		.r_flag		(	r_flag			)	,
    		.dout	    (	dout			)	
    );
    task	send_data;
    	integer	i;
    	begin
    		for(i=0; i<400; i=i+1)
    			begin
    				@(posedge	sclk)
    					data_v = 1'b1;
    					datain = i;
    			end
    			@(posedge	sclk)
    				data_v = 1'b0;
    				datain = 0;
    	end
    endtask
    
    task	read_data;
    		integer	i;
    		begin
    			for(i=0;i<259;i=i+1)	
    				begin
    					@(posedge	sclk)
    					r_flag = 1'b1;
    				end
    			@(posedge sclk)
    			data_v = 1'b0;
    		end
    endtask
    
    endmodule
    

    仿真波形图:
    在这里插入图片描述在这里插入图片描述在这里插入图片描述

    展开全文
  • Xilinx FIFO IP核详细解析,包含仿真

    一. IP概述

    可参考Xilinx官网fifo_generator概述

    Xilinx IP解析之FIFO Generator v13.2 -1

    以下翻译自官网此IP的概述。

    产品描述:

    LogiCORE™IP FIFO生成器内核生成经过充分验证的先进先出(FIFO)内存队列,非常适合需要按顺序存储和检索数据的应用。

    该内核为所有FIFO配置提供了优化的解决方案,并在利用最少资源的同时提供了最高性能(高达500 MHz)。通过Vivado®Design Suite提供的结构可以由用户自定义,包括宽度,深度,状态标志,存储器类型以及写/读端口的宽高比。

    主要功能和优势:

    • FIFO深度高达4,194,304字
    • FIFO数据宽度从1到1024位(对于本机FIFO配置),最大4096位(对于AXI FIFO配置)
    • 非对称纵横比(读写端口比率范围为1:8至8:1)
    • 支持独立或通用时钟域
    • 可选的存储器类型(块RAM,分布式RAM,移位寄存器或内置FIFO)
    • 本机或AXI接口(AXI4,AXI4-Lite或AXI4-Stream)
    • 同步或异步重置选项
    • 支持分组模式
    • 支持某些配置的纠错(ECC)和注入功能
    • 支持首字直通(FWFT)
    • 支持用于Block RAM和基于内置FIFO原语的实现的Embedded Register选项
    • 支持–空/满,几乎空/满和可编程的空/满信号

    二. IP产品手册

    可参考Xilinx官网fifo_generator文档

    Xilinx IP解析之FIFO Generator v13.2 -2

    可下载PG057 - FIFO Generator v13.2 Product Guide (v13.2)

    三. IP框图与信号端口

    XILINX的FIFO Generator IP提供了三种接口的FIFO,分别是Native,AXI Memory Mapped 以及 AXI Sream,我个人只用过Native即普通FIFO,所以下文只介绍这一种FIFO类型。

    3.1 IP模块框图(普通FIFO)

    Xilinx IP解析之FIFO Generator v13.2 -3

    3.2 IP信号列表

    信号名位宽必须/可选说明
    wr_clk1必须写时钟,提供给写端口使用的时钟
    wr_en1必须写使能,高有效,
    在每个写时钟上升沿被捕捉,捕捉一次写入一次数据
    full1必须满信号,高有效,
    FIFO内部写数据个数 = FIFO写深度的第一个时钟上升沿置高,
    FIFO内部写数据个数 < FIFO写深度的第一个时钟上升沿拉低。
    在full有效时,FIFO会关闭写功能,如果此时wr_en有效,full会置高overflow即输出满溢信号,FIFO中的数据没有变化,往满FIFO中写不是破坏性的。
    din1, 2, … , 1024必须写入的数据,当wr_en高被捕捉时,din被写入到FIFO中
    almost_full1可选快满信号,高有效,
    FIFO内部写数据个数 = FIFO深度 - 1的第一个写时钟上升沿置高,
    FIFO内部写数据个数 < FIFO深度 - 1的第一个写时钟上升沿拉低
    prog_full1可选设定满信号,高有效,
    参考4.3.3 Programmable Flags —— 可编程标志
    wr_rst1可选写复位,高有效,
    写复位信号有效后的第一个写时钟上升沿,FIFO被清空,并不再响应写使能,
    直到写复位信号失效后下一个写时钟上升沿(包括)开始再去响应写使能
    rd_clk1可选读时钟,
    对于同步FIFO,FIFO读写时钟合一
    对于异步FIFO,FIFO会有分开的写时钟和读时钟
    rd_en1必须读使能,高有效,在每个读时钟上升沿被捕捉,捕捉一次读出一次数据
    empty1必须空信号,高有效,
    FIFO内部读数据个数 = 0的第一个读时钟上升沿置高,
    直到FIFO内部读数据个数 > 0的第一个读时钟上升沿拉低。
    在empty有效时,FIFO会关闭读功能,如果此时rd_en有效,FIFO会置高underflow即输出空溢信号,FIFO内部的数据没有变化,读取空FIFO不是破坏性的。
    dout可设定位宽 =
    din位宽 *(1/8,1/4,1/2,1,2,4,8)
    必须读数据,读数据位宽 * 读深度 = FIFO容量 = 写数据位宽 * 写深度
    对于FWFT FIFO,dout预先有效,在读使能被捕捉的同时更新下一个读数据,
    对于标准FIFO,在读使能被捕捉的时钟过后的第二个时钟上升沿,dout才是读出的数据
    almost_empty1可选快空信号,高有效,
    FIFO内部读数据个数 = 1的第一个读时钟上升沿置高,
    FIFO内部读数据个数 > 1的第一个读时钟上升沿被拉低
    prog_empty1可选设定空信号,高有效,
    参考4.3.3 Programmable Flags —— 可编程标志

    其它信号很少使用,这里不做介绍。

    3.3 设计注意事项

    3.3.1 rst —— 复位

    在FPGA配置完成后,读写操作开始之前,FIFO必须被复位,有同步/异步两种复位可用。

    3.3.2 clk —— 时钟

    Xilinx建议,不要通过改变clk来改变FIFO的读写行为,而应该去控制读写使能信号,当时钟未稳定时,不要去操作FIFO,当时钟稳定后,先对FIFO进行复位,然后再去操作FIFO。

    3.3.2 wr_en 和 rd_en

    虽然写满和读空行为都不是破坏性的,但仍然强烈建议不要在FIFO满时置高写使能,不要在FIFO空时置高读使能。也就是wr_en的用户逻辑需要考虑full信号,rd_en的用户逻辑需要考虑empty信号。

    四. IP配置

    4.1 Basic

    image-20211205163013383

    4.1.1 FIFO接口类型

    最常用的就是Native接口类型的FIFO,即普通FIFO。

    4.1.2 FIFO实现

    FIFO实现有两个方面的含义:

    ① FIFO时钟,公共时钟就是同步FIFO,此时读写操作共用一个时钟;独立时钟就是异步FIFO,此时写操作用写时钟,读操作用读时钟。

    当选择异步FIFO时,会出现Synchronization stages —— 同步级数的选项,此选项的意思是,当FIFO中写入数据后,empty信号并不会立刻拉低,因为写入数据是基于写时钟的,而empty信号是基于读时钟的,如果Synchronization stages设定为2,则意味着empty会在FIFO中写入数据成功后的2个读时钟周期后拉低。选3就是3个读时钟周期后,以此类推。

    最小的Synchronization stages值通常和具体的器件型号有关,器件频率越快,则此选项最小选值越大,例如200MHz器件最低可以选2,而400MHz器件最低只能选4。这也告诉我们,速度越快,跨时钟域的同步越可能不稳定,需要更多级数的D触发器。

    总的来说,Synchronization stages貌似是一个不那么关键的参数,通常不需要修改

    ② 存储类型,有以下四种:

    1)Block RAM,块RAM,简称BRAM,是在FPGA内部嵌入的硬核存储器,BRAM数量是衡量FPGA性能的重要指标,采用BRAM做FIFO是性能最优的,但一个BRAM是18Kb,即使FIFO容量很小,也最少使用一个BRAM,这就造成了存储容量的浪费。

    2)Distributed RAM,分布式RAM,是使用FPGA内部的LUT即查找表资源搭建的FIFO,它的性能不及BRAM FIFO,但好处是它容量可以很灵活的配置,需要多少容量就用多少LUT去搭建,不会存在容量浪费的情况。

    3)Shift Register,移位寄存器,此存储类型只支持公共时钟,没用过。

    4)Built-in FIFO,内置FIFO,没用过。

    说明,BRAM和分布式RAM是创建FIFO最常选用的存储类型,一般来说,FIFO容量超过1024个字节就考虑使用BRAM,没超过1024字节选择分布式RAM。当然,如果芯片BRAM资源很富余的话,全部采用BRAM也是可以的。后两种基本用不到。

    4.1.3 FIFO支持的功能

    不同的芯片型号与不同的实现形式的FIFO会支持不同的功能,不必去记忆这些,在Basic界面会将对应实现的功能展示出来。功能含义如下:

    (1)non-symmetric aspect ratios(different read and write data widths),非对称纵横比 即 不同的写入与读取数据位宽,支持此功能允许读取数据位宽与写入数据位宽不同,具体的读取位宽可为输入位宽的1/8,1/4,1/2,1倍,2倍,4倍 或 8倍,当然位宽必须是整数,例如写入数据位宽=3时,读取数据位宽就只能取3,6,12,24。

    (2)First-Word Fall-Through,首字直通,简称FWFT。FIFO按是否支持此功能分别两种:

    1)Standard FIFO,标准FIFO,写入在wr_en有效的第一个wr_clk时钟上升沿完成。读数据时,rd_en有效,rdata端口经过几个读时钟周期的延迟才装载完成最外侧读数据,具体延迟周期数跟FIFO设置有关,下面会讲到。

    image-20211205165755547

    2)FWFT FIFO,首字直通FIFO,写入和标准FIFO完全相同,但FWFT FIFO会将读数据预先就装载到rdata端口上,rd_en并不是控制FIFO去输出读数据,而是控制FIFO去更新下一个读数据到rdata端口上。

    通常来说,FWFT FIFO是更易使用的,读取无延迟的优势使得读时序很容易控制。

    (3) Uses Bulit-in FIFO primitives,使用内置FIFO原语。

    (4)ECC support,ECC是Error Injection and Correction的简称,意思是错误注入和纠正。

    (5)Dynamic Error Injection,动态错误注入。

    4.1.4 Using Block RAM FIFOs Versus Built-in FIFOs,BRAM FIFO与 内置FIFO使用对比

    参考手册16页:

    内置FIFO解决方案旨在利用内置FIFO宏内部的逻辑。对于快满,快空以及其它几个特性,内置FIFO没有实现,因为它们不是宏的原生特性,需要额外逻辑来实现。

    手册中写道:基准测试表明,采用内置FIFO + 外部逻辑实现宏的非原生特性 的解决方案与直接使用BRAM FIFO相比,逻辑资源消耗小的优势在减弱。特别是对于大容量的FIFO,BRAM更具优势,所以我们强烈建议,当需要FIFO具备内置FIFO的非原生特性时,采用BRAM的实现形式而不是内置FIFO

    4.2 Native Ports

    image-20211205170711568

    4.2.1 Read Mode —— 读取模式

    选择标准FIFO与FWFT FIFO,推荐总是使用FWFT FIFO。

    4.2.2 Data Port Parameters —— 数据端口参数

    选择写位宽与写深度,以及读位宽与读深度。只有支持读写位宽不一致功能的FIFO,读位宽才是可选的,不支持此功能的话,读位宽必须等于写位宽。

    4.2.3 ECC,Output Register and Power Gating Options —— 错误注入与纠正,输出寄存器 和 功率控制选项

    ECC:只有BRAM FIFO 和 内置FIFO支持ECC功能,

    Output Register:输出寄存器,勾选此选项意思是在输出端口再插入寄存器,插入寄存器会增加输出延迟,这点在设计读取时序时需要特别注意。共有三种输出寄存器可以选择:

    1)Embedded Registers,嵌入式寄存器

    2)Fabric Registers,光纤寄存器

    3)Embedded Reg And Fabric Reg,嵌入式寄存器 + 光纤寄存器

    Power Gating:功率控制,只有UltraScale类型芯片的built-in FIFO才支持功率控制功能。当勾选Dynamic Power Gating(动态功率控制)时,输入端口会增加一个sleep信号,当sleep信号高有效时,FIFO会进入省电模式,省电模式禁止写和读,此时wr_en与rd_en都应该为低,FIFO保留内部的数据不改变,直到sleep低电平失效。

    image-20211205171420809

    Initialization:初始化,其实就是复位,复位总是高电平有效,无法修改FIFO的复位电平。同步FIFO支持同步复位和异步复位,而异步FIFO只支持异步复位。

    异步复位可控制full信号在复位期间的值。可配置复位期间读数据端口的值,不配置的话读数据端口默认为0。

    Read Latency:读延迟,只有标准FIFO才有读延迟,且会受Output Register的配置影响;FWFT FIFO读延迟始终为0。

    4.3 Status Flags

    image-20211128211026331

    4.3.1 Optional Flag —— 可选标志

    Almost Full Flag:快满信号,高有效,在FIFO内部写数据个数 >= FIFO深度 - 1之后的第一个写时钟上升沿置高,直到FIFO内部写数据个数 < FIFO深度 - 1后的第一个写时钟上升沿拉低。

    Almost Empty Flag:快空信号,高有效,在FIFO内部读数据个数 <= 1之后的第一个读时钟上升沿置高,直到FIFO内部读数据个数 > 1后的第一个读时钟上升沿拉低。

    4.3.2 Handshaking Options —— 握手选项

    Write Port Handshaking:写端口握手

    Write Ackongledge:写应答,在每次写完成后的第一个时钟上升沿置高/拉低(有效电平可配置),一次成功写入对应一个写时钟周期的写应答。

    Overflow:满溢出,在FIFO满之后仍有wr_en信号使能的第一个时钟上升沿置高/拉低(有效电平可配置),一次满溢出有效电平持续一个写时钟。

    Read Port Handshaking:读端口握手

    Valid Ackongledge:数据有效应答,在每次读完成后的第一个时钟上升沿置高/拉低(有效电平可配置),一次成功读取对应一个读时钟周期的数据有效应答。

    Underflow:空溢出,在FIFO空之后仍有rd_en信号使能的第一个时钟上升沿置高/拉低(有效电平可配置),一次空溢出有效电平持续一个读时钟。

    4.3.3 Programmable Flags —— 可编程标志

    Programmable Full Type:可编程满类型,有五个选项可选:

    image-20211205173025774

    No Programmable Full Threshold:无可编程满临界点

    Single Programmable Full Threshold Constant:单个可编程满临界点常量

    Multiple Programmable Full Threshold Constant:双向可编程满临界点常量

    Single Programmable Full Threshold Input Port:单个可编程满临界点输入端口

    Multiple Programmable Full Threshold Input Port:双向可编程满临界点输入端口

    下面是Programmable Full Type:可编程空类型,同理,不再赘述。

    可编程满标志的产生逻辑:

    当FIFO中的写数据 >= Full Therhold Assert Value中规定的数据量(取值范围:13 ~ 写入深度-1)时,可编程满置高;

    当FIFO中的写数据 <= Full Therhold Negate Value中规定的数据量(取值范围:12 ~ Full Therhold Assert Value中的值-1)时,可编程满拉低。

    可编程空标志的产生逻辑:

    同理,取值范围需要注意:

    Empty Therhold Assert Value的范围:4 ~ 读取深度-3;

    Empty Therhold Negate Value的范围:Empty Therhold Assert Value+1 ~ 读取深度-2。

    4.4 Data Counts

    image-20211205173843111

    同步FIFO对应 Data Count,异步FIFO对应 Write Data Count 以及 Read Data Count。

    Data count的位宽是可选的,当选择标准FIFO时,范围是1 ~ log2(数据深度);当选择FWFT FIFO时,范围是1 ~ log2(数据深度)+1。举例说明:

    如果数据深度 = 16,Data count位宽选择4,那显然Data count的取值范围是0~15,这意味着计数最多记到15,当FIFO满时计数应该是16,但这最后一个数不会被记。如果此时Data count位宽选为3,那么Data count可表示的数是0~7,那么FIFO中数据量 = 2,Data count才会加1,数据量 = 4,Data count才会加2,也就是说Data count被低位截断了;如果此时Data count位宽选为1,那所有低位都被截断了,意味这FIFO中数据量 = 8,Data count才会加1。

    如果勾选More Accurate Data Counts(精确计数),位宽变为1~5可选,5位宽最大可表示31,前面选的FIFO深度是16,意味着FIFO满时的最后计数16也会被记入。还有一点,选择FWFT FIFO时,FIFO的实际深度会大于设定的深度,如上面Native Ports界面的图所示,设定深度16而FWFT FIFO的实际深度是17,精确计数可以计数到实际深度17,这就是精确计数的概念。

    当选择同步FWFT FIFO时,默认就应用了精确计数,而无需手动选择。

    还需要说明的是,计数是有延迟的,不是FIFO中数据量一改变,计数值马上改变的,这个延时的周期数和器件有关。

    另外,计数通常只适用于调试,调试结束后就不在需要了,应该计数会增加额外的资料消耗,而且计数到某一个值的功能可以由可编程满/空信号来代替,显然单比特的信号更易接收和使用。

    4.5 Summary

    image-20211128214803503

    五. IP仿真

    仿真框图:

    image-20211205193212774

    对于以下关心的问题分别仿真:

    5.1 复位是否会清空FIFO,清空需要多长时间?

    image-20211205192335219

    仿真显示:对于同步,复位置高后,会在下一个时钟上升沿清空FIFO;对于异步复位则是立即清空FIFO,无需等待时钟上升沿。复位还会同时置高full和empty。

    5.2 复位结束后FIFO能马上进行写和读吗?不能的话需要间隔多少时钟周期?

    上图显示,复位结束后即rst=0后,full信号还会一直为高持续多个周期,此时FIFO不能写也不能读(没有数据),这个持续周期数对于16深度的FIFO是13个写时钟周期,对于深度32的FIFO还是13个写时钟周期,对于深度1024的FIFO是14个写时钟周期,可见FIFO从复位结束到恢复读写功能需要大约13个写时钟周期

    5.3 FWFT FIFO的实际深度会大于设定深度,那么full和almost_full信号是当数据量达到设定深度置高,还是达到实际深度才置高?

    image-20211205174008025

    对于设定深度16,实际深度17的FWFT FIFO,almost_full在写入16个数据后置高,full在写入17个数据后置高,所以满信号是以实际深度为准的。

    5.4 FIFO写入一个数据后,多久empty会失效?

    image-20211205185350800

    仿真结果显示:写入第一个数据后,经过8个读时钟周期,empty才拉低。

    5.5 可编程满和可编程空的产生逻辑是什么?

    确实如4.3.3 Programmable Flags —— 可编程标志节描述的一致,不好展示,读者可自行仿真验证。

    六. FIFO使用建议

    1.总是使用FWFT FIFO,无延迟的读便于控制

    2.资源足够时总是使用BRAM FIFO;资源紧张时,小型FIFO可使用分布式FIFO

    3.FIFO在使用之前必须复位,复位时置高full,禁止一切读写操作

    4.在产生wr_en信号时,必须和~full信号进行与操作,且必须是组合逻辑,因为时序逻辑会延迟一个写时钟才起作用,可能造成写满的情况发生,示例代码如下:

    reg wr_en_temp;
    always @(posedge clk) begin
      if (~rstn)
        wr_en_temp <= 1'b0;
      else if (data_valid)
        wr_en_temp <= 1'b1;
      else
        wr_en_temp <= 1'b0;
    
    assign wr_en = ~full && wr_en_temp;
    

    5.与产生wr_en同理,产生rd_en信号时,必须和~empty信号进行与操作,且必须是组合逻辑,防止读空的情况发生,示例代码如下:

    reg rd_en_temp;
    always @(posedge clk) begin
      if (~rstn)
        rd_en_temp <= 1'b0;
      else if (ready)
        rd_en_temp <= 1'b1;
      else
        rd_en_temp <= 1'b0;
    
    assign rd_en = ~empty && rd_en_temp;
    

    七. 工程分享

    Xilinx IP解析——FIFO Generator V13.2 Vivado 2021.2工程:

    链接:https://pan.baidu.com/s/1FIqZx29V2zkiqfib380amw
    提取码:q9fs

    展开全文
  • 【FPGA基础篇】Xilinx FIFO详细解析

    千次阅读 2021-09-06 16:24:57
    FIFO官方手册要点类型Reset写操作满标志写操作时序分析读操作空信号读操作时序分析Standard ReadFirst-Word Fall-Through同时读写时序分析握手信号Programmable FlagsData CountsNon-symmetric Aspect Ratios FIFO...


    FIFO作为FPGA岗位求职过程中最常被问到的基础知识点,也是项目中最常被使用到的IP,其意义是非常重要的。本文基于对FIFO Generator的Xilinx官方手册的阅读与总结,汇总主要知识点如下:

    类型

    FIFO的类型区分主要根据FIFO在实现时利用的是芯片中的哪些资源,其分类主要有以下四种:

    1. shift register FIFO:通过寄存器来实现的,这种类型的FIFO最好少用,因为我们都知道FF资源在FPGA是非常珍贵的。

    2. built-in FIFO:这种类型的FIFO只有7系列之后(包括UltraScale)才有。笔者的理解是一种集成的FIFO硬核

    3. Block Ram FIFO:通过块RAM的资源配置形成的FIFO,其本质是Block RAM+一些外设电路。

    4. Distributed Ram FIFO:通过分布式RAM配置形成的FIFO,与BRAM类似,只是RAM的类型不一样。

    Reset

    ​ shift register FIFO和built-in FIFO的复位信号是不可选的,即一定存在的。对于shift register FIFO和7系列的built-in FIFO,Xilinx只提供了异步复位;而对于UltraScale,复位是同步复位信号,但提供了w_rst_busy和rd_rst_busy输出信号表示FIFO是否已经复位完毕。

    ​ Block RAM FIFO 和 Distributed RAM FIFO的复位信号是可选的。对于共用时钟的FIFO,选择同步复位和异步复位的区别主要在于是否复位信号是否和共用时钟同步;当选择异步复位时,可以Enable Safety Circuit,顾名思义就是让电路更安全,即通过复位完成信号wr_rst_busy和rd_rst_busy来表示是否FIFO已经复位完成。对于独立时钟的FIFO,即读和写的时钟分开,Enable Reset Synchronication时只有一个rst(实际上这个复位是异步复位),不使能时有两个时钟域的rst,分别为wr_rst和rd_rst,而这两个复位信号实际上是同步于各自的时钟的,同时也能Enable Safety Circuit,是不是觉得好像整错了,其实Xilinx的官方文档就是这么说明的,如果还是觉得有问题,实践一下……

    ​ 其实上边的如果不理解,我自己总结了一下:看复位是同步复位还是异步复位,只需要看信号的名字,对于srst(Synchronized Reset)和wr_rst/rd_rst,这几个rst是同步复位,一个同步于共用时钟,其余两个同步于各自的时钟域;对于rst,则认为是异步复位。

    写操作

    ​ 写数据只有在din输入同时wr_ack被断言时才写入到FIFO中。这里wr_ack是对数据接收的应答,断言时表示接收成功。当然也可以不使能wr_ack,这样子其实也没什么大问题,只是wr_ack的存在会让数据的写入更加安全。

    ​ 需要注意的一个关键点是,FIFO被写满时,即使再输入数据,写入请求还是会被忽略的,FIFO中的数据保持不变。

    满标志

    ​ 满标志有full和almost_full两种。full表示不能写数据了,almost_full则表示只能再写入一个数据。当full被断言时,写请求会被忽略掉,同时overflow溢出标志被断言。

    ​ 【注】built-in FIFO不支持almost_full标志。

    写操作时序分析

    image-20210906083921164

    ​ 上图是从datasheet中copy的一个典型的写操作时序图。

    1. 当wr_en被使能为1时,表示写操作开始,并在时钟上升沿开始写入。此时full为低电平表示FIFO未满,可以写入。

    2. 当数据写入成功时,wr_ack被断言,即拉高表示数据写入成功***(此时我们还是得注意写入成功那个时刻,wr_ack实际上还是低电平,真正能检测到高电平的还是得在下个时钟沿)***

    3. 当FIFO只能再支持写一个数据时,almost_full被断言***(应该注意到,这些标志信号都是有一个cycle的延迟的,即实际上当我们检测到amost_full拉高时,最后一个数据也在同时刻写入FIFO,所以FIFO在这个时刻已经满了)***

    4. 当FIFO的almost_full拉高时,再次写入一个数据,则full也被断言。

    5. 当FIFO的full被断言时,再写入数据,wr_ack被拉低,同时overflow溢出信号被断言。

    6. 在FIFO被写满时,如果开始读操作,full信号会被拉低,此时数据又可以再次写入FIFO。

    读操作

    ​ 当read使能且FIFO不是空的时候,数据开始从FIFO读出。同时valid信号被断言表示数据有效。读操作只有在FIFO有数据时才能成功,当FIFO是空的时,此时读信号会被忽略,同时underflow会被断言表示下溢,数据输出不会发生任何变化。

    空信号

    ​ almost_empty表示FIFO即将被读空,只剩下一个数据。empty表示FIFO已经被读空,只有当FIFO再次被写入数据时,empty才会再次被拉低。almost_empty和empty都同步于rd_clk时钟域。当FIFO被读空时,再进行读写则underflow信号会被断言。

    【注】built-in FIFO不支持almost_empty信号

    当读操作和写操作同时发生在empty被断言时,写操作可以正常执行,读操作会被忽略,在下个时钟,empty和underflow被拉低后,才能继续进行读操作。

    读操作时序分析

    ​ FIFO的读操作有两种模式,Standard Read和First-Word Fall-Through。简单地说,标志读模式下,数据会在请求的下一个时钟给出,而FWFT则在请求的同一个时钟给出。

    Standard Read

    image-20210906111828367

    ​ 标准读模式下,当empty没有被断言时,表示FIFO中有数据可读。此时使能rd_en,在下个时钟上升沿即开始读取数据,同时valid被拉高表示读取数据有效。当读到FIFO只剩一个数据时,almost_empty被断言;当读完所有数据时,empty被断言。此时如果再进行读取,则underflow被断言,表示下溢,同时valid拉低表示数据无效。

    First-Word Fall-Through

    image-20210906124042278

    ​ 在FWFT模式下,数据总是能被提前获取的,可以这么理解,在我们还不需要读取FIFO的数据的时候,其实我们不在乎FIFO中第一个数据是什么,但FWFT模式下,第一个数据提前进入了准备发送的状态,即我们可以dout处看到即将输出的数据是什么,而当我们开始读的时候,下一个数据就进入准备状态,也被我们提前获取了。

    ​ 比较两种模式下的flag信号。almost_empty是在FIFO中还剩下一个数据是被断言,empty是在把最后一个数据读取完了之后被断言,在SR模式下,empty是在把最后一个数据读出来的同时拉高,在FWFT模式下,empty是在获取最后一个数据后才拉高,因为我们是提前知道最后一个数据,此时的数据还是停留在FIFO中,只有把它读出来了,FIFO才是空的,empty才会被断言。inderflow都在读空之后还试图继续读取的时候才会拉高,所以underflow总是比empty慢一拍。valid总是和数据是同步的。

    同时读写时序分析

    ​ 下图是标准读写模式下的时序图,原理前面已经讲过了,这里提供给大家验证自己的理解是否正确。

    image-20210906125634078

    握手信号

    FIFO的握手信号主要有wr_ack、valid、underflow和overflow。

    wr_ack:write acknowledge,即写操作应答。当写入成功时,wr_ack断言回应表示写入数据成功。

    valid:valid信号表示数据有效的意思,它的时序在SR和FWFT模式中均表现为数据有效,但和rd_en的时序相位有区别。

    underflow:下溢信号。当FIFO为空且继续读取数据时,则会出现下溢。

    overflow:上溢信号。当FIFO写满后还继续写入数据时,则出现上溢。

    Programmable Flags

    ​ 用户自定义阈值标志位。分为Programmable full和Programmable empty两种。前者表示FIFO写满状态的阈值,后者表示FIFO读空状态的阈值。简单地说,就是不管FIFO的深度,你想让它存入多少数据时就认为已经装满了,或者你让他认为还剩多少数据就已经算读空,可以自行设置。

    ​ 对于prog_full和prog_empty,可以设置为单阈值(single)多阈值(multiple),设置单阈值时,大于或等于(小于或等于)阈值就会断言满(空)信号。而设置多阈值,就可以出现滞留效果,以prog_full为例,当设置assert threshold为100,negate threshold为80时,当FIFO中数据没到100时,只有大于100后才会断言满,而此时断言满之后被读到100以下后,FIFO仍然认为是满的,只有持续读到小于80,才会认为未满,即negate。

    ​ 其次,对于阈值的设定,既可以设置为常数,也可以设置为一个自定义输入。当定义为自定义输入的时候,FIFO的满空状态就变成自适应的了,随时可以通过阈值输入进行修改。

    Data Counts

    ​ Data Count只能用于共用时钟。对于读写时钟分开的情况,则分别用Read Data Count和Write Data Count来表示FIFO中的数据,异步FIFO中虽然是同一个FIFO,但rd_data_cnt和wr_data_cnt中的数值不一定是相等的,为什么这么设置,因为安全!具体说明:

    Read Data Count 和 Write Data Count 都是采用的保守估计的方式。什么是保守估计,意思就是假设FIFO中至少有8个数据可读,但FIFO只跟你说我这里只有8个数据可读,那么你就会认为只能读8个数据,实际上可能能读9个或者10个,这么做的原因时为了保证FIFO读操作的安全性,后面我们分析异步FIFO的时候就能深刻理解这么做的精妙之处,这就是保守估计。类似的,当FIFO中还可以写至少8个数据时,FIFO会说只能写8个数据了,这样子你也只会写8个数据,实际上FIFO可以写9-10个左右。datasheet中的原文表述为Read data count (rd_data_count) pessimistically reports the number of words available for reading. The count is guaranteed to never over-report the number of words available in the FIFO (although it may temporarily under-report the number of words available) to ensure that the user design never underflows the FIFO.

    那么,FIFO是怎么实现这种保守估计的呢?结合下图一起分析,我们以Write Data Count为例,由于wr_data_cnt同步于wr_clk,wr_en也同步于wr_clk,所以wr_en使能后,每写入一个data,都可以在下个时钟沿反馈到wr_data_cnt上,写入一个数据,wr_data_cnt就加一;相应的,读出一个数据,wr_data_cnt也需要减一,才能正确反应FIFO中的数据量。但对于rd_en,由于rd_en是同步于rd_clk的,所以rd_en的使能需要通过一系列的时钟同步到wr_clk中才能反映到wr_data_cnt上,通常采用的方式是格雷码和打拍子的方式,如下图所示,可以看到需要将Read Counter通过格雷码转换(格雷码转换可以消除很多中间不定态,大大增强了稳定性),再进行跨时钟域传输,这里跨时钟域传输一般可以选择打拍子的方式,由于已经转化成了格雷码,此时多bit传输就可以变成单bit传输,因为相邻state只有其中一个bit发生了变化,单bit跨时钟域传输就可以采用打拍子的方式进行时钟域转换,这样子就造成了的结果就是传送到wr_clk时钟域时的Read Counter的数值是过去的Read Counter,比最新的Read Counter要小,因此Write Counter-Read Counter偏大,从而认为FIFO中有更多的数据存储(实际上并没有那么多数据),因此wr_data_cnt输出的信息就是FIFO中最多有多少个数据,至少还能写入多少个数据,而我们能知道的就是我们只要写入的数据不超过它的最小值,就能保证FIFO永远不会写满,这样子安全性就提高了。

    image-20210906153021708

    Non-symmetric Aspect Ratios

    ​ 非对称比例用于设置写数据和读数据的位宽不同的情况。用例子说明如下:

    image-20210906151526916

    上图表示1:4的Aspect Ratio,即写一次只能写一个数据,但读可以一次读四个数据,写的时候是从高位写到低位。需要注意的一个点是,对于读写非对称的情况,如上所述,假设读空了FIFO之后,empty被断言,则此时写入一个数据并不能拉低empty,必须写入至少四个才能将empty拉低,即FIFO中遵循位宽最大法则。

    展开全文
  • xilinx FIFO的使用及各信号的讨论

    千次阅读 2018-11-06 10:40:52
    FIFO的完整英文拼写为First In First Out,即先进先出。FPGA或ASIC中使用到的FIFO一般是指对数据的存储具有先进先出特性的一个存储器,常被用于数据的缓存或者...FIFO从大的情况来分,有两类结构:单时钟FIFO(SC...

    转自:http://www.eefocus.com/guoke1993102/blog/15-06/313183_36284.html

    FIFO的完整英文拼写为First In First Out,即先进先出。FPGA或ASIC中使用到的FIFO一般是指对数据的存储具有先进先出特性的一个存储器,常被用于数据的缓存或者高速异步数据的交互。

    FIFO从大的情况来分,有两类结构:单时钟FIFO(SCFIFO)和双时钟FIFO(DCFIFO),其中双时钟FIFO又可以分为普通双时钟(DCFIFO)和混合宽度双时钟FIFO(DCFIFO_MIXED_WIDTHS)。

    SCFIFO:single-clock FIFO

    DCFIFO:dual-clock FIFO(supports same port widths for input and output data)

    DCFIFO_MIXED_WIDTHS:dual-clock FIFO(supports different port widths for input and output data)

    FIFO的使用非常广泛,一般用于不同时钟域之间的数据传输,比如FIFO的一端是AD数据采集,另一端是计算机的PCI总线,假设其AD采集的速率为16位100K SPS,那么每秒的数据量为100K×16bit=1.6Mbps,而PCI总线的速度为33MHz,总线宽度32bit,其最大传输速率为33*32=1056Mbps,在两个不同的时钟域间就可以采用FIFO来作为数据缓冲。另外,对于不同宽度的数据接口也可以用FIFO,例如单片机位8位数据输出,而DSP可能是16位数据输入,在单片机与DSP连接时就可以使用FIFO来达到数据匹配的目的。

     本文就讲通过ISE软件生成一个FIFO,并对其进行一些操作以求更加了解FIFO中各个信号的作用以及控制方法(有些简单步骤将省略不提)。

     在这步中,由于现在做的不是soc工程,选择Native.

    Next后,需选择时钟和存储器类型。1,时钟,由FIFO的作用可知大部分都是读写不同步的,这里我们也选择异步模式,即读写的时钟不同。2,存储器类型,这里主要是block RAM和distribute RAM之间的区别。简而言之,block RAM是FPGA中定制的ram资源,而distribute RAM则是由LUT构成的RAM资源。由此区别表明,当FIFO较大时应选择block RAM,当FIFO较小时,选择distribute RAM.另外一个很重要的就是block RAM支持读写不同宽度,而distribute不支持。在这里为了更全面的了解FIFO,选择block RAM以拥有非对称方向速率的特性。

     读模式有两种选择,一般选择标准模式,至于First-Word Fall-Fhrough的含义请查看FIFO手册。写数据宽度定义为8位,写深度定义为256.读宽度定义为4位,而读深度将根据以上几个参数自动计算。但我们需要注意的是,在data port parameters处,有actual write depth和actual read depth,他们都比我们设置的要小,其意义以及原因将在例程中说明。

    之后便是添加信号,信号越多越难操作,但同时也能让我们更加准确的控制FIFO,这里为了更好的了解FIFO,把所有能选的信号都选上。

    接下来是复位信号以及可编程信号的配置。虽然在block RAM和distribute RAM中,复位信号不是必需的,但根据习惯,还是启用rst端口,且配置成同步复位,即整个FIFO共用一个复位信号,而不是读写不同的复位。至于编程信号,看选项就很容易理解了。配置如图,FIFO中数据达到200时,programmable full有效,数据为10时,programmable empty有效。

     之后是写计数和读计数,都使之有效,由于写深度是256,读深度是512.因此写计数器的宽度定义为8,读计数器的狂度定义为9.其实不一定计数器一定要比深度大,当计数器计数最大值小于数据深度时,例如数据深度为512,而计数器大小为256,则每两个数据计数器计数一次。

     最后可以看到我们配置的FIFO信息如下(注意几个关键信息),最后生成IP就好了。

     通过点击View HDL Instantiation Template,我们可以看到所有需要例化的信号,以及格式。

    在该FIFO例程中,首先是将1-255写入FIFO中,此时不读取,观察各个信号,然后再从FIFO中读出FIFO中存储的数据,此时不再写入,观察各信号。

    代码如下:

    module FIFO_top(
    	input clk,rst,
    	output  wire [3:0] dout
    );
    	wire clk_50M_wire;
    	wire [7:0] din_wire;
    	wire valid,wr_ack;
    	wire overflow,underflow;
    	wire almost_empty,almost_full;
    	wire [8:0] rd_data_count;
    	wire [7:0] wr_data_count;
    	wire prog_full,prog_empty;
    	wire wr_en,rd_en;
    	wire full,empty;
    	///
    	//二分频电路
    	//100M为读时钟,50M为写时钟
    	reg clk_50M;
    	assign clk_50M_wire = clk_50M ;
    
    	always @(posedge clk or posedge rst) 
    		begin
    			if (rst) 
    				clk_50M<=0;
    			else 
    				clk_50M<=~clk_50M;
    		end
    
    	
    	reg [2:0] cnt;
    	//非满时写,且满后就不再写了,即便之后数据被读取导致非满
    	assign wr_en =(full==0 && rd_en==0 && cnt==5)?1:0 ;
    	//写时不读取,写完再读取
    	assign rd_en = (empty==0 && wr_en==0)?1:0 ;
    
    	reg [7:0] din;
    	assign din_wire = din ;
    
    	always @(posedge clk_50M or posedge rst) 
    		begin
    			if (rst) 
    				begin
    					din<=1;
    				end
    			else 
    				begin
    					if(wr_en) 
    						din<=din+1;
    					else 
    						din<=din;
    				end
    		end
    
    	always @ (posedge clk_50M or posedge rst)
    		if(rst) 
    			cnt<=0;
    		else 
    			begin
    				if(cnt==3'd5) 
    					cnt<=cnt;
    				else 
    					cnt<=cnt+1;
    			end
    
    	FIFO FIFO (
    	.rst(rst), // input rst
    	.wr_clk(clk_50M_wire), // input wr_clk 50M 
    	.rd_clk(clk), // input rd_cFIFOlk 100M 
    	.din(din_wire), // input [7 : 0] din
    	.wr_en(wr_en), // input wr_en
    	.rd_en(rd_en), // input rd_en
    	.dout(dout), // output [3 : 0] dout
    	.full(full), // output full
    	.almost_full(almost_full), // output almost_full
    	.wr_ack(wr_ack), // output wr_ack
    	.overflow(overflow), // output overflow
    	.empty(empty), // output empty
    	.almost_empty(almost_empty), // output almost_empty
    	.valid(valid), // output valid
    	.underflow(underflow), // output underflow
    	.rd_data_count(rd_data_count), // output [8 : 0] rd_data_count
    	.wr_data_count(wr_data_count), // output [7 : 0] wr_data_count
    	.prog_full(prog_full), // output prog_full 200
    	.prog_empty(prog_empty) // output prog_empty 10
    	);
    endmodule

    仿真代码如下:

    `timescale 1ns / 1ps
    
    module vtf_FIFO_test;
    
        // Inputs
        reg clk;
        reg rstin_n;
    
        // Outputs
        wire [3:0] dout;
    
        // Instantiate the Unit Under Test (UUT)
        FIFO_test uut (
            .clk(clk), 
            .rstin_n(rstin_n), 
            .dout(dout)
        );
    
        initial begin
            // Initialize Inputs
            clk = 0;
            rstin_n = 0;
    
            // Wait 100 ns for global reset to finish
            #1000;
            rstin_n = 1;
            // Add stimulus here
        end
    
    	always #10 clk = ~clk;
                  
    endmodule

    1,复位信号rst: 由结果可知,其为高电平有效,且复位后其他信号的初始值是可以在产生FIFO中配置的,之前配置为0;很重要的一点是,复位后的几个写周期内(2,3个周期)是无法进行写操作的,所以在本例程中,复位一段时间后再拉高wr_en以确保首先写入的是1.

    2,写使能信号wr_en与写响应信号wr_ack:关于该信号,很重要的一点是,写入的值是wr_en拉高时的值;还是说当wr_en拉高后,下一周期才能进行写操作?如果是前者,由波形所示,写入的第一个值应该是1;如果是后者,写入的应该是2。这就需要根据读取的第一个值来判断了。而经查看,读取的第一个值为1,也就是说,只要wr_en拉高,立马就进行写操作

    从下图还能明白wr_ack的工作模式,即写入成功时,wr_ack将在下一周期拉高。也就是说,wr_ack反映的是上一周期的写操作。

    3,读使能信号rd_en与读响应信号valid:在读操作中,第一个读取的数据应该是0,第二个是1(原因之后解释)。由波形可知,当rd_en有效的那个上升沿,并没有进行读操作,而是在下一个周期才真正读取了数据,同时valid被拉高,这是与写操作所不同的地方。

    4,写计数wr_data_count和rd_data_count:因为写数据会有256个,读数据会有512个,一旦count的大小不够,count从一开始就会失效,成为高阻态,所以应该给wr_data_count设置成8位,rd_data_count设置成9位。当把wr_data_count设置成7位,rd_data_count设置成8位时,结果见图。

    正常设置时,即wr_data_count设置成8位,rd_data_count设置成9位。

    在写的过程中,可以看到,wr_data_count正常计数,每次加一,但是其值滞后2个周期。而由于读操作是每次4位,写操作是每次8位,即每次写操作都意味着需要读两次才能读出数据,所以每次写操作,rd_data_count都是加2。

    在读过程中,rd_data_count是每次减1。同理,wr_data_count则是每2次读操作才减1。

    对于这两个信号,也有不太正常的地方。如下图,当进行了读操作的时候,wr_data_count依旧保持在255不变,rd_data_count则在505和504之间切换,且其最大值不是预期的510.

    可能的原因在于wr_data_count是属于写时钟域的,读操作进行后需要一段时间才能反映到写时钟域的各个参数,这在之后的empty等信号也可以得出类似结论。

    至于rd_data_count应该是受读操作以及full或者wr_data_count等信号的共同影响,导致其在505和504之间不停变换。

    官方文档也提到说,wr_data_count以及rd_data_count是大概的,不是非常准确。

    5,prog_full;almost_full;full:Prog_full在之前的设置中是200,该值是根据wr_data_count判定的,即当wr_data_count为200时,prog_full置一。但是由于wr_data_count滞后2个周期,所以真正写入到FIFO中的值应该有202个了。

    full以及almost_full由图可知,在数据数满足要求后的下一个周期被拉高。而且当读操作进行后,这两个信号并不是立刻被拉低,和之前所提到的一样,这两个信号属于写时钟域,读操作反映到这两个信号上需要一定的时间

    6,prog_empty;almost_empty;empty:

    Prog_empty之前设置的是10,由波形图知,其信号还是比较准确的。

    Almost_empty以及empty则提早了一个周期被拉高

    也可以看到,当写操作进行时,empty等信号也不是立刻变低的,其原因也应该是属于不同时钟域。

    7,underflow;overflow: 改动程序,使写信号一直有效,可以看到当full变高后的下一周期因为继续进行写操作,使得overflow也被拉高。

    再改动程序,写操作一段时间后,读信号一直有效。可以看到当empty有效后,继续读操作,underflow将在下一周期被拉高。

    8,关于FIFO实际读写深度的问题:在之前的设置中可以看到,我们原本设置的写深度是256,读深度是512;但是边上显示的实际读写深度分别是255,510.从结果中我们也可以看到:当写到255时(数据是1~255),full被拉高。读数据以及读数据深度是根据写数据和写深度来的,自然也就是510了。也就是说实际写深度会比设置的小1,这是在工程中需要注意的地方。

    9,关于读写不对称的问题:所谓的读写不对称,即读写的位大小以及读写速率不一样。在本例程中,写入的数据是8位的,而读出的数据是4位的。那么读操作的时候是怎么样一个读出法呢?在写操作中,我们是顺序写入1~255的。通过观察读数据可知,读出的数据为:0,1,0,2,0,3……这就说明当读写非对称时,是先读取数据的高位的。

    10,关于FIFO的深度计算问题:在很多笔试面试中,都会问的FIFO的深度计算问题。因此,了解这方面也是很有必要的。

    网上有很多关于这方面的公式,在此就不做讨论了。其实很简单,只要先计算单位时间内读写数据量的差值,然后乘以持续时间,就是FIFO的最小深度了。但是这里还需要注意几点:

    1,背靠背问题,假设写数据100个wr_clk内写入80个数据,这时就需要考虑最坏的情况,就是前20个时钟不写入,接着80个时钟写入,再后来的80个时钟继续写入,最后的20个时钟不写入。这样写入数据最集中的情况就有160个时钟写入160个数据了。

    2,需要留有深度裕量,即实际的深度会比设置的小,因此应该多设置点FIFO深度,以避免丢失数据。

    展开全文
  • 嵌入式系统

    2020-01-19 22:09:14
    IP核 全称知识产权核(intellectual property core) 在集成电路的可重用设计方法学中,IP核是指某一方提供的、形式为逻辑单元、芯片设计的可重用模块。 三类IP核: 软核 通常是与工艺无关、具有寄存器传输级硬件...
  • HPM(High-Performance Matrix)是一个自生成的AMBA3 bus subsystem。... 1)write issuing capability,表示MI接口中写操作的FIFO深度,如果小于SI中的write acceptance capability可能会影响  性能。 ...
  • arm7tdmi的i2c驱动注释

    2016-03-28 13:24:15
    //这个i2c接口只支持主模式 The Master I2C Interface Module supports I2C Master Only mode with /* 1. 7 bits address DEVICE 7位设备地址 ...3. Master write to slave receiver in single or
  • 串口驱动分析之samsung.c

    千次阅读 2013-06-14 16:59:07
    //获取接收fifo中已有的数据个数,结构体s3c24xx_uart_info在文件s3c2440.c中初始化 static int s3c24xx_serial_rx_fifocnt(struct s3c24xx_uart_port *ourport,  unsigned long ufstat) {  struct s3c24...
  • 16字节发送和接收FIFO • Hardware flow control support (CTS/RTS) •硬件流控制支持(CTS / RTS) • Shadow registers to reduce software overhead and also include a software programmable reset •...
  • Frame error, Break, Receive buffer data ready, Transmit buffer empty, and Transmit shifter empty. These conditions are indicated by the corresponding UART status register (UTRSTATn/UERSTATn). ...
  • Serial UART information

    千次阅读 2011-08-07 14:16:52
    If FIFO buffering is used, more than one character can be written to the transmitter holding register when the bit signals an empty state. There is no indication of the amount of bytes currently ...
  • USB开发笔记

    2013-05-15 11:34:00
    EP8PF,表示端点8 Programmable Flag PINFLAGSAB = 0x08;表示FLAGA是EP2EF,端点2空 ——官方固件代码的注释有误 PINFLAGSCD = 0xE0;表示FLAGD是EP6FF,端点6满 ——官方固件代码的注释有误 OUT端点只有...
  • UART

    千次阅读 2012-09-14 11:08:30
    FIFO buffer memory between the receiver shift register and the host system interface. This allows the host processor even more time to handle an interrupt from the UART and prevents loss of ...
  • S3C44B0 寄存器描述

    千次阅读 2013-07-07 22:17:47
    • Supports single scan and dual scan displays • Supports virtual screen function • System memory is used as display memory • Dedicated DMA for fetching image data from system memory • ...
  • nRF24L01+ enters standby-II mode if CE is held high on a PTX device with an empty TX FIFO. If a new packet is uploaded to the TX FIFO, the PLL immediately starts and the packet is transmitted after ...
  • S3C44B0X寄存器描述

    千次阅读 2008-01-22 13:20:00
    Supports single scan and dual scan displays &S226; Supports virtual screen function &S226; System memory is used as display memory &S226; Dedicated DMA for fetching image data from system memory &S...
  • zz spru976阅读心得

    千次阅读 2010-12-25 15:43:00
    · An ERROR response is sent if the RX buffer descriptor queue has no empty buffers (there is an overflow) . · Out-of-order responses are allowed. · A RETRY response is issued to the first ...
  • 如上图,tiny4412的板子上引出了3个UART接口,分别是UART0 , 2, 3,它有5组UART,另外一组UART1用在了WIFI + BT模块,UART4没有引出来,这几组UART的区别主要是FIFO的大小,UART0的FIFO为256byte,UART1, 4的FIFO大小为64...
  • man bash

    2017-05-18 17:14:00
    All of the single-character shell options documented in the description of the set builtin command can be used as options when the shell is invoked. In addition, bash interprets the following ...
  • VLSI interview questions (1)

    千次阅读 2014-04-30 00:05:20
    c)Place as many substrate contact as possible in the empty spaces of the layout. d)Do not use poly over long distances as it has huge resistances unless you have no other choice. e)Use fingered...
  • /* tx fifo size */ unsigned char x_char; /* xon/xoff char */ unsigned char regshift; /* reg offset shift */ unsigned char iotype; /* io access style */ unsigned char unused1; #...
  • CPT104 计算机操作系统概念笔记

    千次阅读 多人点赞 2021-05-17 22:53:29
    Virtual Memory 虚拟内存 Demand Paging 按需调页 按需调页的有效访问时间The Effective Access Time (EAT) Copy-on-Write 写时复制 写时复制的问题 Page Replacement 页置换 页置换算法 First-In First-Out (FIFO) ...
  • /* tx fifo size */ unsigned char x_char; /* xon/xoff char */ unsigned char regshift; /* reg offset shift */ unsigned char iotype; /* io access style */ unsigned char unused1; #...
  • [转] A trip through the Graphics Pipeline

    千次阅读 2015-09-29 16:56:02
    转一个国外牛人的文章;深入浅出的介绍了现代GPU的方方面面,从软件到硬件都有。理解了这些对理解新一代图形API大有好处! 原文 A trip through the Graphics Pipeline 2011: Index A trip through the Graphics ...
  • bash手册

    千次阅读 2015-11-21 21:35:23
     All of the single-character shell options documented in the description of the set builtin command can be used  as options when the shell is invoked. In addition, bash interprets the following ...

空空如也

空空如也

1 2 3 4
收藏数 78
精华内容 31
关键字:

fifoip核singleprogrammableempty