01 概述
MPSoC是Xilinx基于16nm工藝推出的異構計算平臺,由于靈活、穩定,在業界得到了廣泛的使用。異構計算是一個比較新的領域,需要協調硬件設計、邏輯設計、軟件設計,對工程師的要求很高。實際設計過程中,很多工程師對實現PS/PL之間的數據交互感到頭疼。
本文將介紹主要的PS/PL之間的數據交互辦法。
02 MPSoC PS/PL之間的數據通路
在開始之前,首先簡要介紹PS/PL之間的數據通路,請參考 《UG1085 Zynq UltraScale+ MPSoC Technical Reference Manual》的Figure 1-1: AXI Interconnect。
PS/PL之間的數據通路主要是通用的AXI Memory接口,其中PS作為主設備的接口有128-bit位寬的HPM0/HPM1, 64-bit位寬的LPD_PL; PL作為主設備的接口有ACP/ACE/HPC0/HPC1/HP0/HP1/HP2/HP3。所有AXI Memory接口的位寬最高都可以支持到128-bit。
PS/PL之間主要通過PS-DDR交互大塊數據。從Figure 1-1可以看到,PS-DDR控制器有六個AXI Slave接口,與PL直接相關的是S3、S4、S5。HPC0/HPC1都連接到了CCI Interconnect。DP和HP0連接到了S3。HP1和HP2連接到了S4。HP3和FP DMA連接到了S5。如果需要提高帶寬,要充分利用PS-DDR控制器的AXI Slave接口。如果可能,HP1和HP2最好不要同時用,因為HP1和HP2都連接到了S4,最后會彼此競爭帶寬。
UG1085的Figure 1-1提供了最詳細的信息,?也有點復雜。為了簡單,也可以參考下面來自于《Zynq UltraScale+ MPSoC Technical Overview》的簡化示意圖。
在Vivado的IP 里,使能相關接口后,接口如下。
03 MPSoC PS/PL之間的簡單數據通路和簡單外設設計
很多時候,PS/PL之間只需要簡單的數據通路。PS只需要下發有限的參數給PL,PL只需要向PS反饋有限的狀態數據。串口、SPI設備、IIC等低速接口,就屬于這種設備。這種情況下,PL內部只需要實現AXI Slave接口和一些寄存器就可以,PS通過AXI接口去訪問寄存器,既向PL提供參數,也可以讀回PL的狀態。
客戶可以自己設計AXI接口和寄存器,也可以使用Vivado里的工具Create and Package IP。
04 使用Vivado里的工具Create and Package IP創建IP
如果使用Vivado里的工具Create and Package IP創建IP,可以參照下列步驟。
1) 調用Vivado的Create and Package IP 模板
2) Create and Package IP 模板介紹
3)新建IP
這一步選擇"Create a new AXI4 peripheral"。
4) IP命名和目錄
根據自己需要,指定IP的名稱和目錄。
5) IP接口選擇
可以看到,只為新的IP選擇了AXI Lite接口,并實現了16個寄存器。工程師可以根據需要選擇寄存器個數,最小4個,最多512個。對于AXI Lite接口,數據位寬是32-bit。
6) 完成IP創建
選擇“Add IP to the repository”, 點擊"Finish", 完成IP創建。
7) BD框圖
在Block Design中,選擇對應的IP。示例中是MyIP。添加后,在Block Design中,得到如下IP。可以看到,MyIP有一個AXI Slave接口,及其對應的時鐘和復位信號。
8) BD設計
AXI Lite的外設很簡單,只有一個AXI Slave接口,及其對應的時鐘和復位信號。把AXI Slave接口通過AXI Interconnect連接到某個PS的AXI Master接口,示例是M_AXI_HPM0_FPD,再提供對應的時鐘和復位信號就可以。AXI連接兩側的Mater和Slave必須使用同一個時鐘和復位信號。
9) 代碼分析
創建IP后,在指定的目錄下,得到如下的文件夾和和文件。
myip_1.0 │ component.xml │ ├─bd │ bd.tcl │ ├─example_designs │ ├─bfm_design │ │ design.tcl │ │ myip_v1_0_tb.sv │ │ │ └─debug_hw_design │ design.tcl │ myip_v1_0_hw_test.tcl │ ├─hdl │ myip_v1_0.v │ myip_v1_0_S00_AXI.v │ └─xgui myip_v1_0.tcl
myip_v1_0_S00_AXI.v里實現了寄存器及其讀寫邏輯。
實現寄存器的Verilog HDL代碼:
//---------------------------------------------- //-- Signals for user logic register space example //------------------------------------------------ //-- Number of Slave Registers 16 reg [C_S_AXI_DATA_WIDTH-1:0]slv_reg0; reg [C_S_AXI_DATA_WIDTH-1:0]slv_reg1; reg [C_S_AXI_DATA_WIDTH-1:0]slv_reg2; reg [C_S_AXI_DATA_WIDTH-1:0]slv_reg3; reg [C_S_AXI_DATA_WIDTH-1:0]slv_reg4; reg [C_S_AXI_DATA_WIDTH-1:0]slv_reg5; reg [C_S_AXI_DATA_WIDTH-1:0]slv_reg6; reg [C_S_AXI_DATA_WIDTH-1:0]slv_reg7; reg [C_S_AXI_DATA_WIDTH-1:0]slv_reg8; reg [C_S_AXI_DATA_WIDTH-1:0]slv_reg9; reg [C_S_AXI_DATA_WIDTH-1:0]slv_reg10; reg [C_S_AXI_DATA_WIDTH-1:0]slv_reg11; reg [C_S_AXI_DATA_WIDTH-1:0]slv_reg12; reg [C_S_AXI_DATA_WIDTH-1:0]slv_reg13; reg [C_S_AXI_DATA_WIDTH-1:0]slv_reg14; reg [C_S_AXI_DATA_WIDTH-1:0]slv_reg15;
寄存器寫操作的Verilog HDL代碼的部分片段:
if (slv_reg_wren) begin case ( axi_awaddr[ADDR_LSB+OPT_MEM_ADDR_BITS:ADDR_LSB] ) 4'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 ... ... default : begin slv_reg0 <= slv_reg0; ... ... slv_reg15 <= slv_reg15; end endcase end
寄存器讀操作的Verilog HDL代碼的部分片段:
// Implement memory mapped register select and read logic generation // Slave register read enable is asserted when valid address is available // and the slave is ready to accept the read address. 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] ) 4'h0 : reg_data_out <= slv_reg0; 4'h1 : reg_data_out <= slv_reg1; 4'h2 : reg_data_out <= slv_reg2; 4'h3 : reg_data_out <= slv_reg3; 4'h4 : reg_data_out <= slv_reg4; 4'h5 : reg_data_out <= slv_reg5; 4'h6 : reg_data_out <= slv_reg6; 4'h7 : reg_data_out <= slv_reg7; 4'h8 : reg_data_out <= slv_reg8; 4'h9 : reg_data_out <= slv_reg9; 4'hA : reg_data_out <= slv_reg10; 4'hB : reg_data_out <= slv_reg11; 4'hC : reg_data_out <= slv_reg12; 4'hD : reg_data_out <= slv_reg13; 4'hE : reg_data_out <= slv_reg14; 4'hF : reg_data_out <= slv_reg15; default : reg_data_out <= 0; endcase end
根據需要,可以將寄存器的某個bit,作為控制信號,連接到應用的邏輯代碼。也可以將應用邏輯代碼的某些信號,作為狀態信號,連接到寄存器的某個bit,做狀態信號,供CPU讀取。
軟件
簡單外設只有寄存器,軟件靠讀寫寄存器,就能實現對硬件的控制。
05 DMA外設設計
如果外設的數據量大,速率要求高,建議使用DMA搬移數據,使PS和PL通過DDR共享數據。
Vivado的工具Create and Package IP同樣可以創建支持DMA功能的IP。大部分步驟,和前述“簡單數據通路”一樣。在“AXI Interfaces”窗口,除了“AXI Lite”接口以外,還要增加“AXI Full Master”接口。
1) 新建AXI接口
在“AXI Interfaces”窗口,點擊“+”按鈕,能創建一個新的接口。
2) 添加AXI Master接口
在彈出的接口中,為“Interface Type”選擇"Full",為“Interface Mode”選擇"Master"。
后續操作,和簡單外設的操作一樣。
3)BD框圖
在Block Design中,選擇對應的IP。示例中是myip_dma。添加后,在Block Design中,得到如下IP。可以看到,myip_dma多了一個AXI Master接口“M00_AXI”和對應的時鐘和復位信號。值得注意的是,myip_dma還多了輸入信號m00_axi_init_axi_txn,輸出信號m00_axi_txn_done和m00_axi_error。m00_axi_init_axi_txn用于發起寫/讀傳輸;m00_axi_txn_done和m00_axi_error由于指示傳輸是否完成。
4) 代碼分析
帶有DMA的IP的文件如下。
myip_dma_1.0 │ component.xml │ ├─bd │ bd.tcl │ ├─example_designs │ ├─bfm_design │ │ design.tcl │ │ myip_dma_v1_0_tb.sv │ │ │ └─debug_hw_design │ design.tcl │ myip_dma_v1_0_hw_test.tcl │ ├─hdl │ myip_dma_v1_0.v │ myip_dma_v1_0_M00_AXI.v │ myip_dma_v1_0_S00_AXI.v │ └─xgui myip_dma_v1_0.tcl
AXI Master的HDL代碼在文件myip_dma_v1_0_M00_AXI.v中,它實現了通過AXI Master端口寫數據、讀數據的功能。讀寫的地址由參數C_M_TARGET_SLAVE_BASE_ADDR指定。
工程師需要根據自己的需要,修改相關邏輯。上述AXI Master示例中,只能向固定地址發起成對的寫、讀操作。在實際工程中,地址通常由軟件配置,寫、讀操作也經常分開。
軟件
DMA外設通常需要由軟件配置DMA操作的目標內存。如果是standalone(baremetal,裸核)代碼,缺省情況下物理地址和軟件地址一樣,直接向DMA的內存地址寄存器寫入軟件得到的地址就可以。如果是Linux下,需要先把軟件地址轉換成硬件地址,再寫入DMA的內存地址寄存器。
06 AXI Stream外設設計
在自己IP里集成DMA,可以根據項目需求定制DMA的功能,實現最優的性能,但是也會帶來設計和維護的工作量。
為了降低工作量,可以使用現成的DMA,并在IP里增加AXI Stream接口,對接AXI DMA,實現DMA功能。
大部分步驟,仍然和前述“簡單數據通路”一樣。在“AXI Interfaces”窗口,除了“AXI Lite”接口以外,選擇要增加“AXI Stream Slave”接口, 和“AXI Stream MasterMaster”接口。
1) 新建AXI接口
在“AXI Interfaces”窗口,點擊“+”按鈕,能創建一個新的接口。
2) 添加AXI Streamm口
在彈出的接口中,為“Interface Type”選擇"Stream",為“Interface Mode”選擇"Master"或者"Slave"。示例中,既添加了AXI Streamm的Master,也添加了AXI Streamm的Master。實際工程中,工程師可以根據需要只添加其中一個,或者添加多個同樣的接口。AXI Streamm的Slave,也被稱為Sink;AXI Streamm的Master,也被稱為Source。
后續操作,和簡單外設的操作一樣。
3) BD框圖
在Block Design中,選擇對應的IP。示例中是myip_stream。添加后,在Block Design中,得到如下IP。可以看到,myip_stream多了一個AXI Stream Master接口,也多了一個AXI Streamm Slave,及其對應的時鐘和復位信號。
4) AXI-DMA接口
AXI Streamm需要和IP AXI DMA搭配使用。使用AXI DMA的簡單配置就可以,比如如下配置。
AXI DMA有一個AXI Lite接口,用于PS配置;有3個 AXI Master接口,M_AXI_SG, M_AXI_MM2S, M_AXI_S2MM,用于訪問DDR等存儲器;另外還有兩個Stream接口,M_AXIS_MM2S, M_AXIS_S2MM,用于通過AXI Streamm接口交換數據。
AXI-DMA連接
如下圖所示,AXI DMA的AXI Lite接口,通過AXI Interconnect 連接到PS AXI Master接口,比如HPM0_FPD,供PS訪問。
AXI DMA的3個AXI Master接口,M_AXI_SG, M_AXI_MM2S, M_AXI_S2MM,通過AXI Interconnect 連接到PS的AXI Slave接口,比如S_AXI_HP0_FPD。AXI DMA的兩個Stream接口,M_AXIS_MM2S連接到用戶IP的S00_AXIS, M_AXIS_S2MM連接到用戶IP的M00_AXIS。
通過AXI DMA的驅動,軟件可以發起MM2S傳輸,AXI DMA先通過M_AXI_SG從PS-DDR里讀取DMA的描述符,得到數據的源地址,再通過M_AXIS_MM2S從PS-DDR里讀取數據。軟件也可以發起S2MM傳輸,AXI DMA先通過M_AXI_SG從PS-DDR里讀取DMA的描述符,得到數據的目標地址,再通過M_AXIS_S2MM向PS-DDR里寫數據。MM2S傳輸和S2MM傳輸既可以分開使用,也可以聯合使用。如果聯合使用,相當于從PS-DDR到PS-DDR的內存搬移工作。
軟件
AXI-DMA的相關軟件設計,請參考 MPSoC邏輯加速模塊數據通道快速設計。
07 PL外設其它接口 7.1. 中斷接口
用戶外設還經常用到中斷,用于向PS產生中斷,通知某些事件。Vivado的工具Create and Package IP也可以創建支持中斷功能的IP。大部分步驟,和前述“簡單數據通路”一樣。在“AXI Interfaces”窗口,勾選“Enable Interrupt Support”, 會得到一個S_AXI_INTR接口和一個中斷輸出信號irq。
通過AXI Interconnect,把S00_AXI和S_AXI_INTR接口連接連接到PS AXI Master接口,比如HPM0_FPD,供PS訪問。把中斷輸出信號irq,通過IP Concat連接到PS的輸入pl_ps_irq。
EMIO接口
PS還提供了簡單的GPIO接口:EMIO。
在PS的配置界面下的GPIO里,使能EMIO,根據自己的需要選擇數量。然后在BD界面下,就能看見EMIO的信號,包括輸出、輸入、和三態信號。工程師可以把自己的信號連接到EMIO信號上,就能使用。
軟件通過訪問GGPIO的Bank 3/4/5,可以控制GPIO,包括操作輸出狀態,和讀取輸入電平。
軟件經常需要檢查PL是否正常工作。很多時候,軟件靠檢查PL加載的done信號來確定。但done只能保證PL已經被加載,不能保證PL已經正常工作。比如,如果PL使用外部時鐘,在外部時鐘故障時,PL即使已經被加載,也沒有工作。這時候,PS去訪問PL的寄存器,會導致PS死機。更好的辦法是,PL通過EMIO向PS反饋PL是否已經正常工作。比如PL實現計數器,把計數器的輸出連接到EMIO的輸入。軟件讀取EMIO的輸入值,如果在變化,說明PL的計數器已經正常工作,那么就代表PL已經正常工作。
08 AXI Firewall
在開發過程中,可能有各種異常狀況。如果?AXI傳輸出現異常,可能導致PS死機,影響調試。為了提高系統可靠性,可以使用Xilinx提供的IP -- AXI Firewall,把它插在正常的AXI Master和 AXI Slave接口之間。下圖是AXI Firewall的連接示例。
使用軟件使能 AXI Firewall后,如果AXI傳輸出現異常,AXI Firewall會正常結束AXI傳輸,保證軟件繼續運行,工程師可以檢查AXI傳輸的錯誤。AXI Firewall輸出的錯誤信號和中斷信號,都可以連接到PS GPIO,或者ILA。工程師可以讀出具體的錯誤信息。
-
控制器
+關注
關注
112文章
16445瀏覽量
179451 -
接口
+關注
關注
33文章
8691瀏覽量
151917 -
數據通路
+關注
關注
0文章
6瀏覽量
7497
原文標題:【干貨分享】Xilinx MPSoC PS/PL之間的數據交互和外設設計
文章出處:【微信號:FPGA-EETrend,微信公眾號:FPGA開發圈】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
【FPGA ZYNQ Ultrascale+ MPSOC教程】33.BRAM實現PS與PL交互
![【FPGA ZYNQ Ultrascale+ MPSOC教程】33.BRAM實現<b class='flag-5'>PS</b>與<b class='flag-5'>PL</b><b class='flag-5'>交互</b>](https://file.elecfans.com/web1/M00/DF/88/o4YBAGAzUm6AL63LAAAk6Si3TqA719.png)
ZYNQ數據交互通路PS和PL的連接技術
Linux下如何通過UIO監控PL給到PS的中斷
![Linux下如何通過UIO監控<b class='flag-5'>PL</b>給到<b class='flag-5'>PS</b>的中斷](https://file1.elecfans.com/web2/M00/95/CC/wKgZomTnDz-Afa2AAAEzefP5obs053.jpg)
zynq 7020 PS和zynq PL是如何通話的?
請問zynq 怎么實現PS與PL數據交互,然后通過UART串口打印出來?
【正點原子FPGA連載】第十四章基于BRAM的PS和PL的數據交互領航者 ZYNQ 之嵌入式開發指南
ZYNQ的ARM和FPGA數據交互——AXI交互最重要的細節
實例詳解:如何利用Zynq-7000的PL和PS進行交互?
![實例詳解:如何利用Zynq-7000的<b class='flag-5'>PL</b>和<b class='flag-5'>PS</b>進行<b class='flag-5'>交互</b>?](https://file1.elecfans.com//web2/M00/A6/59/wKgZomUMPQ6AXgRDAABdykFia5k464.jpg)
datamover完成ZYNQ片內PS與PL間的數據傳輸
![datamover完成ZYNQ片內<b class='flag-5'>PS</b>與<b class='flag-5'>PL</b>間的<b class='flag-5'>數據</b>傳輸](https://file1.elecfans.com//web2/M00/A6/A6/wKgZomUMP2KAFZWrAAAifb3N8rA249.png)
Zynq PS / PL 第四篇:Adam Taylor MicroZed系列之 24
![Zynq <b class='flag-5'>PS</b> / <b class='flag-5'>PL</b> 第四篇:Adam Taylor MicroZed系列之 24](https://file1.elecfans.com//web2/M00/A6/AA/wKgZomUMP36AF5szAACDNopBhtw714.jpg)
評論