如圖是該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_tready信號的拉高,然后等待一個寫周期,S_AXIS_tvalid拉高,這個時候,數據便開始寫入FIFO。
在寫入的時候給了兩次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需要保持高電平。
讀取端的控制信號同理。
參考資料: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