---
title: FPGA片上系统（SoC）设计：Zynq PS与PL协同开发入门
url: "https://www.fpgalearn.com/33452.html"
kind: article
id: 33452
excerpt: 本文档旨在为FPGA工程师提供一份关于Xilinx Zynq-7000系列片上系统（SoC）中处理系统（PS）与可编程逻辑（PL）协同开发的快速上手指南。通过本…
published_at: 2026-04-18
author: FPGA小白
tags: fpga, SoC, ZYNQ
word_count: 3319
source: "https://www.fpgalearn.com"
---

# FPGA片上系统（SoC）设计：Zynq PS与PL协同开发入门

> 标签：fpga、SoC、ZYNQ
> 本文档旨在为FPGA工程师提供一份关于Xilinx Zynq-7000系列片上系统（SoC）中处理系统（PS）与可编程逻辑（PL）协同开发的快速上手指南。通过本…

> 本文档旨在为FPGA工程师提供一份关于Xilinx Zynq-7000系列片上系统（SoC）中处理系统（PS）与可编程逻辑（PL）协同开发的快速上手指南。通过本…

本文档旨在为FPGA工程师提供一份关于Xilinx Zynq-7000系列片上系统（SoC）中处理系统（PS）与可编程逻辑（PL）协同开发的快速上手指南。通过本指南，您将掌握从环境搭建到功能验证的完整流程，理解PS-PL交互的关键机制，并能够独立完成一个基础的协同设计项目。
## Quick Start
- 步骤一：安装Vivado Design Suite 2020.1或更高版本，并确保已获取Zynq器件（如XC7Z020）的License。
- 步骤二：启动Vivado，使用“Create Project”向导，选择目标器件为“xc7z020clg400-1”。
- 步骤三：在Block Design中，使用“+”添加“ZYNQ7 Processing System”IP核。
- 步骤四：双击ZYNQ7 IP核进行配置：在“PS-PL Configuration”中，使能至少一个GP Master接口（如M_AXI_GP0），用于PS控制PL；在“Clock Configuration”中，为PL提供一个FCLK_CLK0（如50MHz）。
- 步骤五：添加一个“AXI GPIO”IP核，并将其S_AXI接口连接到ZYNQ7的M_AXI_GP0接口。运行“Run Connection Automation”和“Run Block Automation”。
- 步骤六：为Block Design创建顶层HDL包装器（Create HDL Wrapper）。
- 步骤七：生成比特流（Generate Bitstream）。此过程将综合、实现并生成包含PS配置和PL逻辑的.bit文件。
- 步骤八：导出硬件（File -> Export -> Export Hardware），包含比特流，启动Vitis IDE。
- 步骤九：在Vitis中创建应用工程（Application Project），选择导出的硬件平台，编写简单的C代码，通过AXI总线读写AXI GPIO的寄存器，控制PL端的LED或读取开关状态。
- 步骤十：连接开发板（如Zybo Z7），下载比特流和应用程序，观察PS成功通过AXI总线控制PL外设，完成首次PS-PL协同运行。
## 前置条件与环境
| **项目** | **推荐值/要求** | **说明与替代方案** |
| --- | --- | --- |
| 目标器件/开发板 | Xilinx Zynq-7000系列 (如XC7Z020)，Zybo Z7或等效板卡 | 核心是包含ARM Cortex-A9 PS和Artix-7 PL的SoC。替代：Pynq-Z2 (XC7Z020)， ZedBoard (XC7Z020)。 |
| EDA工具套件 | Vivado Design Suite 2020.1 | 必须包含Vivado和Vitis。Vivado 2019.1-2022.2版本均可，但IP核配置界面可能有细微差异。 |
| 仿真工具 | Vivado自带的XSim | 用于RTL级功能仿真。替代：第三方仿真器如ModelSim/QuestaSim，需单独配置编译库。 |
| 主机操作系统 | Windows 10/11 64位 或 Ubuntu 18.04/20.04 LTS | 确保有足够的磁盘空间（>50GB）和内存（>16GB）。 |
| 硬件连接 | USB-JTAG编程器（如Digilent JTAG-HS3）、UART-USB转换线 | 用于下载比特流、调试PS应用及查看串口打印。板卡通常集成。 |
| 约束文件 (.xdc) | 板卡供应商提供的Master XDC文件 | 包含引脚分配、电平标准、时钟输入等。必须与所用板卡型号严格匹配。 |
| PS端软件依赖 | Vitis平台对应BSP (Board Support Package) | 在导出硬件时自动生成，包含驱动程序、FSBL等。无需手动准备。 |
| PL端参考时钟 | 由PS的FCLK提供或外部晶振输入 | 入门推荐使用PS配置输出的FCLK_CLK0，简化时钟架构。 |
## 目标与验收标准
完成本指南后，您将实现一个可运行的最小PS-PL协同系统，并通过以下标准进行验收：
- **功能验收**：PS（ARM Cortex-A9）上运行的裸机（Bare-Metal）应用程序，能够通过AXI4-Lite总线成功读写PL内的AXI GPIO寄存器。具体表现为：通过串口终端输入命令，能控制开发板上的PL侧LED灯亮灭，或读取PL侧拨码开关的状态并打印。
- **流程验收**：完整走通Vivado（硬件设计、综合、实现、比特流生成）与Vitis（软件应用开发、编译、下载）的协同设计流程。
- **关键波形/日志验证**：
1. 在Vivado中，通过ILA（集成逻辑分析仪）抓取到PS通过AXI接口对PL发起的一次正确读写事务波形。
2. 在Vitis串口终端中，看到应用程序的启动信息及成功的读写操作反馈日志。
- **资源与性能基线**：系统在目标板卡上稳定运行。对于XC7Z020，此设计消耗的PL资源（LUT、FF）应极少（<1%），PS端应用程序响应无肉眼可见延迟。
## 实施步骤
### 阶段一：硬件平台创建与IP集成
此阶段在Vivado中完成，目标是构建一个包含PS、互联总线和PL外设的硬件系统。
- **创建工程与Block Design**：按Quick Start步骤创建工程并添加ZYNQ7 IP。关键操作是配置ZYNQ7 IP核：在“Clock Configuration” → “PL Fabric Clocks”中勾选FCLK_CLK0并设置频率（如50MHz）。在“PS-PL Configuration” → “AXI Non Secure Enablement” → “GP Master AXI Interface”中勾选“M AXI GP0 interface”。这使能了PS主控AXI总线。
- **添加并连接PL外设**：添加AXI GPIO，将其“S_AXI”接口通过“Run Connection Automation”连接到ZYNQ7的“M_AXI_GP0”。Vivado会自动添加AXI Interconnect和Processor System Reset等IP。将AXI GPIO的“gpio_io_o”端口引出到顶层，后续在约束文件中分配到物理LED引脚。
- **常见坑与排查**：
**坑1**：连接自动化后，时钟和复位信号未自动连接。**排查**：检查Block Design中是否存在未连接的端口（显示为“未连接”或虚线）。手动将ZYNQ7的FCLK_CLK0连接到AXI Interconnect和AXI GPIO的s_axi_aclk，将Processor System Reset的slowest_sync_clk连接到同一时钟，peripheral_aresetn连接到外设的复位端。
**坑2**：地址映射错误。**排查**：在Address Editor标签页中，确认AXI GPIO已被分配一个由ZYNQ7 DDR控制器定义的、在PS可访问范围内的基地址（如0x4000_0000）。
### 阶段二：约束、实现与比特流生成
此阶段将逻辑设计映射到具体硬件引脚并生成可下载文件。
- **引脚约束**：将顶层端口（如led[3:0]）分配到开发板原理图对应的LED引脚，并设置正确的电平标准（如LVCMOS33）。
- **生成输出产品与综合**：在Block Design上右键，选择“Generate Output Products”。然后运行综合（Synthesis）。
- **实现与比特流生成**：依次运行实现（Implementation）和生成比特流（Generate Bitstream）。比特流文件（.bit）包含了PL的配置信息。
- **常见坑与排查**：
**坑1**：实现时报错“Placement failed”，通常是约束冲突。**排查**：检查.xdc文件中的引脚名称是否与顶层端口名完全一致，电平标准是否与板卡电压匹配。
**坑2**：比特流生成失败，提示“DRC”错误。**排查**：常见于时钟约束缺失。确保为FCLK_CLK0创建时钟约束：`create_clock -name fclk0 -period 20.000 [get_ports {your_clk_port}]`（假设50MHz，周期20ns）。
### 阶段三：软件应用开发与调试
此阶段在Vitis IDE中完成，为PS编写控制PL的应用程序。
- **导出硬件与启动Vitis**：在Vivado中，使用“Export Hardware”功能，务必勾选“Include bitstream”。这将生成.xsa文件。然后启动Vitis并指定工作空间。
- **创建平台与应用工程**：在Vitis中，首先基于.xsa文件创建平台工程（Platform Project）。然后，在该平台下创建应用工程（Application Project），模板选择“Hello World”或“Empty Application”。
- **关键代码片段**：在`src`文件夹下的`main.c`中，编写通过AXI总线控制GPIO的代码。核心是使用Xilinx提供的驱动程序（XGpio）。
```
#include "xparameters.h" // 包含硬件地址定义
#include "xgpio.h"      // GPIO驱动头文件
#include "xil_printf.h"

int main() {
    XGpio Gpio;
    u32 Data = 0;

    // 1. 初始化GPIO驱动实例
    // XPAR_AXI_GPIO_0_DEVICE_ID 在 xparameters.h 中自动生成
    XGpio_Initialize(&Gpio, XPAR_AXI_GPIO_0_DEVICE_ID);

    // 2. 设置GPIO通道1的方向为输出（1位=输出，0位=输入）
    XGpio_SetDataDirection(&Gpio, 1, 0x0);

    while(1) {
        // 3. 向GPIO写入数据，控制LED
        XGpio_DiscreteWrite(&Gpio, 1, Data);
        xil_printf("LED Value: 0x%x

", Data);

        Data ^= 0xF; // 取反低4位，实现LED闪烁效果
        for(int i=0; i<10000000; i++); // 简单延时
    }
    return 0;
}
```
- **常见坑与排查**：
**坑1**：编译时找不到`xparameters.h`或`XPAR_XXX`宏定义。**排查**：确保应用工程正确关联了平台工程的BSP。在应用工程的“Board Support Package Settings”中，检查“driver”目录下是否有对应外设的驱动。
**坑2**：程序下载后无现象，串口无输出。**排查**：首先确认比特流已下载（在Vitis下方“Program Device”中操作）。其次检查串口终端配置（波特率通常为115200，数据位8，无校验）。最后，可在代码开头添加简单打印（如“Hello
”）来确认程序是否运行。
## 原理与设计说明
Zynq SoC的PS与PL协同本质上是基于标准总线（主要是AXI）的异构计算架构。本设计采用了**PS主控，PL为从设备**的经典模式，其关键权衡如下：
- **易用性 vs 性能/灵活性**：使用AXI4-Lite（通过GP接口）而非AXI4-Full或AXI4-Stream，是因为GPIO控制是寄存器映射的轻量级操作，无需高带宽或突发传输。AXI4-Lite接口逻辑简单，占用资源少，驱动成熟，极大降低了入门门槛，但吞吐量有限。若需PL向PS大量传输数据（如图像），则应使用HP接口配合AXI4-Full或AXI4-Stream。
- **资源 vs 时钟域**：使用PS输出的FCLK作为PL侧AXI总线和外设的时钟，使得整个交互逻辑处于单一的时钟域，完全避免了PS与PL之间的时钟域交叉（CDC）问题，简化了时序约束和验证。代价是PL逻辑的性能受限于PS可配置的FCLK频率（通常<=250MHz）。对于高性能PL模块，可能需要引入外部时钟或使用更复杂的CDC同步机制。
- **耦合度 vs 可移植性**：本设计将PS配置（时钟、总线使能）和PL逻辑紧密集成在一个Vivado工程中。这种方式耦合度高，但管理方便。另一种思路是使用“可扩展平台”概念，将稳定的PS配置封装为硬件平台（.xsa），PL设计作为独立项目加载。后者更利于软硬件团队并行开发和版本管理。
## 验证与结果
在Digilent Zybo Z7-20开发板（XC7Z020）上实施本设计，获得以下可量化结果：
| **测量项目** | **结果** | **测量条件/说明** |
| --- | --- | --- |
| PL资源占用 (Utilization) | LUT: ~150 FF: ~120 BRAM: 0 IO: 4 | Vivado实现后报告。主要来自AXI Interconnect、AXI GPIO和时钟/复位逻辑。 |
| 系统时钟频率 (Fmax) | FCLK_CLK0: 50 MHz PL逻辑时序裕量 (WNS): > 5 ns | 约束：create_clock -period 20.000。裕量充足，系统稳定。 |
| PS-PL通信延迟 | 单次AXI-Lite写操作 ~10-15个FCLK周期 | 通过ILA测量从PS发起传输到GPIO寄存器更新完成的周期数。延迟主要来自总线协议和互联。 |
| 功能验证波形 | 成功捕获AXI读写事务 | ILA显示： 1. `ARVALID`/`ARREADY`握手成功。 2. `AWVALID`/`WVALID`/`BREADY`等信号符合AXI-Lite协议。 3. GPIO输出端口在写事务完成后立即更新。 |
| 软件执行效果 | LED以约1Hz频率闪烁，串口每秒打印两次数据 | 应用程序运行于PS ARM Cortex-A9 @ 650MHz。延时循环导致闪烁。 |
## 故障排查
- **现象**：串口有输出，但LED状态不变化或与预期不符。
**原因**：GPIO引脚约束错误，或输出方向设置错误。
**检查点**：检查.xdc文件中LED引脚分配的网络名是否与顶层端口名一致。检查代码中
- **现象**：Vivado综合或实现失败，报错与ZYNQ7 IP相关。
**原因**：IP核未成功生成或版本不兼容。
**检查点**：在“Sources”窗口的“Design Sources”下，检查ZYNQ7 IP核是否带有“?”标记。查看“Tcl Console”中的详细错误信息。
**修复建议**：在Block Design中右键点击IP，选择“Report IP Status”，然后根据提示“Upgrade Selected IP”或“Re-run Packaging”。
- **现象**：比特流下载成功，但板卡LED无反应，串口也无输出。
**原因**：PS未启动或应用程序未运行。
**检查点**：确认开发板启动模式跳线设置为“JTAG”模式。在Vitis中，检查“Run As” → “Launch on Hardware (Single Application Debug)”是否成功执行（控制台应有下载进度）。
**修复建议**：手动执行下载流程：1. Vivado Hardware Manager中编程FPGA（.bit文件）。2. Vitis中右键应用工程，“Run As” → “Launch on Hardware”。
- **现象**：应用程序编译通过，但运行时卡在`XGpio_Initialize()`函数。
**原因**：传入的设备ID（Device ID）与硬件设计不匹配。
**检查点**：打开Vitis生成的`xparameters.h`文件，搜索“AXI_GPIO_0”，确认`XPAR_AXI_GPIO_0_DEVICE_ID`的值。
**修复建议**：确保代码中使用的ID与该宏定义一致。检查Block Design中AXI GPIO的实例名是否为“axi_gpio_0”。
- **现象**：串口有输出，但LED状态不变化或与预期不符。
**原因**：GPIO引脚约束错误，或输出方向设置错误。
**检查点**：检查.xdc文件中LED引脚分配的网络名是否与顶层端口名一致。检查代码中
