以下文章來源于OpenFPGA,作者碎碎思
使用 Python/MyHDL 創(chuàng)建自定義 FPGA IP,與 Vivado 集成,并通過 PYNQ 進(jìn)行控制——實(shí)現(xiàn)軟件上的簡(jiǎn)單硬件設(shè)計(jì)。
介紹
硬件開源編程利器MyHDL簡(jiǎn)介
傳統(tǒng)上,F(xiàn)PGA 開發(fā)意味著編寫 Verilog 或 VHDL 代碼——這些語(yǔ)言功能強(qiáng)大但冗長(zhǎng),與現(xiàn)代軟件工作流程格格不入。如果能用 Python 來描述硬件呢?Python 也是你用于軟件開發(fā)、測(cè)試和數(shù)據(jù)分析的語(yǔ)言。
本項(xiàng)目演示了如何使用MyHDL (一種基于 Python 的硬件描述語(yǔ)言)創(chuàng)建自定義 FPGA IP 核,并將其集成到 Xilinx Vivado 中。通過 Python 的強(qiáng)大表達(dá)能力和 MyHDL 的硬件轉(zhuǎn)換功能,我們可以使用熟悉的工具和語(yǔ)法來設(shè)計(jì)、仿真和部署 FPGA 邏輯。
最終成果:一個(gè)支持周期性(基于定時(shí)器)和軟件觸發(fā)中斷的中斷生成器 IP,通過 AXI4-Lite 與 Zynq UltraScale+ PS 完全集成,可以通過 PYNQ 的 Python 接口進(jìn)行控制。
為什么選擇 MyHDL?
MyHDL彌合了軟件開發(fā)和硬件開發(fā)之間的差距:
Python 語(yǔ)法:用熟悉的 Python 代碼編寫硬件描述
仿真支持:在綜合之前,使用 Python 測(cè)試硬件邏輯。
代碼生成:自動(dòng)將 Verilog 代碼轉(zhuǎn)換為 Vivado 集成所需的格式
模塊化設(shè)計(jì):可重用的接口定義和組件
類型安全:硬件感知類型檢查可防止常見錯(cuò)誤
項(xiàng)目概述
中斷生成器 IP 提供:
兩個(gè)獨(dú)立的中斷輸出:獨(dú)立的中斷 1 和中斷 2 通道
周期性中斷模式:可配置的基于定時(shí)器的中斷,帶有 32 位周期計(jì)數(shù)器
軟件觸發(fā)模式:通過寄存器寫入按需生成中斷
基于寄存器的控制:用于配置和狀態(tài)監(jiān)控的 AXI4-Lite 接口
中斷管理:用于靈活中斷控制的狀態(tài)寄存器和使能寄存器
先決條件
硬件:

Xilinx KR260 機(jī)器人入門套件 網(wǎng)絡(luò)連接(用于 PYNQ 訪問)
軟件:
Ubuntu 24.04 LTS(構(gòu)建主機(jī))
Python 3.12
Vivado 2025.2(或兼容版本)
定制的 Yocto Linux 鏡像,包含 PYNQ
參考:
https://www.hackster.io/wstanislaus/custom-yocto-linux-network-boot-for-xilinx-kr260-e22ac3
Jupyter Notebook 服務(wù)器(包含在 PYNQ 鏡像中)
構(gòu)建依賴項(xiàng):
sudo apt-get update sudo apt-get install -y python3.12 python3.12-venv make
項(xiàng)目結(jié)構(gòu):

