1
定义
FIFO(First In First Out )先入先出存储器,在FPG设计中常用于跨时钟域的处理,FIFO可简单分为同步FIFO和异步FIFO。同步FIFO可理解为读写时钟同源且频率相同的FIFO,异步FIFO为读写时钟不同源,时钟频率不一样的FIFO。
2
同步FIFO的仿真
该仿真基于XIlinx的fifo generator13.2进行设计,IP core的配置如下。
由图所示,时钟模式配置为common clock,FIFO深度为16,FIFO数据位宽为36bit,其中32bit为数据位宽,4bit为用户自定义比特tuser。下图为FIFO例化的IPcore。
理论情况下FIFO的数据传输时序如下
当复位拉高后,FIFO模块若没有满,s_axis_tready信号会拉高,然后用户将s_axis_valid信号拉高就可以向FIFO里面写入有效的数据了,这就发起了写操作;此时在主端口用户可将m_axis_tready拉高,FIFO若不为空,则m_tvalid信号会拉高,此时就可以源源不断的从FIFO里读出数据了,这就发起了读操作。
下面讨论下在同步FIFO中的两种情况
2.1 读写时钟为100M,m_axis_tready在m_axis_tvaild后,此时的仿真图如下所示。
由上图所示,在用户侧还未将m_axis_tready拉高之前,valid到来后,FIFO输出的数据就不为0了,而是FIFO中存入的第一个数据,一直到用户将m_axis_tready拉高,才会输出FIFO里的下一个数据。所以并不是我们理解的,只有用户发起FIFO读,FIFO才会输出数据。
2.2 读写时钟为100M,m_axis_tready在m_axis_tvaild前,此时的仿真图如下所示。
由上图所示,在FIFO的valid数据到来之前,我们先将tready拉高,这样就不会在读操作之前FIFO就吐出数据了。在做设计时,将复位拉高后,随即将tready拉高即可。
3
** 异步FIFO的仿真**
做异步FIFO时,IPCORE的配置如下图所示
时钟模式配置为independent clock,FIFO深度为16,FIFO数据位宽为36bit,其中32bit为数据位宽,4bit为用户自定义比特tuser。
理论情况下FIFO的数据传输时序如下
由上图所示,读速率是写速率的1/2,因此写不是连续的,读速率是连续的。下面分几个情况进行讨论。
3.1 写为100M读为30.3M,m_trady在m_tvaild前
由上图所示,写数据也不连续,s_tready为周期性有效,切换周期和读时钟周期一样,其中高电平时间为一个写数据时钟周期。
3.2 写为50M读为100M,m_trady在m_tvaild前
由上图所示,此时读数据不连续,m_tvalid为周期性有效,切换周期和写时钟周期一样,其中高电平时间为一个读数据时钟周期。
4
对不同深度配置进行讨论
4.1当FIFO深度为16时
由上图可知,若读数据不及时,比较滞后,则FIFO可以存入15个数据,当FIFO满后,s_axis_tready拉低,不能继续写FIFO,当读操作开始时,FIFO将从存入的第一个数据依次输出。
4.2 当fifo为32时
由上图可知,若读数据不及时,比较滞后,则FIFO可以存入33个数据,当FIFO满后,s_axis_tready拉低,不能继续写FIFO,当读操作开始时,FIFO将从存入的第一个数据依次输出。
5
在仿真时遇到的问题
在仿真时提示说t_user管脚找不到,但打开代码和block_design看了下,该端口是存在的,后面把block_design删掉,重新例化新模块后,问题解决,目前不知道是什么问题导致。
6
激励文件
`timescale 1ns / 1ps
module tb_fifo( );
reg [31:0] s_axis_tdata ;
wire s_axis_tready;
reg s_axis_tvalid;
reg [3:0] s_axis_tuser ;
reg m_aclk ;
reg s_aclk ;
reg s_aresetn ;
wire [31:0] m_axis_tdata ;
reg m_axis_tready;
wire m_axis_tvalid;
wire [3:0] m_axis_tuser ;
initial begin
s_aresetn = 1'b0;
s_axis_tdata = 32'h0000_0001;
s_axis_tvalid = 1'b0;
m_aclk =1'b1;
s_aclk =1'b1;
s_axis_tuser = 4'b1010;
#50
s_aresetn = 1'b1;
#10
s_axis_tvalid = 1'b1;
end
initial begin
m_axis_tready = 1'b0;
#340
m_axis_tready= 1'b1;
end
always #10 s_aclk = ~s_aclk;
always #5 m_aclk = ~m_aclk;
always @(posedge s_aclk) begin
s_axis_tdata = s_axis_tdata +1'b1;
end
design_1_wrapper tb_design_fifo_wrapper (
.S_AXIS_0_tdata (s_axis_tdata ),
.S_AXIS_0_tready(s_axis_tready),
.S_AXIS_0_tvalid(s_axis_tvalid),
.S_AXIS_0_tuser (s_axis_tuser ),
.m_aclk_0 (m_aclk ),
.s_aclk_0 (s_aclk ),
.s_aresetn_0 (s_aresetn ),
.M_AXIS_0_tdata (m_axis_tdata ),
.M_AXIS_0_tready(m_axis_tready),
.M_AXIS_0_tvalid(m_axis_tvalid),
.M_AXIS_0_tuser (m_axis_tuser)
);
endmodule
-
FPGA设计
+关注
关注
9文章
428浏览量
26514 -
存储器
+关注
关注
38文章
7487浏览量
163808 -
FIFO存储
+关注
关注
0文章
103浏览量
5970 -
时钟源
+关注
关注
0文章
93浏览量
15958
发布评论请先 登录
相关推荐
评论