AXI4的主機協議代碼分析
一、模塊分析
(1)端口列表
input wire INIT_AXI_TXN, // Asserts when ERROR is detected output reg ERROR, // Asserts when AXI transactions is complete output wire TXN_DONE, // AXI clock signal input wire M_AXI_ACLK, // AXI active low reset signal input wire M_AXI_ARESETN, // Master Interface Write Address Channel ports. Write address (issued by master) output wire [C_M_AXI_ADDR_WIDTH-1 : 0] M_AXI_AWADDR, // Write channel Protection type. // This signal indicates the privilege and security level of the transaction, // and whether the transaction is a data access or an instruction access. output wire [2 : 0] M_AXI_AWPROT, // Write address valid. // This signal indicates that the master signaling valid write address and control information. output wire M_AXI_AWVALID, // Write address ready. // This signal indicates that the slave is ready to accept an address and associated control signals. input wire M_AXI_AWREADY, // Master Interface Write Data Channel ports. Write data (issued by master) output wire [C_M_AXI_DATA_WIDTH-1 : 0] M_AXI_WDATA, // Write strobes. // This signal indicates which byte lanes hold valid data. // There is one write strobe bit for each eight bits of the write data bus. output wire [C_M_AXI_DATA_WIDTH/8-1 : 0] M_AXI_WSTRB, // Write valid. This signal indicates that valid write data and strobes are available. output wire M_AXI_WVALID, // Write ready. This signal indicates that the slave can accept the write data. input wire M_AXI_WREADY, // Master Interface Write Response Channel ports. // This signal indicates the status of the write transaction. input wire [1 : 0] M_AXI_BRESP, // Write response valid. // This signal indicates that the channel is signaling a valid write response input wire M_AXI_BVALID, // Response ready. This signal indicates that the master can accept a write response. output wire M_AXI_BREADY, // Master Interface Read Address Channel ports. Read address (issued by master) output wire [C_M_AXI_ADDR_WIDTH-1 : 0] M_AXI_ARADDR, // Protection type. // This signal indicates the privilege and security level of the transaction, // and whether the transaction is a data access or an instruction access. output wire [2 : 0] M_AXI_ARPROT, // Read address valid. // This signal indicates that the channel is signaling valid read address and control information. output wire M_AXI_ARVALID, // Read address ready. // This signal indicates that the slave is ready to accept an address and associated control signals. input wire M_AXI_ARREADY, // Master Interface Read Data Channel ports. Read data (issued by slave) input wire [C_M_AXI_DATA_WIDTH-1 : 0] M_AXI_RDATA, // Read response. This signal indicates the status of the read transfer. input wire [1 : 0] M_AXI_RRESP, // Read valid. This signal indicates that the channel is signaling the required read data. input wire M_AXI_RVALID, // Read ready. This signal indicates that the master can accept the read data and response information. output wire M_AXI_RREADY
識別方法:M_AXI作為前綴,表明是主機的AXI協議變量。AR開頭的是讀地址,AW開頭的是寫地址,R開頭的是讀數據,W開頭的是寫數據,B開頭的是寫響應。這是五個通道的基本判斷(前面是后面的必要條件,但不是充分條件,即AR不一定是讀地址,例如ARESETN是低電平復位信號,具體的看英文注釋即可判斷)。
(2)clogb2函數
function integer clogb2 (input integer bit_depth); begin for(clogb2=0; bit_depth>0; clogb2=clogb2+1) bit_depth = bit_depth >> 1; end endfunction
這個函數的功能就是返回一個整型變量的位寬深度(也就是二進制的有效數據,排除前面的多余0所剩下的位寬)。
(3)內部信號聲明
xilinx的IP中端口信號一定是大寫的,內部使用信號則是小寫,方便閱讀時判斷信號是否為端口列表中的信號。端口信號需要考慮和其他模塊連接的問題,二內部信號則沒有這么多的考慮。
(4)初始化信號init_txn_ff2
//Generate a pulse to initiate AXI transaction. always @(posedge M_AXI_ACLK) begin // Initiates AXI transaction delay if (M_AXI_ARESETN == 0 ) begin init_txn_ff <= 1'b0; init_txn_ff2 <= 1'b0; end else begin init_txn_ff <= INIT_AXI_TXN; init_txn_ff2 <= init_txn_ff; end end
采用兩級reg延時將INIT_AXI_TXN初始化信號接收過來。
(5)寫地址通道的實現
always @(posedge M_AXI_ACLK) begin //Only VALID signals must be deasserted during reset per AXI spec //Consider inverting then registering active-low reset for higher fmax if (M_AXI_ARESETN == 0 || init_txn_pulse == 1'b1) begin axi_awvalid <= 1'b0; end //Signal a new address/data command is available by user logic else begin if (start_single_write) begin axi_awvalid <= 1'b1; end //Address accepted by interconnect/slave (issue of M_AXI_AWREADY by slave) else if (M_AXI_AWREADY && axi_awvalid) begin axi_awvalid <= 1'b0; end end end
使用開始寫入信號觸發寫地址通道的握手信號。寫通道初始信號也是由其控制的。
always @(posedge M_AXI_ACLK) begin if (M_AXI_ARESETN == 0 || init_txn_pulse == 1'b1) begin write_index <= 0; end // Signals a new write address/ write data is // available by user logic else if (start_single_write) begin write_index <= write_index + 1; end end
(6)寫數據通道的實現
由於前面在從機的時候就詳細地介紹了如何區分每個信號的作用。這里不再列舉代碼,對源碼感興趣的可以在vivado的工程中尋找。這里關注如何理解這些信號的變化,為理解時序圖打下基礎。
axi_wvalid受start_single_write控制拉高,由其他信號拉低。這個實際上需要對整個數據傳輸的流程有所認識,這里不做解釋。
(7)寫響應通道
axi_bready:等待握手信號,等待從機發送寫完成后握手信號。
(8)讀地址通道
read_index:讀初始化信號
axi_arvalid:讀地址通道的握手信號。
(9)讀數據通道
axi_rready:讀數據等待握手信號。
read_resp_error:讀數據錯誤信號。
這里的基本功能和從機的lite形似,但是,作為主機,其還有重要的邏輯需要實現。在基本的通道構建完成后,還需要對其作為主機的協調和鏈接選擇的功能實現。
二、系統功能
(1)寫入地址
axi_awaddr在M_AXI_AWREADY和axi_awvalid握手成功后即寫入地址32'h0000_0004的地址位。
//Write Addresses always @(posedge M_AXI_ACLK) begin if (M_AXI_ARESETN == 0 || init_txn_pulse == 1'b1) begin axi_awaddr <= 0; end // Signals a new write address/ write data is // available by user logic else if (M_AXI_AWREADY && axi_awvalid) begin axi_awaddr <= axi_awaddr + 32'h00000004; end end
(2)寫入數據
axi_wdata在寫入數據握手成功后即可將初始化的數據write_index寫入數據通道。具體實現和前面的寫入地址是一致的。
(3)讀地址
將axi_araddr通道加上想要讀的地址即可實現。和前面的實現方式一樣,都是等待握手成功后完成地址操作。由expected_rdata實現地址的接收。
(4)指令連接狀態機
IDLE負責實現所有信號初始化。INIT_WRITE負責將初始化寫信號。INIT_READ負責初始化讀信號。INIT_COMPARE負責處理讀寫沖突信號。具有報錯的作用。具體實現方法在代碼中可以一一看到。
(5)終端寫入統計
通過一個last_write信號表明寫入數據的結束。可以切入時鍾刻度得到數據寫入的數量。
(6)最后寫入校對
writes_done可以完成用於和last_write比較,校對寫入的數據是否有正確的寫響應信號。
(7)終端讀取統計
last_read可以判斷最后一位數據的讀取完成。
(8)最后讀取校對
reads_done可以在last_read基礎上加上讀握手判斷,用於判斷讀數據是否成功。
(9)報錯機制
read_mismatch用於數據的判斷讀信號是否匹配。error_reg用於判斷存儲的數據和傳輸的數據是否匹配。判斷方法就是是否有錯誤的信號。
三、總結反思
相對於AXI4從機的協議,主機需要的內容顯然更多,抽象的層次也不一樣。從機可以直接得到通道的信號得到數據,而主機則需要更多的判斷機制。需要使用線路判斷邏輯和錯誤信號判斷邏輯來支持數據的傳輸。這些額外的邏輯需要認真學習。事實上,其他的傳輸邏輯也是需要這些部分的輔助的。這個學會了,其他的也就觸類旁通了。