軟件版本:vitis2020.2(vivado2020.2)
操作系統:WIN10 64bit
硬件平台:適用XILINX A7/K7/Z7/ZU/KU系列FPGA(米聯客(milianke)MZU07A-EG硬件開發平台)
登錄"米聯客"FPGA社區-www.uisrc.com視頻課程、答疑解惑!
5.1概述
AXI4-Stream去掉了地址,允許無限制的數據突發傳輸規模,AXI4-Stream接口在數據流傳輸中應用非常方便,本來首先介紹了AXI4-Stream協議的型號定義,並且給出了一些Stream接口的時序方案圖。之后通過VIVADO自帶的AXI4模板,創建axi-stream-master和axi-stream-slave ip。通過圖形設計連線,添加仿真激勵完成驗證。
本文實驗目的:
1:掌握基於VIVADO工具產生AXI協議模板
2:掌握通過VIVADO工具產生AXI-Stream代碼
3:掌握通過VIVADO封裝AXI-Stream圖形化IP
4:通過仿真驗證AXI-Stream IP的工作是否正常。
5.2AXI4-Stream協議介紹
5.2.1信號定義
信號 |
源 |
描述 |
ACLK |
時鍾源 |
信號在ACLK信號上升沿采樣 |
ARESETn |
復位源 |
復位信號,ARESETn低電平有效 |
TVALID |
master |
TVALID代表主設備數據有效,當TVALID和TREADY同時有效完成數據收發 |
TREADY |
slave |
TREADY表示從設備准備可以,主設備可以發送數據,當TVALID和TREADY同時有效完成數據收發 |
TDATA[(8n-1):0] |
master |
TDATA axi-stream的數據 |
TSTRB[(n-1):0] |
master |
TSTRB[n-1:0]對應的bit位為1代表對應的字節有效,否則無效,但是會占用這個數據位。 |
TKEEP[(n-1):0] |
master |
KEEP[n-1:0]對應的bit位為1代表對應的字節有效,否則為空,可以丟掉。 |
TLAST |
master |
TLAST代表最后一個數據。 |
TID[(i-1):0] |
master |
TID是數據流的標識符,用來表明不同的數據流。 |
TDEST[(d-1):0] |
master |
TDEST為據流提供路由信息。 |
TUSER[(n-1):0] |
master |
TUSER一般用於數據的同步,代表stream數據的開始。 |
以上所有信號,在axi-stream傳輸中,不一定全部用到,具體根據應用場景的情況而定。
5.2.1axi-stream方案展示
下圖中除了ACLK外,axi-stream的信號用到了,TVALID、TREADY、TLAST、TDATA。其中TDATA雖然是12bit但是實際上會占用16bit的物理總線。並且數據是循環發送,用TLAST標識了一次循環的最后一個數據。
下圖中截圖來自AXI-DMA mm2s接口的時序圖,除了ACLK外,axi-stream的信號用到了,TVALID、TREADY、TLAST、TDATA、TKEEP。用TLAST標識了一次循環的最后一個數據。
下圖中是來自於xilinx vivado自帶的axis_vid_out ip的視頻輸出時序。EOL就是tlast ,SOF就是tuser初次外還包括了VALID、READY、DATA信號。
5.3創建axi-stream-slave總線接口IP
新建fpga工程,過程省略
5.4創建axi-stream-master總線接口IP
未來完成axi-steam協議的驗證,采用以上方法,我們再創建一個saxis的IP
創建完成后如下圖所示
5.5創建FPGA圖像化設計
設置IP路徑
添加已經創建好的IP
輸入關鍵詞axis,在最后可以看到,雙擊添加Ip
完成連線
maxis的ip參數設置
saxis的ip參數設置
自動創建頂層文件
5.6創建仿真文件
仿真程序非常簡單,只要提供時鍾和復位信號
`timescale 1ns / 1ns /* Company : Liyang Milian Electronic Technology Co., Ltd. Brand: 米聯客(milianke) Technical forum:uisrc.com taobao1: milianke.taobao.com taobao2: osrc.taobao.com jd:milianke.jd.com Create Date: 2019/12/17 Module Name: axis_top_sim Description: Copyright: Copyright (c) msxbo Revision: 1.0 Signal description: 1) _i input 2) _o output 3) _n activ low 4) _dg debug signal 5) _r delay or register 6) _s state mechine */ ////////////////////////////////////////////////////////////////////////////////
module axis_top_sim();
reg m00_axis_aclk_0; reg m00_axis_aresetn_0;
system_wrappertem system_wrapper_inst ( .m00_axis_aclk_0(m00_axis_aclk_0), .m00_axis_aresetn_0(m00_axis_aresetn_0) );
initial begin m00_axis_aclk_0 = 1'b0; m00_axis_aresetn_0 = 1'b0; #100; m00_axis_aresetn_0 = 1'b1; end
always begin #5 m00_axis_aclk_0 = ~m00_axis_aclk_0; end
endmodule |
5.7程序分析
默認的maxis模板才的代碼有bug,我們對其進行修改.
1:把以下代碼替換默認的代碼並且保存
`timescale 1 ns / 1 ps
module maxis_v1_0_M00_AXIS # ( // Width of S_AXIS address bus. The slave accepts the read and write addresses of width C_M_AXIS_TDATA_WIDTH. parameter integer C_M_AXIS_TDATA_WIDTH = 32, // Start count is the number of clock cycles the master will wait before initiating/issuing any transaction. parameter integer C_M_START_COUNT = 32 ) ( // Global ports input wire M_AXIS_ACLK, // input wire M_AXIS_ARESETN, // Master Stream Ports. TVALID indicates that the master is driving a valid transfer, A transfer takes place when both TVALID and TREADY are asserted. output wire M_AXIS_TVALID, // TDATA is the primary payload that is used to provide the data that is passing across the interface from the master. output wire [C_M_AXIS_TDATA_WIDTH-1 : 0] M_AXIS_TDATA, // TSTRB is the byte qualifier that indicates whether the content of the associated byte of TDATA is processed as a data byte or a position byte. output wire [(C_M_AXIS_TDATA_WIDTH/8)-1 : 0] M_AXIS_TSTRB, // TLAST indicates the boundary of a packet. output wire M_AXIS_TLAST, // TREADY indicates that the slave can accept a transfer in the current cycle. input wire M_AXIS_TREADY ); // Total number of output data localparam NUMBER_OF_OUTPUT_WORDS = 8;
// function called clogb2 that returns an integer which has the // value of the ceiling of the log base 2. function integer clogb2 (input integer bit_depth); begin for(clogb2=0; bit_depth>0; clogb2=clogb2+1) bit_depth = bit_depth >> 1; end endfunction
// WAIT_COUNT_BITS is the width of the wait counter. localparam integer WAIT_COUNT_BITS = clogb2(C_M_START_COUNT-1);
// bit_num gives the minimum number of bits needed to address 'depth' size of FIFO. localparam bit_num = clogb2(NUMBER_OF_OUTPUT_WORDS);
// Define the states of state machine // The control state machine oversees the writing of input streaming data to the FIFO, // and outputs the streaming data from the FIFO parameter [1:0] IDLE = 2'b00, // This is the initial/idle state
INIT_COUNTER = 2'b01, // This state initializes the counter, once // the counter reaches C_M_START_COUNT count, // the state machine changes state to SEND_STREAM SEND_STREAM = 2'b10; // In this state the // stream data is output through M_AXIS_TDATA // State variable reg [1:0] mst_exec_state; // Example design FIFO read pointer reg [bit_num-1:0] read_pointer;
// AXI Stream internal signals //wait counter. The master waits for the user defined number of clock cycles before initiating a transfer. reg [WAIT_COUNT_BITS-1 : 0] count; //streaming data valid wire axis_tvalid; //Last of the streaming data wire axis_tlast; wire tx_en; //The master has issued all the streaming data stored in FIFO wire tx_done;
// I/O Connections assignments assign M_AXIS_TVALID = axis_tvalid; assign M_AXIS_TDATA = read_pointer; assign M_AXIS_TLAST = axis_tlast; assign M_AXIS_TSTRB = {(C_M_AXIS_TDATA_WIDTH/8){1'b1}};
// Control state machine implementation always @(posedge M_AXIS_ACLK) begin if (!M_AXIS_ARESETN) // Synchronous reset (active low) begin mst_exec_state <= IDLE; count <= 0; end else case (mst_exec_state) IDLE: mst_exec_state <= INIT_COUNTER; INIT_COUNTER: // The slave starts accepting tdata when // there tvalid is asserted to mark the // presence of valid streaming data if ( count == C_M_START_COUNT - 1 ) begin mst_exec_state <= SEND_STREAM; end else begin count <= count + 1; mst_exec_state <= INIT_COUNTER; end
SEND_STREAM: // The example design streaming master functionality starts // when the master drives output tdata from the FIFO and the slave // has finished storing the S_AXIS_TDATA if (tx_done) begin mst_exec_state <= IDLE; end else begin mst_exec_state <= SEND_STREAM; end endcase end
//tvalid generation //axis_tvalid is asserted when the control state machine's state is SEND_STREAM and //number of output streaming data is less than the NUMBER_OF_OUTPUT_WORDS. assign axis_tvalid = ((mst_exec_state == SEND_STREAM) && (read_pointer < NUMBER_OF_OUTPUT_WORDS));
// AXI tlast generation assign axis_tlast = (read_pointer == NUMBER_OF_OUTPUT_WORDS - 1'b1)&& tx_en;
assign tx_done = axis_tlast;
//FIFO read enable generation
assign tx_en = M_AXIS_TREADY && axis_tvalid;
// Streaming output data is read from FIFO always @( posedge M_AXIS_ACLK ) begin if(!M_AXIS_ARESETN) begin read_pointer <= 0; end else if (tx_en) begin read_pointer <= read_pointer + 32'b1; end end
endmodule |
2:在Tcl Console中輸入reset_project對工程IP復位
3:之后單擊Refresh IP Catalog
最后單擊upgrade Selected完成更新
在看看看saxis的源碼,這部分代碼非常簡單
首先是狀態機,當S_AXI_TVALID有效,saxis的狀態機進入WRITE_FIFO
只要接收的數據小於(write_pointer <= NUMBER_OF_INPUT_WORDS-1)並且saxis狀態機是WRITE_FIFO狀態機,表示saxis可以接收數據,設置axis_tready==1
如下:assign axis_tready = ((mst_exec_state == WRITE_FIFO) && (write_pointer <= NUMBER_OF_INPUT_WORDS-1));
write_pointer 用於寫入了多少個數據。
寫數據到fifo中
5.8實驗結果
仿真結果