Zynq PS-PL协同设计入门:从硬件到软件的打通
Xilinx Zynq-7000(及Zynq UltraScale+ MPSoC)最大的魅力在于PS(Processing System,双核ARM Cortex‑A9)与PL(Programmable Logic,FPGA)的紧密耦合。新手常卡在“Vivado 里加完IP,Linux/裸机程序怎么访问?”——本文按真实工程顺序,演示从 PL 逻辑封装 → PS 硬件配置 → 应用软件读写寄存器的完整打通流程。
一、硬件侧:在 Vivado 中为 PL 添加自定义 AXI‑Lite 从设备
最常见协同方式是 PS 通过 GP AXI 总线访问 PL 寄存器(AXI4‑Lite Slave)。Vivado 提供 Create and Package IP 向导自动生成模板。
1. 新建 Custom IP(AXI4‑Lite Slave)
• Tools → Create and Package IP → Create a new AXI4 peripheral
- Number of Registers:例设 4 个(32‑bit)
• Finish 后 Vivado 生成 my_pl_regs_v1_0.v + 顶层 S_AXI_*,重点看自动生成的寄存器文件:
// 在 my_pl_regs_v1_0_S_AXI.v 中找到寄存器写分支
always @(posedge S_AXI_ACLK) begin
if (!S_AXI_ARESETN) begin
slv_reg0 <= 0; slv_reg1 <= 0; slv_reg2 <= 0; slv_reg3 <= 0;
end else if (slv_reg_wren) begin
case (axi_awaddr[ADDR_LSB+OPT_MEM_ADDR_BITS:ADDR_LSB])
2'h0: slv_reg0 <= S_AXI_WDATA[31:0];
2'h1: slv_reg1 <= S_AXI_WDATA[31:0];
// ...
endcase
end
end
// 读分支同理,返回 slv_regX
slv_reg0~3 就是你 PL 侧可用的控制/状态寄存器,可引出到顶层 LED、PWM、DMA 触发等逻辑。
2. Block Design 连接
• 添加 ZYNQ7 Processing System,Run Block Automation(自动连 DDR/ clocks)
- 添加刚生成的 my_pl_regs IP
• 点击 Run Connection Automation,Vivado 会:
• 把 IP 的 s_axi 连到 M_AXI_GP0(PS → PL AXI 总线)
- 分配 Base Address(默认 0x43C0_0000,可在 Address Editor 修改)
• Generate Bitstream → Export Hardware(Include bitstream)→ Launch SDK/Vitis
二、软件侧:在 Vitis/SDK 中读写 PL 寄存器
PS 端把 PL AXI‑Lite 区间当普通内存映射访问即可。
1. 定义基地址(与 Vivado Address Editor 一致)
#define PL_REG_BASE 0x43C00000
#define PL_REG_CTRL 0x00 // slv_reg0 offset
#define PL_REG_STAT 0x04 // slv_reg1 offset
2. 寄存器读写(裸机 / Bare-metal)
#include "xil_io.h"
#include "xparameters.h"
#define PL_BASE (XPAR_MY_PL_REGS_0_S_AXI_BASEADDR)
void pl_write(u32 offset, u32 val) {
Xil_Out32(PL_BASE + offset, val);
}
u32 pl_read(u32 offset) {
return Xil_In32(PL_BASE + offset);
}
int main(void) {
// 点亮LED(假设PL把slv_reg0[0]连LED)
pl_write(PL_REG_CTRL, 0x01);
// 读状态
u32 st = pl_read(PL_REG_STAT);
if (st & 0x01)
xil_printf("PL done flag set\n");
while(1);
}
若用 Linux + UIO,可将 0x43C00000 加入 device‑tree reg = <0x43c00000 0x1000>;,用户空间 mmap() 后同样 *(volatile uint32_t*)(map_base+offset) 访问。
三、常见协同接口形式对比
协同方式 典型用途 特点
AXI4‑Lite Slave(PS→PL寄存器) 控制/状态寄存器、参数配置 最简单,延迟低,适合非流数据
AXI4‑Stream(PS⇄PL DMA) 图像/雷达大数据流 需 AXI DMA 或 Zynq HP 口
EMIO(PS GPIO → PL) 少量同步信号(start/reset) 省 AXI 资源,仅几位
Interrupt(PL→PS) PL 完成通知 配 GIC,在 Vitis 中 XScuGic_Connect()
实际项目通常 混用:AXI‑Lite 配参 + EMIO 做同步 + Stream+DMA 传数据 + IRQ 通知。
四、调试与避坑清单
1. 地址对齐:AXI‑Lite 寄存器偏移必须是 4 字节对齐,slv_regX 偏移 = X*4。
2. 未 Generate Bitstream / 未 Export HW:Vitis 打开旧 HDF 会连不上 PL 逻辑——确认 File → Export → Export Hardware 勾选 Include bitstream。
3. PS 访问挂死(Data Abort):通常是因为 PL AXI Slave 未返回 BRESP/ RRESP,检查:
• PL IP s_axi_awready / s_axi_arready 是否拉高
- 是否在 RTL 中忘了处理未定义地址读(默认返回 0 且 rvalid=1)
4. Cache 一致性(Linux):若 PL 通过 HP AXI 口写内存被 PS 读,需 cache flush 或 用 non‑cached mapping(UIO 默认 non‑cached)。
五、结语
Zynq PS‑PL 协同设计的核心就三步:① Vivado 中用 AXI‑Lite Slave IP 封装 PL 寄存器并分配 Base Address → ② Export Hardware(含 bitstream)→ ③ Vitis/SDK 用 Xil_Out32/Xil_In32 按该地址直接读写。掌握这个最小闭环后,再逐步加入 DMA Stream、中断与 EMIO,就能构建出真正 “ARM 主控 + FPGA 加速” 的完整系统。