構(gòu)建 MyHDL IP
構(gòu)建過程將基于 Python 的 MyHDL 代碼轉(zhuǎn)換為 Verilog,以便與 Vivado 集成。
步驟 1:構(gòu)建 IP
cdmyhdl make all
這條命令:
創(chuàng)建一個(gè) Python 3.12 虛擬環(huán)境
安裝 MyHDL 軟件包
將 MyHDL 代碼轉(zhuǎn)換為 Verilog
輸出:build/interrupt_generator_ip.v
手動(dòng)構(gòu)建過程:
# Create virtual environment python3.12 -m venv venv sourcevenv/bin/activate # Install MyHDL pip install --upgrade pip pip install myhdl # Convert to Verilog PYTHONPATH=. python PL/MyHDL/src/interrupt_generator_ip/interrupt_generator_ip.py
生成的 Verilog 文件(interrupt_generator_ip.v)包含完整的 IP 核,帶有 AXI4-Lite 接口,可直接用于 Vivado 集成。
MyHDL IP架構(gòu)
核心組件:
中斷生成器核心(interrupt_gen.py)實(shí)現(xiàn)周期性和軟件觸發(fā)的中斷邏輯,管理周期計(jì)數(shù)器和中斷狀態(tài),提供兩個(gè)獨(dú)立的中斷輸出。
IP Wrapper ( interrupt_generator_ip.py)將 AXI4-Lite 接口轉(zhuǎn)換為內(nèi)部 AxiLocal 格式,實(shí)例化中斷生成器內(nèi)核,并為 Vivado 生成 Verilog 輸出。
AXI 接口(axi_lite.py,axi_local.py)標(biāo)準(zhǔn) AXI4-Lite 從接口,用于內(nèi)部路由的簡(jiǎn)化本地 AXI 總線
寄存器:

步驟 1:創(chuàng)建新項(xiàng)目
打開 Vivado 并選擇“創(chuàng)建項(xiàng)目”
選擇RTL 項(xiàng)目,然后單擊“下一步”。
設(shè)置項(xiàng)目名稱:interrupt_demo
選擇項(xiàng)目路徑
選擇“Do not specify sources at this time”。
點(diǎn)擊“Boards”,然后選擇“Kria KR260 Robotics Starter Kit SOM”。
步驟 2:添加 MyHDL 生成的 Verilog
在 Vivado 中,右鍵單擊Design Sources → Add Sources。
選擇“Add or create design sources”
點(diǎn)擊“Add Files”并導(dǎo)航至build/interrupt_generator_ip.v
點(diǎn)擊“完成”

步驟 3:創(chuàng)建模塊設(shè)計(jì)
在“ Sources ”窗口中右鍵單擊→創(chuàng)建塊設(shè)計(jì)
給它起個(gè)名字interrupt_demo
單擊“確定”

步驟 4:添加IP核
將以下 IP 核添加到模塊設(shè)計(jì)中:
Zynq UltraScale+ PS ( zynq_ultra_ps_e)雙擊配置啟用PL-PS 時(shí)鐘(100MHz)啟用M_AXI_HPM0_LPD接口啟用IRQ_F2P中斷輸入
中斷生成器 IP (自定義 IP)在模塊設(shè)計(jì)中右鍵單擊 →添加模塊從列表中選擇這是 MyHDL 生成的 IPinterrupt_generator_ip_0

AXI Smart Memory Controller (axi_smc)通過 AXI4-Lite 將 PS 連接到自定義 IP
AXI 中斷控制器(axi_intc)合并 PL 中斷基地址:0xB0010000

Interrupt Concatenator(xlconcat)組合中斷生成器輸出,連接到 AXI 中斷控制器
Processor System Reset (proc_sys_reset)PL邏輯復(fù)位控制器
步驟 5:連接IP核
連接以下部件:
PS → AXI SMC → Interrupt Generator:AXI4-Lite 接口
Interrupt Generator → Interrupt Concatenator:兩個(gè)中斷輸出
Interrupt Concatenator → AXI Interrupt Controller:組合中斷總線
AXI Interrupt Controller → PS :IRQ_F2P 中斷輸入
PS → 所有 IP :時(shí)鐘和復(fù)位信號(hào)
步驟 6:創(chuàng)建 HDL 包裝器
右鍵單擊塊設(shè)計(jì) →創(chuàng)建 HDL 包裝器
選擇“讓 Vivado 管理包裝器并自動(dòng)更新”
單擊“確定”
步驟 7:完成積木設(shè)計(jì)
最終的模塊設(shè)計(jì)應(yīng)該如下所示:

