FIFO在FPGA中,一般用于不同时域之间的数据传递,在俩个的时域中传递数据时就可以采用FIFO来作为数据缓冲。但在异步数据处理的过程中,常常因为en信号的不准确导致数据读取失败或丢失,本文整理了一些文档关于控制信号的内容,供参考学习。
1.1 分类:
根据数据出现在输出总线上的时间不同分为不同的种类。
普通FIFO(Normal mode):每次在使能位有效的情况下,读时钟和写时钟的上升沿来时,将数据读出 ,一个时钟一个数据。
预取FIFO(Show-ahead mode):写时同普通FIFO一样,读时数据提前输出到总线上,比普通FIFO早一个时钟。
1.2 FIFO阻塞
如果一个进程为了从FIFO中读取数据而阻塞打开了FIFO,那么称该进程内的读操作为设置了阻塞标志的读操作。如果有进程写打开FIFO,且当前FIFO为空,则对于设置了阻塞标志的读操作来说,将一直阻塞下去,直到有数据可以读时才继续执行;对于没有设置阻塞标志的读操作来说,则返回0个字节。
1.3 FIFO读操作处理方式
两种方式来读FIFO,都是基于标准FIFO,非预读FIFO:
第一种,有数就读。 这种方式很简单,将fifo_empty信号取反就是fifo_rden信号,即 fifo_rden <= not fifo_empty;
第二种,根据下级模块或者其他外部条件读数。这种情况稍微复杂一点。适用情况是并不是有数据就读,需要等待前面操作步骤完成。
但是对FIFO的读操作是容易犯错误的。如果对almost_empty或者empty信号用的不好,就可能导致FIFO中残留一个数据,或者FIFO已空,却还在进行读操作,将FIFO中最后一个数据两次写入下级模块中。
1.4 Xilinx FIFO generator IP复位释放方式
FIFO手册上说明:复位完成后需要延时3个时钟才能进行FIFO读写操作,则从仿真波形上也可以看出full信号在复位完成3个时钟之后才拉低,所以这点需要注意一下。
In this configuration, the FIFO requires a minimum asynchronous reset pulse of 1 write clock period (WR_CLK/CLK). After reset is detected on the rising clock edge of write clock, 3 write clock periods are required to complete proper reset synchronization. During this time, the FULL, ALMOST_FULL, and PROG_FULL flags are asserted. After reset is deasserted, these flags deassert after three clock periods (WR_CLK/CLK) and the FIFO can then accept write operations.
读操作:由于采用的是常规读操作模式,则置高rd_en一个时钟之后读数据才输出,对应valid有效信号延时rd_en一个时钟,valid正好对齐dout。
注意full ,almost_full等信号的变化,almost_full延时一个时钟之后full信号才置高,都是跟随写时钟变化的。full信号跟随写时钟,empty信号跟随读时钟。
1.5 读写小tips
-
当读完FIFO内数据的同时,读端口状态并不会马上响应,rdempty不会高电平有效。这是由于FIFO有读保护逻辑,所以更新才会慢上两拍,如果此时再更具该信号判断FIFO是否可读必然会处错误.
-
在异步时钟下,读写计数是大概不准的。
-
58 assign wr_en = (!full && !rd_en && (cnt == 3'd5)) ? 1'b1 : 1'b0;//非满时写,且满后就不再写了,即便之后数据被读取导致非满 59 assign rd_en = (empty == 1'b0 && wr_en == 1'b0) ? 1'b1 : 1'b0;//写时不读取,写完再读取
参考文档
【2】FIFO 读写操作
【4】fifo读写使能怎么控?