01AXI4總線axi-lite-slave(AXI4總線實戰)


軟件版本:vitis2020.2(vivado2020.2)

操作系統:WIN10 64bit

硬件平台:適用XILINX A7/K7/Z7/ZU/KU系列FPGA(米聯客MZU07A-EG開發硬件平台)

登錄"米聯客"FPGA社區-www.uisrc.com視頻課程、答疑解惑!

1.1概述

    使用XILINX 的軟件工具VIVADO以及XILINX的7代以上的FPGA或者SOC掌握AXI-4總線結束,並且可以靈活使用AXI-4總線技術完成數據的交換,可以讓我們在構建強大的FPGA內部總線數據互聯通信方面取得高效、高速、標准化的優勢。

本文實驗目的:

1:學習AXI總線協議包括AXI-FULL、AXI-Lite

2:掌握基於VIVADO工具產生AXI協議模板

3:掌握通過VIVADO工具產生AXI-lite-Slave代碼,並且會修改寄存器

4:理解AXI-lite-Slave中自定義寄存器的地址分配

5:掌握通過VIVADO封裝AXI-LITE-SLAVE 圖形化IP

6:通過仿真驗證AXI-LITE IP的工作是否正常。

1.2AXI總線協議介紹

1.2.1AXI總線概述

在XIINX FPGA的軟件工具vivado以及相關IP中有支持三種AXI總線,擁有三種AXI接口,當然用的都是AXI協議。其中三種AXI總線分別為:

AXI4:(For high-performance memory-mapped requirements.)主要面向高性能地址映射通信的需求,是面向地址映射的接口,允許最大256輪的數據突發傳輸;

AXI4-Lite:(For simple, low-throughput memory-mapped communication )是一個輕量級的地址映射單次傳輸接口,占用很少的邏輯單元。

AXI4-Stream:(For high-speed streaming data.)面向高速流數據傳輸;去掉了地址項,允許無限制的數據突發傳輸規模。

由於AXI4和AXI4-Lite信號大部分一樣,以下只介紹AXI4信號.另外對於AXI4-Stream協議不再本文中接收,后面有單獨介紹的文章。

1.2.2AXI-4總線信號功能

1:時鍾和復位

信號

方向

描述

ACLK  

時鍾源  

全局時鍾信號

ARESETn  

復位源

全局復位信號,低有效

 

寫地址通道信號:

信號

方向

描述

AWID 

主機to從機

寫地址ID,用來標志一組寫信號

AWADDR 

主機to從機

寫地址,給出一次寫突發傳輸的寫地址

AWLEN 

主機to從機

AWLEN[7:0]決定寫傳輸的突發長度。AXI3只支持1~16次的突發傳輸(Burst_length=AxLEN[3:0]+1),AXI4擴展突發長度支持INCR突發類型為1~256次傳輸,對於其他的傳輸類型依然保持1~16次突發傳輸(Burst_Length=AxLEN[7:0]+1)。

burst傳輸具有如下規則:

wraping burst ,burst長度必須是2,4,8,16

burst不能跨4KB邊界

不支持提前終止burst傳輸

AWSIZE 

主機to從機

寫突發大小,給出每次突發傳輸的字節數支持1248163264128

AWBURST 

主機to從機

突發類型:

2'b00 FIXED:突發傳輸過程中地址固定,用於FIFO訪問

2'b01 INCR :增量突發,傳輸過程中,地址遞增。增加量取決AxSIZE的值。

2'b10 WRAP:回環突發,和增量突發類似,但會在特定高地址的邊界處回到低地址處。回環突發的長度只能是2,4,8,16次傳輸,傳輸首地址和每次傳輸的大小對齊。最低的地址整個傳輸的數據大小對齊。回環邊界等於(AxSIZE*AxLEN

2'b11 Reserved 

AWLOCK 

主機to從機

總線鎖信號,可提供操作的原子性

AWCACHE 

主機to從機

內存類型,表明一次傳輸是怎樣通過系統的

AWPROT 

主機to從機

保護類型,表明一次傳輸的特權級及安全等級

AWQOS 

主機to從機

質量服務QoS

AWREGION 

主機to從機

