1. Zynq平台概述:从架构到环境搭建
做嵌入式这么多年,Zynq是我见过最「有意思」的芯片之一。它把ARM处理器和FPGA逻辑放在同一个die上,说白了就是让软件工程师和硬件工程师能真正坐在一起干活。我第一次接触Zynq是在一个工业视觉项目上,客户既要跑Linux做网络协议栈,又要做实时图像预处理——传统方案得用ARM+FPGA两块板子,Zynq一片搞定。
1.1 Zynq-7000系列架构:PS与PL的「双核」世界
Zynq-7000系列的核心架构,可以拆成两大部分:PS(Processing System)和PL(Programmable Logic)。PS是硬核的ARM Cortex-A9双核处理器,PL就是那片可编程的FPGA逻辑。两者通过内部高速总线互联,延迟比板级连接低一个数量级。
关键认知:Zynq不是「FPGA带了个ARM」,而是「ARM SoC集成了FPGA」。PS是老大,系统上电后PS先启动,PL可以看作是PS的一个外设。
我习惯把PS比作「大脑」,PL比作「可定制的肌肉」。大脑负责决策(操作系统、网络、文件系统),肌肉负责高速重复劳动(图像滤波、FFT、数据包处理)。
PS内部结构速览
| 组件 | 说明 | 我的经验 |
|---|---|---|
| ARM Cortex-A9双核 | 主频最高1GHz,带NEON SIMD引擎 | 跑Linux完全够用,别指望它做实时控制 |
| L1/L2 Cache | 32KB I/D + 512KB共享L2 | 注意Cache一致性,PL访问DDR时要小心 |
| DDR控制器 | 支持DDR3/DDR3L,最大1GB | 我踩过坑:PL和PS同时访问DDR,带宽分配要提前规划 |
| 静态存储器接口 | NAND、NOR、QSPI | 启动方式从这里选,QSPI最常用 |
| I/O外设 | USB、UART、I2C、SPI、CAN、GigE | 这些是硬核,不占PL资源 |
PL部分核心资源
- 逻辑单元(LC):从Artix-7到Kintex-7级别,28K~444K
- DSP48E1 Slice:每个可做25×18乘法累加,适合数字信号处理
- Block RAM:36Kb每块,可配置为双端口RAM/FIFO
- 高速收发器(GTP/GTX):最高12.5Gbps,做SerDes接口
选型建议:如果算法以乘加为主(如CNN卷积),多关注DSP数量;如果以数据缓存为主(如视频帧缓冲),多关注BRAM容量。我做过一个雷达信号处理项目,DSP用光了,BRAM还剩一半——选型时失算了。
1.2 PS与PL协同工作原理:内部总线与接口
PS和PL怎么通信?靠的是内部总线。Zynq提供了多种接口,每种接口的带宽、延迟、用途都不一样。选错了接口,性能可能差一个数量级。
主要通信接口一览
| 接口名称 | 带宽 | 延迟 | 典型用途 |
|---|---|---|---|
| AXI_HP(高性能端口) | 4个口,每个32位/64位,最高600MB/s | 低 | PL直接访问DDR,大数据搬移 |
| AXI_GP(通用端口) | 2个主+2个从,32位,约150MB/s | 中 | 控制寄存器、小数据量通信 |
| AXI_ACP(加速一致性端口) | 1个,64位,约600MB/s | 低 | PL访问CPU Cache,保持一致性 |
| EMIO(扩展MIO) | GPIO级别 | 高 | PL控制PS的I/O引脚 |
为什么会这样设计?你想想看,如果PL只是偶尔读几个寄存器,用AXI_GP就够了。但如果PL要做视频帧的实时处理,每秒几十MB的数据量,那就必须走AXI_HP直通DDR。我见过有人用AXI_GP传视频数据,结果帧率上不去,查了半天才发现是接口带宽瓶颈。
避坑指南:AXI_ACP虽然能保持Cache一致性,但使用起来有坑。我曾经在ACP端口上做DMA传输,没处理好Cache Line对齐,导致数据错位。建议:除非你非常熟悉ARM的Cache模型,否则优先用AXI_HP + 手动Cache刷新。
启动流程:PS先跑,PL后配
Zynq的启动顺序是固定的:
- PS从Boot ROM加载第一阶段引导程序(FSBL)
- FSBL初始化PS基本外设(DDR、时钟、MIO)
- FSBL加载PL的比特流(Bitstream),配置FPGA逻辑
- 加载U-Boot或裸机程序,最终启动Linux
这个流程意味着:PL的配置是在PS控制下完成的。你可以选择在Linux启动前配置PL(早期配置),也可以在Linux启动后动态配置(部分重配置)。我一般用早期配置,简单可靠。
1.3 开发环境搭建:Vivado + Vitis + Petalinux
搭建开发环境是入门的第一道坎。很多新手在这里卡住,其实没那么复杂。我按自己的习惯,把搭建过程分成三步。
第一步:Vivado —— 硬件设计工具
Vivado负责PL端的开发:写RTL代码、综合、实现、生成比特流。也负责PS端的配置:DDR参数、时钟、外设使能。
- 版本选择:我建议用最新的稳定版,目前2023.x系列比较成熟
- 安装要点:勾选「Zynq-7000」器件库,其他按需选
- 许可证:WebPACK版免费,够用;如果要用Kintex-7以上器件,需要付费许可
小技巧:Vivado安装包很大(~30GB),下载时选「Combined Installer」一次性搞定。我习惯把Vivado、Vitis、Petalinux装在同一台Ubuntu 20.04机器上,省得来回切换。
第二步:Vitis —— 软件/嵌入式开发工具
Vitis是Xilinx的统一软件平台,替代了老的SDK。它负责:
- 编写PS端的裸机程序或Linux应用
- 编译、调试、下载
- 管理硬件平台(Hardware Platform)
Vitis的安装通常和Vivado一起完成。安装后需要配置一下XSA文件路径——XSA是Vivado导出的硬件描述文件,包含PS配置、地址映射、外设信息。
第三步:Petalinux —— Linux系统定制工具
Petalinux是Xilinx提供的嵌入式Linux构建系统,基于Yocto。它帮你生成:
- U-Boot引导程序
- Linux内核(含设备树)
- 根文件系统
- PL驱动模块
安装Petalinux前,需要确保系统满足依赖:
# Ubuntu 20.04 安装依赖
sudo apt-get install -y gawk wget git diffstat unzip texinfo \
gcc build-essential chrpath socat cpio python3 python3-pip \
python3-pexpect xz-utils debianutils iputils-ping python3-git \
python3-jinja2 libegl1-mesa libsdl1.2-dev pylint3 \
xterm python3-distutils python3-setuptools
# 设置Petalinux环境
source /opt/Xilinx/Petalinux/2023.1/settings.sh
注意:Petalinux对Ubuntu版本有严格限制。2023.1版本只支持Ubuntu 20.04和22.04。我曾经在Ubuntu 18.04上硬装,编译到一半报错,浪费了半天。老老实实按官方文档来。
1.4 知识结构总览:一张图看懂Zynq开发
下面这张SVG图,概括了Zynq开发的核心流程和工具链关系。我每次带新人,都会先让他们看这张图。
1.5 环境验证:跑通第一个Hello World
环境搭好后,我习惯先跑一个最简单的「Hello World」来验证。这里说的不是printf,而是让PS通过AXI_GP控制PL上的一个LED。
步骤很简单:
- Vivado中创建一个Block Design,添加Zynq PS核和AXI GPIO IP
- 连接AXI总线,分配地址(默认0x41200000)
- 生成比特流,导出XSA
- Vitis中创建裸机工程,写代码:
#include "xparameters.h"
#include "xgpio.h"
XGpio gpio;
int main() {
// 初始化GPIO设备
XGpio_Initialize(&gpio, XPAR_AXI_GPIO_0_DEVICE_ID);
// 设置方向:输出
XGpio_SetDataDirection(&gpio, 1, 0x00);
// 循环闪烁
while(1) {
XGpio_DiscreteWrite(&gpio, 1, 0x01); // LED亮
sleep(1);
XGpio_DiscreteWrite(&gpio, 1, 0x00); // LED灭
sleep(1);
}
return 0;
}
下载到板子上,看到LED闪烁,说明整个工具链通了。嗯,这一步虽然简单,但能帮你排除90%的环境问题。
我的习惯:每次新项目开始前,我都会用这个「LED闪烁」工程验证开发板、下载器、工具链是否正常。别嫌它简单,它能帮你省下后面排查「到底是代码问题还是环境问题」的时间。
1.6 本章小结
Zynq平台的核心就三件事:PS管控制、PL管加速、AXI管通信。开发环境搭建也不复杂,Vivado做硬件、Vitis做软件、Petalinux做系统,三者通过XSA文件串联。记住启动顺序:PS先跑,再配PL,最后进Linux。