
使用 Python/MyHDL 创建自定义 FPGA IP,与 Vivado 集成,并通过 PYNQ 进行控制——实现软件上的简单硬件设计。

硬件开源编程利器MyHDL简介
传统上,FPGA 开发意味着编写 Verilog 或 VHDL 代码——这些语言功能强大但冗长,与现代软件工作流程格格不入。如果能用 Python 来描述硬件呢?Python 也是你用于软件开发、测试和数据分析的语言。
本项目演示了如何使用MyHDL (一种基于 Python 的硬件描述语言)创建自定义 FPGA IP 核,并将其集成到 Xilinx Vivado 中。通过 Python 的强大表达能力和 MyHDL 的硬件转换功能,我们可以使用熟悉的工具和语法来设计、仿真和部署 FPGA 逻辑。
最终成果:一个支持周期性(基于定时器)和软件触发中断的中断生成器 IP,通过 AXI4-Lite 与 Zynq UltraScale+ PS 完全集成,可以通过 PYNQ 的 Python 接口进行控制。
MyHDL弥合了软件开发和硬件开发之间的差距:
中断生成器 IP 提供:
硬件:

Xilinx KR260 机器人入门套件 网络连接(用于 PYNQ 访问)
软件:
参考:
https://www.hackster.io/wstanislaus/custom-yocto-linux-network-boot-for-xilinx-kr260-e22ac3
构建依赖项:
sudo apt-get update
sudo apt-get install -y python3.12 python3.12-venv make
项目结构:

构建过程将基于 Python 的 MyHDL 代码转换为 Verilog,以便与 Vivado 集成。
cd myhdl
make all
这条命令:
手动构建过程:
# Create virtual environment
python3.12 -m venv venv
source venv/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 集成。
核心组件:
寄存器:



将以下 IP 核添加到模块设计中:


连接以下部件:
最终的模块设计应该如下所示:

硬件平台导出后,现在可以使用 PYNQ 的 Python 接口与自定义 IP 进行交互。
将以下内容复制到 KR260 开发板:
在 Ubuntu 构建/开发机器上:
firefox http://172.20.1.2:9090/
找到pynq_interrupt.ipynb并打开它。
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
# 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
# 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)
MyHDL 的优势:
整合优势:
http://www.myhdl.org/
https://pynq.readthedocs.io/
https://www.xilinx.com/support/documentation/sw_manuals/xilinx2025_2/ug910-vivado-getting-started.pdf
https://www.xilinx.com/products/boards-and-kits/kria.html
https://www.hackster.io/wstanislaus/custom-yocto-linux-network-boot-for-xilinx-kr260-e22ac3
https://github.com/wstanislaus/Xilinx_KR260_Projects/tree/main/myhdl
该项目表明,FPGA 开发并不意味着要放弃现代软件工具。通过使用 MyHDL,我们可以:
最终形成的开发工作流程既能让软件工程师感到自然流畅,又能保持 FPGA 设计的强大功能和灵活性。无论是在构建新的 IP 核原型、尝试软硬件协同设计,还是构建生产系统,MyHDL 都能在软件和硬件世界之间架起一座桥梁。
END