區域標志,能實現單一物理接口對應的多個邏輯接口

AWUSER 

主機to從機

用戶自定義信號

AWVALID 

主機to從機

有效信號,表明此通道的地址控制信號有效

AWREADY 

從機to主機

表明""可以接收地址和對應的控制信號

 

2:寫數據通道信號:

信號名    

方向    

描述      

WID 

主機to從機

一次寫傳輸的ID tag

WDATA 

主機to從機

寫數據

WSTRB 

主機to從機

WSTRB[n:0]對應於對應的寫字節,WSTRB[n]對應WDATA[8n+7:8n]WVALID為低時,WSTRB可以為任意值,WVALID為高時,WSTRB為高的字節線必須指示有效的數據。

WLAST 

主機to從機

表明此次傳輸是最后一個突發傳輸

WUSER 

主機to從機

用戶自定義信號

WVALID 

主機to從機

寫有效,表明此次寫有效

WREADY 

從機to主機

表明從機可以接收寫數據

 

寫響應信號:

信號名    

方向    

描述      

BID 

從機to主機

寫響應ID tag

BRESP 

從機to主機

寫響應,表明寫傳輸的狀態

BUSER 

從機to主機

用戶自定義

BVALID 

從機to主機

寫響應有效

BREADY 

主機to從機

表明主機能夠接收寫響應

3:讀地址通道信號:

信號

方向

描述

ARID

主機to從機

讀地址ID,用來標志一組寫信號

ARADDR

主機to從機

讀地址,給出一次讀突發傳輸的讀地址

ARLEN

主機to從機

ARLEN[7:0]決定讀傳輸的突發長度。AXI3只支持1~16次的突發傳輸(Burst_length=AxLEN[3:0]+1),AXI4擴展突發長度支持INCR突發類型為1~256次傳輸,對於其他的傳輸類型依然保持1~16次突發傳輸(Burst_Length=AxLEN[7:0]+1)。

burst傳輸具有如下規則:

wraping burst ,burst長度必須是2,4,8,16

burst不能跨4KB邊界

不支持提前終止burst傳輸

ARSIZE

主機to從機

讀突發大小,給出每次突發傳輸的字節數支持1248163264128

ARBURST

主機to從機

突發類型:

2'b00 FIXED:突發傳輸過程中地址固定,用於FIFO訪問

2'b01 INCR :增量突發,傳輸過程中,地址遞增。增加量取決AxSIZE的值。

2'b10 WRAP:回環突發,和增量突發類似,但會在特定高地址的邊界處回到低地址處。回環突發的長度只能是2,4,8,16次傳輸,傳輸首地址和每次傳輸的大小對齊。最低的地址整個傳輸的數據大小對齊。回環邊界等於(AxSIZE*AxLEN

2'b11 Reserved 

ARLOCK

主機to從機

總線鎖信號,可提供操作的原子性

ARCACHE

主機to從機

內存類型,表明一次傳輸是怎樣通過系統的

ARPROT

主機to從機

保護類型,表明一次傳輸的特權級及安全等級

ARQOS

主機to從機

質量服務QoS

ARREGION

主機to從機

區域標志,能實現單一物理接口對應的多個邏輯接口

ARUSER

主機to從機

用戶自定義信號

ARVALID

主機to從機

有效信號,表明此通道的地址控制信號有效

ARREADY

從機to主機

表明""可以接收地址和對應的控制信號

4:讀數據通道信號:

信號名    

方向    

描述      

RID

從機to主機

一次讀傳輸的ID tag

RDATA

從機to主機

讀數據

RRESP 

從機to主機

讀響應,表明讀傳輸的狀態

RLAST

從機to主機

表明此次傳輸是最后一個突發傳輸

RUSER

從機to主機

用戶自定義信號

RVALID

從機to主機

寫有效,表明此次寫有效

RREADY

主機to從機

表明從機可以接收寫數據

1.2.3數據有效的情況

