1. Zynq架构概览:PS与PL的划分、AXI总线基础、Zynq启动流程与调试入口
好,咱们开始第一讲。Zynq这个芯片,说白了就是一颗ARM处理器和一个FPGA坐在同一块硅片上。很多人刚接触时容易懵——它到底算ARM开发还是FPGA开发?我的答案是:两者都是,而且你得学会让它们配合。
我个人习惯把Zynq看作一个「双核团队」:PS(Processing System)是项目经理,负责跑Linux、做控制、处理网络协议;PL(Programmable Logic)是执行团队,专门干那些高吞吐、低延迟的脏活累活。你想想看,如果让ARM去处理1Gbps的视频流,光是中断就能把它淹死。但交给PL,流水线一搭,数据直接流过,延迟能控制在微秒级。
1.1 PS与PL的划分
先看一张我手绘的架构简图,帮你建立整体印象:
从图上你能看到,PS和PL是两块完全独立的「领地」。PS这边跑的是ARM硬核,有自己的一级二级缓存、内存控制器和各种外设。PL那边就是FPGA fabric,LUT、FF、DSP、BRAM这些资源随便你用。
但真正有意思的是中间那条紫色的AXI总线。它就像一座桥,让两边可以高速交换数据。我在项目中遇到过不少新手,把PS和PL当成两个独立芯片来调试,结果两边数据对不上,查了三天才发现是AXI握手时序出了问题。
1.2 AXI总线基础
AXI是ARM公司推出的高性能总线协议,Zynq里主要用了三种:
| AXI 类型 | 特点 | 典型用途 | 我的经验 |
|---|---|---|---|
| AXI4 | 高性能内存映射,支持突发传输 | DDR访问、大数据块搬运 | 适合一次传几百字节以上的场景 |
| AXI4-Lite | 简化版,单次传输,无突发 | 配置寄存器、状态查询 | 我习惯用它做控制通道,简单可靠 |
| AXI4-Stream | 无地址,连续数据流 | 视频流、DMA、FIFO | 延迟最低,适合高速流水线 |
为什么要有三种?你想想看,如果你只是想读一个状态寄存器,用AXI4搞个16拍的突发传输,那不是杀鸡用牛刀吗?反过来,如果你要传一帧1080p的视频,用AXI4-Lite一次传4字节,CPU得等到天荒地老。
AXI的握手信号其实不复杂,核心就是五个通道:
- 读地址通道(AR):主机告诉从机「我要读哪个地址」
- 读数据通道(R):从机把数据返回给主机
- 写地址通道(AW):主机告诉从机「我要写哪个地址」
- 写数据通道(W):主机把数据发给从机
- 写响应通道(B):从机告诉主机「写完了,没问题」
每个通道都用VALID和READY信号做握手。VALID表示发送方数据有效,READY表示接收方准备好了。两者同时为高时,一个传输完成。
1.3 Zynq启动流程
Zynq的启动流程,说白了就是「谁先醒,谁后醒」的问题。PS是老大,它先启动,然后通过PCAP接口把PL的bitstream加载进去。整个过程分三个阶段:
- BootROM(阶段0):芯片上电后,ARM核先执行片内的BootROM代码。它检查启动模式引脚(MIO[2:0]),决定从QSPI、NAND、SD卡还是JTAG加载。
- FSBL(阶段1):BootROM把FSBL(First Stage Boot Loader)加载到OCM(On-Chip Memory)并执行。FSBL负责初始化PS的基本外设(时钟、DDR、MIO),然后加载PL的bitstream。
- SSBL / 用户程序(阶段2):FSBL加载完bitstream后,再加载SSBL(比如U-Boot)或者直接启动裸机程序。SSBL再加载操作系统内核。
这里有个关键点:PL的bitstream是在FSBL阶段加载的。也就是说,在PS跑Linux之前,PL就已经配置好了。如果你想让PL在Linux启动后再动态重配置,那就得用PCAP驱动或者DMA方式,那是进阶话题了。
1.4 调试入口
调试Zynq,你得准备好几把「钥匙」:
| 调试对象 | 工具 | 接口 | 适用场景 |
|---|---|---|---|
| PS 软件 | Xilinx SDK / Vitis | JTAG + 串口 | 单步调试、断点、变量查看 |
| PL 逻辑 | Vivado + ILA / VIO | JTAG | 波形抓取、内部信号观察 |
| PS-PL 交互 | AXI Monitor / Trace | JTAG | 总线事务分析、性能统计 |
| Linux 内核 | KGDB / printk / ftrace | 串口 / 网络 | 驱动调试、性能分析 |
我个人最常用的组合是:ILA抓PL波形 + SDK调试PS代码 + 串口打印日志。三管齐下,大部分问题都能定位。