如图是该fifo的配置图,vivado版本2018.2.
AXI4-Stream Data FIFO 配置

AXI4-Stream Data FIFO 配置

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_tready信号的拉高,然后等待一个写周期,S_AXIS_tvalid拉高,这个时候,数据便开始写入FIFO。
在这里插入图片描述在写入的时候给了两次S_AXIS_tlast信号,然后观察读出端的情况。

在这里插入图片描述然后我们可以看到,S_AXIS_tlast被传递到读取端,这个时候将M_AXIS_tready拉低,我们可以看到,读取被禁止,同时继续写入数据,观察数据写满的情况。然后过一段时间后再将M_AXIS_tready拉高,可以看到,S_AXIS_tlast再次被传递。
在这里插入图片描述

S_AXIS_tlas被传递

从下图可以看出,当FIFO写满以后,S_AXIS_tready会被拉低,这个时候数据将不能写入,当M_AXIS_tready被拉高,读取段开始读取数据,这时FIFO非满,S_AXIS_tready又被拉高。
在这里插入图片描述

同时,我们将S_AXIS_tvalid拉低,可以看到,当数据读完以后,M_AXIS_tvalid被拉高。
在这里插入图片描述
通过仿真可以看出只有当 S_AXIS_tvalidS_AXIS_tready同时为高时,数据才能写入,而S_AXIS_tready表示FIFO非满,S_AXIS_tvalid由用户控制。S_AXIS_tlast表示写入的最后一个数据,读取端同理,需要注意的是,S_AXIS_tkeep需要保持高电平。
读取端的控制信号同理。
参考资料:https://www.xilinx.com/support/documentation/ip_documentation/axis_interconnect/v1_1/pg035_axis_interconnect.pdf
以下是仿真代码

`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
Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