AXI4所采用的是一種READY,VALID握手通信機制,簡單來說主從雙方進行數據通信前,有一個握手的過程。傳輸源產生VLAID信號來指明何時數據或控制信息有效。而目地源產生READY信號來指明已經准備好接受數據或控制信息。傳輸發生在VALID和READY信號同時為高的時候。VALID和READY信號的出現有三種關系。

  1. VALID先變高READY后變高。時序圖如下:

    在箭頭處信息傳輸發生。

  2. READY先變高VALID后變高。時序圖如下:

    同樣在箭頭處信息傳輸發生。

  3. VALID和READY信號同時變高。時序圖如下:

    在這種情況下,信息傳輸立馬發生,如圖箭頭處指明信息傳輸發生。

    1.2.4突發式讀寫

    1:突發式寫時序圖

    這一過程的開始時,主機發送地址和控制信息到寫地址通道中,然后主機發送每一個寫數據到寫數據通道中。當主機發送最后一個數據時,WLAST信號就變為高。當設備接收完所有數據之后他將一個寫響應發送回主機來表明寫事務完成。

    2:突發式讀的時序圖

    當地址出現在地址總線后,傳輸的數據將出現在讀數據通道上。設備保持VALID為低直到讀數據有效。為了表明一次突發式讀寫的完成,設備用RLAST信號來表示最后一個被傳輸的數據。

    1.3創建axi4-lite-slave總線接口IP

    新建fpga工程,過程省略

    新建完成工程后,單擊菜單欄Tools->Create and Package New IP,開始創建一個AXI4-Lite接口總線IP

    選擇使用vivado自帶的AXI總線模板創建一個AXI4-Lite接口IP

    設置IP的名字為saxi_lite

     

    模板支持3中協議,分別是AXI4-Full AXI4-Lite AXI4-Stream

    總線包括Master和Slave兩種模式,這里選擇Slave模式

    這里選擇Verify Peripheral IP using AXI4 VIP 可以對AXI4-Lite快速驗證

    單擊Finish 后展開VIVADO自動產生的demo,單擊Block Design的工程,可以看到如下2個IP。其中saxi_lite_0就是我們自定義的IP,另外一個master_0是用來讀寫我們自定義的saxi_lite_0,以此驗證我們的IP正確性。

    繼續站看代碼看看里面有什么東西

    右擊Generate Output Products

    路徑uisrc/03_ip/saxi_lite_1.0/hdl路徑下的saxi_lite_v_0_S00_AXI.v就是我們的源碼。另外一個saxi_lite_v1_0.v是軟件產生了一個接口文件,如果我們自己定義IP可有可無。

    1.4程序分析

    axi總線信號的關鍵無非是地址和數據,而寫地址的有效取決於AXI_AWVALID和AXI_AWREADY,寫數據的有效取決於S_AXI_WVALID和S_AXI_WREADY。同理,讀地址的有效取決於AXI_ARVALID和AXI_ARREADY,讀數據的有效取決於S_AXI_RVALID和S_AXI_RREADY。所以以下代碼的閱讀分析注意也是圍繞以上4個信號的有效時序。

    以下程序我們把關鍵信號的代碼拆分閱讀

    1:axi-lite-slave的axi_awready

        always @( posedge S_AXI_ACLK )

        begin

         if ( S_AXI_ARESETN == 1'b0 )

         begin

         axi_awready <= 1'b0;

         aw_en <= 1'b1;

         end

         else

         begin

         if (~axi_awready && S_AXI_AWVALID && S_AXI_WVALID && aw_en)

         begin

         // slave is ready to accept write address when

         // there is a valid write address and write data

         // on the write address and data bus. This design

         // expects no outstanding transactions.

         axi_awready <= 1'b1;

         aw_en <= 1'b0;

         end

         else if (S_AXI_BREADY && axi_bvalid)

         begin

         aw_en <= 1'b1;

         axi_awready <= 1'b0;

         end

         else

         begin

         axi_awready <= 1'b0;

         end

         end

        end  

    2:axi-lite-slave的axi_awaddr

        always @( posedge S_AXI_ACLK )

        begin

         if ( S_AXI_ARESETN == 1'b0 )

         begin

         axi_awaddr <= 0;

         end

         else

         begin

         if (~axi_awready && S_AXI_AWVALID && S_AXI_WVALID && aw_en)

         begin

         // Write Address latching

         axi_awaddr <= S_AXI_AWADDR;

         end

         end

        end  

    3:axi-lite-slave的axi_wready

    當滿足(~axi_wready && S_AXI_WVALID && S_AXI_AWVALID && aw_en )==1條件,設置axi_wready有效。

        always @( posedge S_AXI_ACLK )

        begin

         if ( S_AXI_ARESETN == 1'b0 )

         begin

         axi_wready <= 1'b0;

         end

         else

         begin

         if (~axi_wready && S_AXI_WVALID && S_AXI_AWVALID && aw_en )

         begin

         // slave is ready to accept write data when

         // there is a valid write address and write data

         // on the write address and data bus. This design

         // expects no outstanding transactions.

         axi_wready <= 1'b1;

         end

         else

         begin

         axi_wready <= 1'b0;

         end

         end

        end  

    4:axi-lite-slave的寫數據寄存器

    axi-lite-slave很重要一點功能就是配合SOC的處理器部分完成一些低速外設,或者寄存器的控制。需要使用多寄存器或者外設,一般在ip代碼里面就已經設置好了。前面用vivado的模板產生自定義ip的時候,我們選擇了4個32bits寄存器,以下的模板中slv_reg0~ slv_reg3共計4個32bits寄存器。

        assign slv_reg_wren = axi_wready && S_AXI_WVALID && axi_awready && S_AXI_AWVALID;

     

        always @( posedge S_AXI_ACLK )

        begin

         if ( S_AXI_ARESETN == 1'b0 )

         begin

         slv_reg0 <= 0;

         slv_reg1 <= 0;

         slv_reg2 <= 0;

         slv_reg3 <= 0;

         end

         else begin

         if (slv_reg_wren)

         begin

         case ( axi_awaddr[ADDR_LSB+OPT_MEM_ADDR_BITS:ADDR_LSB] )

         2'h0:

         for ( byte_index = 0; byte_index <= (C_S_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 )

         if ( S_AXI_WSTRB[byte_index] == 1 ) begin

         // Respective byte enables are asserted as per write strobes

         // Slave register 0

         slv_reg0[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8];

         end

         2'h1:

         for ( byte_index = 0; byte_index <= (C_S_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 )

         if ( S_AXI_WSTRB[byte_index] == 1 ) begin

         // Respective byte enables are asserted as per write strobes

         // Slave register 1

         slv_reg1[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8];

         end

         2'h2:

         for ( byte_index = 0; byte_index <= (C_S_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 )

         if ( S_AXI_WSTRB[byte_index] == 1 ) begin

         // Respective byte enables are asserted as per write strobes

         // Slave register 2

         slv_reg2[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8];

         end

         2'h3:

         for ( byte_index = 0; byte_index <= (C_S_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 )

         if ( S_AXI_WSTRB[byte_index] == 1 ) begin

         // Respective byte enables are asserted as per write strobes

         // Slave register 3

         slv_reg3[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8];

         end

         default : begin

         slv_reg0 <= slv_reg0;

         slv_reg1 <= slv_reg1;

         slv_reg2 <= slv_reg2;

         slv_reg3 <= slv_reg3;

         end

         endcase

         end

         end

        end

    5:axi-lite-slave的axi_bvalid信號

    axi_bvalid用於告知axi master axi-slave端已經完成數據接收了

        always @( posedge S_AXI_ACLK )

        begin

         if ( S_AXI_ARESETN == 1'b0 )

         begin

         axi_bvalid <= 0;

         axi_bresp <= 2'b0;

         end

         else

         begin

         if (axi_awready && S_AXI_AWVALID && ~axi_bvalid && axi_wready && S_AXI_WVALID)

         begin

         // indicates a valid write response is available

         axi_bvalid <= 1'b1;

         axi_bresp <= 2'b0; // 'OKAY' response

         end // work error responses in future

         else

         begin

         if (S_AXI_BREADY && axi_bvalid)

         //check if bready is asserted while bvalid is high)

         //(there is a possibility that bready is always asserted high)

         begin

         axi_bvalid <= 1'b0;

         end

         end

         end

        end

    6:axi-lite-slave的axi_arready

    當條件滿足(~axi_arready && S_AXI_ARVALID)==1設置axi_arready有效,並且寄存住總線上的地址axi_araddr <= S_AXI_ARADDR

        always @( posedge S_AXI_ACLK )

        begin

         if ( S_AXI_ARESETN == 1'b0 )

         begin

         axi_arready <= 1'b0;

         axi_araddr <= 32'b0;

         end

         else

         begin

         if (~axi_arready && S_AXI_ARVALID)

         begin

         // indicates that the slave has acceped the valid read address

         axi_arready <= 1'b1;

         // Read address latching

         axi_araddr <= S_AXI_ARADDR;

         end

         else

         begin

         axi_arready <= 1'b0;

         end

         end

        end

    7:axi-lite-slave的axi_araddr

        always @( posedge S_AXI_ACLK )

        begin

         if ( S_AXI_ARESETN == 1'b0 )

         begin

         axi_arready <= 1'b0;

         axi_araddr <= 32'b0;

         end

         else

         begin

         if (~axi_arready && S_AXI_ARVALID)

         begin

         // indicates that the slave has acceped the valid read address

         axi_arready <= 1'b1;

         // Read address latching

         axi_araddr <= S_AXI_ARADDR;

         end

         else

         begin

         axi_arready <= 1'b0;

         end

         end

        end

    8:axi-lite-slave的axi_rvalid信號

    當條件滿足(axi_arready && S_AXI_ARVALID && ~axi_rvalid)==1的時候設置axi_rvalid有效,表示axi-lite-slave總線上的數據是有效的。

        always @( posedge S_AXI_ACLK )

        begin

         if ( S_AXI_ARESETN == 1'b0 )

         begin

         axi_rvalid <= 0;

         axi_rresp <= 0;

         end

         else

         begin

         if (axi_arready && S_AXI_ARVALID && ~axi_rvalid)

         begin

         // Valid read data is available at the read data bus

         axi_rvalid <= 1'b1;

         axi_rresp <= 2'b0; // 'OKAY' response

         end

         else if (axi_rvalid && S_AXI_RREADY)

         begin

         // Read data is accepted by the master

         axi_rvalid <= 1'b0;

         end

         end

        end

     

    assign S_AXI_RVALID    = axi_rvalid;

     

    9:axi-lite-slave的讀數據寄存器

    本文實驗中,axi-master寫入4個寄存器數據,然后讀出,通過查看數據是否一致可以確認axi-lite-slave工作是否正常。當slv_reg_rden有效的時候,數據被讀入寄存器axi_rdata,當axi_rvalid有效的時候,數據被鎖存。

    assign slv_reg_rden = axi_arready & S_AXI_ARVALID & ~axi_rvalid;

        

    always @(*)

        begin

         // Address decoding for reading registers

         case ( axi_araddr[ADDR_LSB+OPT_MEM_ADDR_BITS:ADDR_LSB] )

         2'h0 : reg_data_out <= slv_reg0;

         2'h1 : reg_data_out <= slv_reg1;

         2'h2 : reg_data_out <= slv_reg2;

         2'h3 : reg_data_out <= slv_reg3;

         default : reg_data_out <= 0;

         endcase

        end

     

        always @( posedge S_AXI_ACLK )

        begin

         if ( S_AXI_ARESETN == 1'b0 )

         begin

         axi_rdata <= 0;

         end

         else

         begin

         // When there is a valid read address (S_AXI_ARVALID) with

         // acceptance of read address by the slave (axi_arready),

         // output the read dada

         if (slv_reg_rden)

         begin

         axi_rdata <= reg_data_out; // register read data

         end

         end

        end

     

    當我們閱讀后分析完以上代碼后,可以發現,axi-lite-slave的代碼中沒有突發長度的處理,每次只處理一個地址的一個數據。並且也沒有WLAST和RLAST信號,說明axi-lite-slave適合一些低速的數據交互,但是可以節省一些FPGA的邏輯資源。

    1.5實驗結果

    單擊仿真

     

     

    添加觀察信號

    AXI總下依次寫入1 2 3 4,slv_reg0~slv_reg3完成數據寄存

    讀數據

     


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM