Xilinx-PYNQ_Z2系列-學習筆記(12):使用pynq進行PS和PL的通信方式

Xilinx-PYNQ_Z2系列-學習筆記(12):使用pynq進行PS和PL的通信方式

該博文參考pynq官方手冊:https://pynq.readthedocs.io/en/v2.3/overlay_design_methodology/pspl_interface.html

PS/PL接口

Zynq PS 與PL之間一共有9個AXI 接口,在PL一側有4個AXI Master HP(High Performance)口,2個AXI Master GP(General Purpose)口,2個AXI Slave GP口跟1個AXI Master ACP口,在PS一側擇相反,master跟slave相互調換。
在這裏插入圖片描述

對應pynq主要有四個類用來管理PS(包括PS DRAM)和PL之間的數據移動。

  • GPIO(General Purpose Input/Output)基本的輸入輸出
  • MMIO(Memory Mapped IO)內存映射的輸入輸出
  • Xlnk(Memory allocation)內存申請
  • DMA(Direct Memory Access)直接內存訪問

其中使用哪個類取決於IP連接到的Zynq PS接口以及IP的接口。

在PYNQ上運行的python代碼可以訪問連接到AXI Slave GP的IP。此時MMIO接口可以用來執行該操作。

連接到AXI Master 端口的IP不受PS的直接控制。AXI Master端口允許IP直接訪問DRAM,因此在這操作之前需要爲IP分配內存,Xlnk可以完成此任務。

爲了在PS DRAM和IP之間實現更高性能的數據傳輸,可以使用DMA

1. PS GPIO

PS和PL之間一共有64 bit GPIO,PS的GPIO可以作爲一種在PS和PL數據交換的簡單的方法,比如中斷控制信號、復位控制信號。另外,使用GPIO,IP核並不需要通過映射內存到系統的方式進行通信。
在這裏插入圖片描述

舉例:

from pynq import GPIO

output = GPIO(GPIO.get_gpio_pin(0), 'out')
input = GPIO(GPIO.get_gpio_pin(1), 'in')

output.write(0)
input.read()

在這裏插入圖片描述
代碼解讀:
>>>from pynq import GPIO: 將GPIO類導入,從而使用GPIO類中的一些函數。

>>>GPIO.get_gpio_pin(0): 用來獲得一個GPIO的pin值,這裏gpio_user_index是從0開始的一個數字。

從上圖可以看出,該函數的返回值pin number爲GPIO的基地址+GPIO偏移量+用戶輸入的index,這裏的GPIO基地址=906,GPIO偏移量爲54,用戶index=0。所以GPIO.get_gpio_pin(0)的返回值爲960。

>>>output = GPIO(GPIO.get_gpio_pin(0), ‘out’): 通過GPIO類的初始化來獲得一個配置好方向和pin號對應的GPIO對象。
在這裏插入圖片描述
這裏將此對象賦給output。
>>>output.write(0): 通過調用函數實現對該pin number對應的GPIO進行讀寫操作。
在這裏插入圖片描述

2. MMIO

連接到AXI GP端口的任何IP都將映射到系統內存中去,可以使用MMIO從Python訪問IP的寄存器或地址空間。一個MMIO讀寫命令可以傳輸32bit的數據,但由於MMIO不支持突發指令,所以MMIO適合IP通過PS的AXI slave GP口讀取少量的數據。
在這裏插入圖片描述
舉例:

IP_BASE_ADDRESS = 0x40000000
ADDRESS_RANGE = 0x1000
ADDRESS_OFFSET = 0x10

from pynq import MMIO
mmio = MMIO(IP_BASE_ADDRESS, ADDRESS_RANGE)

data = 0xdeadbeef
mmio.write(ADDRESS_OFFSET, data)
result = mmio.read(ADDRESS_OFFSET)

代碼解讀:
這段示例首先申請了一段以0x40000000爲基地址,設置1000爲地址範圍MMIO,並設置0x10爲偏移量。