步驟 8:生成比特流
步驟 9:導(dǎo)出硬件
File → Export → Export Hardware
Include bitstream
Export to interrupt_demo.xsa
PYNQ 集成
硬件平臺(tái)導(dǎo)出后,現(xiàn)在可以使用 PYNQ 的 Python 接口與自定義 IP 進(jìn)行交互。
步驟 1:將文件復(fù)制到 KR260
將以下內(nèi)容復(fù)制到 KR260 開發(fā)板:
interrupt_demo.bit→/nfsroot/lib/firmware/
interrupt_demo.hwh→/nfsroot/lib/firmware/
APU/pynq_interrupt.ipynb→/nfsroot/home/xilinx/Notebook/
步驟 2:打開 Jupyter 服務(wù)器
在 Ubuntu 構(gòu)建/開發(fā)機(jī)器上:
firefox http://172.20.1.2:9090/
找到pynq_interrupt.ipynb并打開它。
步驟 3:加載Overlay
from pynq import Overlay, Interrupt
import asyncio
# Load the FPGA overlay
overlay = Overlay('interrupt_demo.bit')
overlay.download()
# Get the interrupt generator IP
intr = overlay.interrupt_generator_ip_0
# Configure PL clock (100MHz)
overlay.clock_dict['fclk_clk0'] = 100000000
步驟 4:配置中斷
# Register offsets period1 = 0x00 period2 = 0x04 isr = 0x08 ier = 0x0C trigger = 0x10 # Configure interrupt1 for software triggering intr.write(period1, 0) # Disable periodic mode intr.write(ier, 1) # Enable interrupt1 # Configure interrupt2 for periodic interrupts (1 second at 100MHz) intr.write(period2, 100000000) intr.write(ier, 2) # Enable interrupt2
步驟 5:處理中斷
# Create interrupt instances
intr_inst1 = Interrupt('axi_intc', intr_id=0) # interrupt1
intr_inst2 = Interrupt('axi_intc', intr_id=1) # interrupt2
# Async interrupt handler
async def interrupt_handler(interrupt_object, interrupt_bit):
print("Handler task started. Waiting for interrupt...")
# Wait for interrupt
await interrupt_object.wait()
print("Interrupt received!")
# Clear the interrupt (write 1 to the bit to clear it)
intr.write(isr, interrupt_bit)
# Trigger software interrupt
intr.write(trigger, 1) # Trigger interrupt1
# Wait for interrupt
await interrupt_handler(intr_inst1, 1)
# Periodic interrupt will fire automatically
await interrupt_handler(intr_inst2, 2)
中斷操作模式
周期性中斷:
將周期寄存器設(shè)置為所需的時(shí)鐘周期計(jì)數(shù)
在 IER 寄存器中啟用中斷
當(dāng)計(jì)數(shù)器到期時(shí),中斷會(huì)自動(dòng)觸發(fā)。
中斷發(fā)生時(shí),ISR 位被置位。
軟件清除 ISR 位以確認(rèn)
軟件觸發(fā)中斷:
將周期寄存器設(shè)置為 0(禁用周期模式)
在 IER 寄存器中啟用中斷
向 TRIGGER 寄存器位寫入 1
Interrupt fires immediately
ISR 位已設(shè)置
軟件清除 ISR 位以確認(rèn)
設(shè)計(jì)優(yōu)勢(shì)
MyHDL 的優(yōu)勢(shì):
快速原型開發(fā):用 Python 編寫硬件,用 Python 進(jìn)行測(cè)試,然后轉(zhuǎn)換為 Verilog 格式
代碼復(fù)用:采用可復(fù)用接口定義的模塊化設(shè)計(jì)
仿真:綜合之前測(cè)試硬件邏輯。
可維護(hù)性:Python 的可讀性使得硬件代碼更容易理解。
整合優(yōu)勢(shì):
標(biāo)準(zhǔn)接口:AXI4-Lite 提供與 PS 的標(biāo)準(zhǔn)連接。
PYNQ 兼容性:通過 Python 無縫控制自定義 IP
靈活配置:基于寄存器的控制支持運(yùn)行時(shí)重新配置
中斷支持:正確的 PL 到 PS 中斷處理
資源
MyHDL 文檔:
http://www.myhdl.org/
PYNQ 文檔:
https://pynq.readthedocs.io/
Xilinx Vivado 文檔:
https://www.xilinx.com/support/documentation/sw_manuals/xilinx2025_2/ug910-vivado-getting-started.pdf
KR260 開發(fā)板文檔:
https://www.xilinx.com/products/boards-and-kits/kria.html
定制 Yocto Linux 項(xiàng)目:
https://www.hackster.io/wstanislaus/custom-yocto-linux-network-boot-for-xilinx-kr260-e22ac3
本項(xiàng)目源文件
https://github.com/wstanislaus/Xilinx_KR260_Projects/tree/main/myhdl
結(jié)論
該項(xiàng)目表明,F(xiàn)PGA 開發(fā)并不意味著要放棄現(xiàn)代軟件工具。通過使用 MyHDL,我們可以:
用 Python 編寫硬件代碼
利用 Python 的生態(tài)系統(tǒng)進(jìn)行測(cè)試和仿真
生成用于 Vivado 集成的標(biāo)準(zhǔn) Verilog
通過 PYNQ 的 Python 接口控制硬件
最終形成的開發(fā)工作流程既能讓軟件工程師感到自然流暢,又能保持 FPGA 設(shè)計(jì)的強(qiáng)大功能和靈活性。無論是在構(gòu)建新的 IP 核原型、嘗試軟硬件協(xié)同設(shè)計(jì),還是構(gòu)建生產(chǎn)系統(tǒng),MyHDL 都能在軟件和硬件世界之間架起一座橋梁。
-
寄存器
+關(guān)注
關(guān)注
31文章
5613瀏覽量
130312 -
定時(shí)器
+關(guān)注
關(guān)注
23文章
3370瀏覽量
124285 -
python
+關(guān)注
關(guān)注
58文章
4881瀏覽量
90250 -
Vivado
+關(guān)注
關(guān)注
19文章
860瀏覽量
71324
原文標(biāo)題:用 Python 寫 FPGA IP!—— MyHDL 自定義中斷生成器實(shí)踐
文章出處:【微信號(hào):HXSLH1010101010,微信公眾號(hào):FPGA技術(shù)江湖】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
PYNQ設(shè)計(jì)案例:基于HDL語(yǔ)言+Vivado的自定義IP核創(chuàng)建
自定義Python PyPI存儲(chǔ)庫(kù)
在NI Multisim中創(chuàng)建自定義元器件
利用SDSoC創(chuàng)建自定義硬件
自定義sobel濾波IP核,IP接口遵守AXI Stream協(xié)議
Python學(xué)習(xí)要點(diǎn):自定義序列實(shí)現(xiàn)切片功能
使用VIvado封裝自定IP并使用IP創(chuàng)建工程
如何在TPT中使用Python實(shí)現(xiàn)自定義報(bào)告
Vivado設(shè)計(jì)套件用戶指南:創(chuàng)建和打包自定義IP
Vivado Design Suite用戶指南:創(chuàng)建和打包自定義IP
創(chuàng)建自定義的基于閃存的引導(dǎo)加載程序(BSL)
使用Python/MyHDL創(chuàng)建自定義FPGA IP
評(píng)論