版权声明:本文为博主原创文章,转载请声明原作者。 https://blog.csdn.net/QQ286615275/article/details/90297888
如图是该fifo的配置图,vivado版本2018.2.
General Options
Component Name
- 器件名字
FIFO depth
- FIFO的深度,可以在16到32768之间变化,具体情况视情况而定,但要是2的n次幂。
Enable packet mode
- 使能包模式:此项设定需要TLAST信号被使能。FIFO的操作在包模式下被修改为存储传送的数据,直到TLAST信号被响应。当TLAST信号被响应或者FIFO满了,存储的数据将被送至AXI4-Stream
master interface.
Asynchronous Clocks
- 异步时钟:启用后S_AXIS_ACLK和M_AXIS_ACLK将会是异步时钟。
Synchronization Stages across Cross Clock Domain Logic
- 当启用异步时钟后,才会有该选项,其作用相当于跨时钟域时的打拍操作。一般默认即可。
ACLKEN Conversion Mode
-
此选项用来选择ACLKEN信号的转换模式。
-
None 没有和这个IP相关的ACLKEN 信号相关
-
S AXIS Only 有一个与S_AXIS_ACLKEN 相关联的 S_AXIS_ACLK信号,但没有M_AXIS_ACLKEN信号
-
M AXIS Only 有一个与M_AXIS_ACLKEN 相关联的 M_AXIS_ACLK信号,但没有S_AXIS_ACLKEN 信号
-
S AXIS & M AXIS
两个时钟都有与它们相关的ACLKEN信号。
Signal Properties:
信号特性:可以看到,软件可以自动计算,当然我们也可以手动修改。
TDATA width (bytes)
- 参数指定axi4流上TData信号的宽度(以字节为单位接口。此参数是一个整数,可以从0到512不等。设置为0以忽略TDATA信号。如果省略了tdata信号,则tkeep和tstb信号也会省略。如图设置为4则可以看到位宽为32bit。
Enable TSTRB
- 是否使能TSTRB信号,只有当TData width(bytes)参数大于0时,才能启用此选项。
Enable TKEEP
- 是否使能TKEEP信号,只有当TData width(bytes)参数大于0时,才能启用此选项。
Enable TLAST
- 是否使能TKEEP信号,只有当TData width(bytes)参数大于0时,才能启用此选项。
TID width (bits)
- 用来指定TID信号的位宽,0为忽略,1~32为相应的位宽。
TDEST width (bits)
- 用来指定TDEST 信号的位宽,0为忽略,1~32为相应的位宽。
TUSER Width (bits)
- 用来指定TUSER 信号的位宽,0为忽略,1~32为相应的位宽。
关于这些信号的具体含义以及时序关系,可以通过仿真观察。
仿真
起始信号
在写入的时候给了两次S_AXIS_tlast信号,然后观察读出端的情况。 然后我们可以看到,S_AXIS_tlast被传递到读取端,这个时候将M_AXIS_tready拉低,我们可以看到,读取被禁止,同时继续写入数据,观察数据写满的情况。然后过一段时间后再将M_AXIS_tready拉高,可以看到,S_AXIS_tlast再次被传递。
从下图可以看出,当FIFO写满以后,S_AXIS_tready会被拉低,这个时候数据将不能写入,当M_AXIS_tready被拉高,读取段开始读取数据,这时FIFO非满,S_AXIS_tready又被拉高。
同时,我们将S_AXIS_tvalid拉低,可以看到,当数据读完以后,M_AXIS_tvalid被拉高。
通过仿真可以看出只有当 S_AXIS_tvalid和S_AXIS_tready同时为高时,数据才能写入,而S_AXIS_tready表示FIFO非满,S_AXIS_tvalid由用户控制。S_AXIS_tlast表示写入的最后一个数据,读取端同理,需要注意的是,S_AXIS_tkeep需要保持高电平。
读取端的控制信号同理。
以下是仿真代码
`timescale 1 us / 1 ps module data_fifo_wrapper (M_AXIS_tdata, M_AXIS_tkeep, M_AXIS_tlast, M_AXIS_tvalid, S_AXIS_tready, axis_data_count, axis_rd_data_count, axis_wr_data_count ); output [15:0]M_AXIS_tdata; output [1:0]M_AXIS_tkeep; output M_AXIS_tlast; reg M_AXIS_tready; output M_AXIS_tvalid; output S_AXIS_tready; output [31:0]axis_data_count; output [31:0]axis_rd_data_count; output [31:0]axis_wr_data_count; wire [15:0]M_AXIS_tdata; wire [1:0]M_AXIS_tkeep; wire M_AXIS_tlast; wire M_AXIS_tvalid; reg [15:0]S_AXIS_tdata; reg [1:0]S_AXIS_tkeep; reg S_AXIS_tlast; wire S_AXIS_tready; reg S_AXIS_tvalid; wire [31:0]axis_data_count; wire [31:0]axis_rd_data_count; wire [31:0]axis_wr_data_count; reg m_axis_aclk; reg m_axis_aresetn; wire s_axis_aclk; reg s_axis_aresetn; initial begin m_axis_aclk = 0; M_AXIS_tready = 0; m_axis_aresetn = 1; s_axis_aresetn = 1; S_AXIS_tdata = 0; S_AXIS_tlast = 0; S_AXIS_tvalid = 0; S_AXIS_tkeep = 0; end always #5 m_axis_aclk = ~m_axis_aclk; assign #2.5 s_axis_aclk = m_axis_aclk;//异步时钟 integer i; initial begin #100; m_axis_aresetn = 0; s_axis_aresetn = 0; #100; s_axis_aresetn = 1; m_axis_aresetn = 1; @(posedge S_AXIS_tready);//等待FIFO准备好 @(posedge s_axis_aclk);//对齐时钟 S_AXIS_tvalid = 1;//写有效 S_AXIS_tkeep = 2'b11; for(i=0;i<512;i=i+1)//写512个数据 begin @(posedge s_axis_aclk) S_AXIS_tdata = S_AXIS_tdata + 1; end @(posedge s_axis_aclk) S_AXIS_tlast = 1;//写最后一个数据 S_AXIS_tdata = S_AXIS_tdata + 1; @(posedge s_axis_aclk) S_AXIS_tlast = 0; for(i=0;i<16;i=i+1) begin @(posedge s_axis_aclk) S_AXIS_tdata = S_AXIS_tdata + 1; end @(posedge s_axis_aclk) S_AXIS_tlast = 1; @(posedge s_axis_aclk) S_AXIS_tlast = 0; #200; @(posedge m_axis_aclk) M_AXIS_tready = 1;//读数据 # (10*520); M_AXIS_tready = 0; for(i=0;i<600;i=i+1) begin @(posedge s_axis_aclk) S_AXIS_tdata = S_AXIS_tdata + 1; end M_AXIS_tready = 1; S_AXIS_tvalid = 0; # (10*1024); end data_fifo data_fifo_i (.M_AXIS_tdata(M_AXIS_tdata), .M_AXIS_tkeep(M_AXIS_tkeep), .M_AXIS_tlast(M_AXIS_tlast), .M_AXIS_tready(M_AXIS_tready), .M_AXIS_tvalid(M_AXIS_tvalid), .S_AXIS_tdata(S_AXIS_tdata), .S_AXIS_tkeep(S_AXIS_tkeep), .S_AXIS_tlast(S_AXIS_tlast), .S_AXIS_tready(S_AXIS_tready), .S_AXIS_tvalid(S_AXIS_tvalid), .axis_data_count(axis_data_count), .axis_rd_data_count(axis_rd_data_count), .axis_wr_data_count(axis_wr_data_count), .m_axis_aclk(m_axis_aclk), .m_axis_aresetn_0(m_axis_aresetn), .s_axis_aclk(s_axis_aclk), .s_axis_aresetn(s_axis_aresetn)); endmodule
文章来源: https://blog.csdn.net/QQ286615275/article/details/90297888