>>>mmio = MMIO(IP_BASE_ADDRESS, ADDRESS_RANGE): 通過MMIO類來獲得一個配置好基地址和地址範圍的MMIO對象,並賦給mmio。
在這裏插入圖片描述
>>>mmio.write(ADDRESS_OFFSET, data): 調用mmio的write函數實現對MMIO的偏移量下的地址進行數據的寫入。
在這裏插入圖片描述
>>>result = mmio.read(ADDRESS_OFFSET): 通過讀該地址寫的數據,發現是之前寫入的0xdeadbeef。

3. Xlnk

該接口必須申請內存後才能被IP使用,所以我們可以使用xlnk來申請一段連續內存緩衝區,該緩衝區允許PS跟PL之間進行有效的數據傳輸,Python或者其他在linux運行的代碼都可以使用這段內存。
當我們Pynq在linux運行的時候,申請的緩衝區存在於Linux虛擬內存中,我們可以使用IP的AXI master的端口對Zynq的AXI Slave端口進行訪問,並且使用overlay的方式可以進入然物理地址,xlnk可以提供物理內存的指針到緩存區,然後通過緩存區給到IP。

舉例:

#分配內存緩衝區
from pynq import Xlnk
import numpy as np

xlnk = Xlnk()
input_buffer = xlnk.cma_array(shape=(5,), dtype=np.uint32)

#內存緩衝區屬性
input_buffer.physical_address

#向緩衝區中寫入數值
for i in range(5):
    input_buffer[i] = i

代碼解讀:
>>>xlnk = Xlnk(): 初始化新的Xlnk對象。
在這裏插入圖片描述
>>>input_buffer = xlnk.cma_array(shape=(5,), dtype=np.uint32): 得到一個內存地址連續的numpy數組。可以通過屬性physical_address來查看物理地址;當該數組不再使用時,可以通過array.freebuffer()array.close() 來對其進行關閉。
這裏申請的數組是一種形狀爲(5,),類型爲uint32的數組。
在這裏插入圖片描述
>>>input_buffer.physical_address: 這裏返回的是你申請的數組的地址。
>>>input_buffer[i] = i: 對地址進行賦值,注意這裏賦值的內容不能超過申請的數組維度。假設你申請了(5,),你就不能賦值0~6。

4. DMA

AXI stream 通常用在高性能的應用程序,AXI流程序可以通過DMA與Zynq AXI HP端口一起使用,Pynq的DMA可以通過AXI直接訪問IP,我們可以從DRAM讀取數據,並且將數據發送到AXI流,或者從流中接受數據寫到DRAM中去。
在這裏插入圖片描述
讀通道從PS DRAM讀取並寫入流。寫通道將從流中讀取,然後寫回到PS DRAM。
當事務完成時,DMA期望連接到DMA(寫通道)的任何流IP都將設置AXI TLAST信號。 如果未設置,則DMA將永遠不會完成事務。

舉例:

import pynq.lib.dma
from pynq import Xlnk
from pynq import Overlay

ol = Overlay("base.bit")
dict1 = ol.ip_dict['trace_analyzer_pmodb/axi_dma_0']
#初始化兩個類
xlnk = Xlnk()
dma = DMA(dict1)
#申請兩段緩衝器
input_buffer = xlnk.cma_array(shape=(5,), dtype=np.uint32)
output_buffer = xlnk.cma_array(shape=(5,), dtype=np.uint32)
#要發送的數據
for i in range(5):
    input_buffer[i] = i
#數據的迴環測試
dma.sendchannel.transfer(input_buffer)
dma.recvchannel.transfer(output_buffer)
dma.sendchannel.wait()
dma.recvchannel.wait()

代碼解讀:
>>>dict1 = ol.ip_dict[‘trace_analyzer_pmodb/axi_dma_0’]: 獲得一個IP字典中描述DMA引擎的條目用於DMA的初始化description參數。
在這裏插入圖片描述
>>>xlnk = Xlnk()和dma = DMA(dict1): 初始化Xlnk和DMA兩個類。
>>>input_buffer = xlnk.cma_array(shape=(5,), dtype=np.uint32): 用Xlnk類申請數組型的內存空間。
>>>dma.sendchannel.transfer(input_buffer): 將內存中的數據發送到AXI流上。
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章