ZYNQ PS-PL 架构解析:ARM 与 FPGA 融合设计及实战
概述
ZYNQ 是 Xilinx 推出的革命性 SoC (System on Chip) 产品,它首次将高性能 ARM 处理器与 FPGA 完美融合在一个芯片上。这种融合设计打破了传统 FPGA 和处理器的界限,为嵌入式系统设计带来了全新的可能性。
ZYNQ 的核心价值:
- 充分发挥 ARM 处理器的控制能力和 FPGA 的并行计算能力
- 实现硬件和软件的完美协同
全面解析了 Xilinx ZYNQ SoC 的 PS-PL 架构,涵盖 PS 处理系统与 PL 可编程逻辑的基础概念、内部结构及资源特性。详细介绍了 AXI 互连架构、PS-PL 物理接口(GP/HP/ACP)及 AXI 协议握手机制。内容包含 DDR 访问、共享内存、中断驱动等通信实战案例,以及视频处理、实时控制等应用场景。同时阐述了 ZYNQ 启动流程、时钟系统配置及最佳实践,旨在帮助开发者掌握软硬协同设计方法,优化系统性能与开发效率。
ZYNQ 是 Xilinx 推出的革命性 SoC (System on Chip) 产品,它首次将高性能 ARM 处理器与 FPGA 完美融合在一个芯片上。这种融合设计打破了传统 FPGA 和处理器的界限,为嵌入式系统设计带来了全新的可能性。
ZYNQ 的核心价值:
本文将帮助您深入理解 PS 和 PL 的概念及其各自的特点,掌握 ZYNQ 的基本架构和组成部分,理解 PS-PL 之间的通信机制,学会设计 PS-PL 协同工作的系统,并通过实战案例巩固理论知识。
在 ZYNQ 芯片中,有两个核心概念需要理解:PS(Processing System) 和 PL(Programmable Logic)。
PS(Processing System) 是指 ZYNQ 芯片中与 FPGA 无关的 ARM 处理器系统部分。
PS 的核心组成:
📊 PS(处理系统) 结构
├─ 应用处理单元 (APU)
│ ├─ 双核 ARM Cortex-A9 处理器
│ ├─ 256KB L2 缓存
│ ├─ 浮点单元 (FPU)
│ └─ NEON 媒体处理引擎
├─ 存储系统
│ ├─ 片内 OCM(On-Chip Memory)
│ ├─ DDR3/DDR4 接口
│ └─ 存储管理单元 (MMU)
├─ 外设接口
│ ├─ USB 2.0
│ ├─ 以太网 (Gigabit Ethernet)
│ ├─ SD/SDIO
│ ├─ SPI
│ ├─ I2C
│ ├─ UART
│ └─ GPIO
└─ 互连与控制
├─ AXI 互连
├─ 时钟管理
├─ 电源管理
└─ 中断控制
PS 的特点:
PL(Programmable Logic) 是指 ZYNQ 芯片中的 FPGA 部分,基于 Xilinx 7 系列 FPGA 架构。
PL 的核心组成:
📊 PL(可编程逻辑) 结构
├─ 逻辑资源
│ ├─ 查找表 (LUT)
│ ├─ 触发器 (FF)
│ └─ 多路选择器 (MUX)
├─ 存储资源
│ ├─ Block RAM(BRAM)
│ ├─ 分布式 RAM
│ └─ FIFO
├─ 计算资源
│ ├─ DSP48E1 切片
│ ├─ 乘法器
│ └─ 累加器
├─ 高速接口
│ ├─ 高速收发器 (GTX/GTP)
│ ├─ PCIe 接口
│ └─ 串行接口
└─ 时钟资源
├─ 全局时钟网络
├─ PLL/MMCM
└─ 时钟缓冲
PL 的特点:
| 特性 | PS(处理系统) | PL(可编程逻辑) |
|---|---|---|
| 处理方式 | 串行处理 | 并行处理 |
| 适用场景 | 控制、算法、OS | 数据处理、加速 |
| 资源占用 | 硬核,不占用逻辑 | 占用 FPGA 逻辑资源 |
| 时钟频率 | 最高 1GHz | 最高 500MHz+ |
| 功耗 | 相对较低 | 可配置 |
| 开发语言 | C/C++/汇编 | Verilog/VHDL |
| 启动时间 | 毫秒级 | 需要配置 |
| 可重构性 | 固定 | 动态可重构 |
ZYNQ-7000 是 Xilinx 推出的第一代 SoC 产品,采用 28nm 工艺,集成了 ARM 处理器和 FPGA。
ZYNQ-7000 的三个子系列:
📊 ZYNQ-7000 系列分类
├─ Z-7010/Z-7015
│ ├─ 基于 Artix-7 FPGA
│ ├─ 逻辑资源较少
│ └─ 适合入门和低成本应用
├─ Z-7020/Z-7030
│ ├─ 基于 Kintex-7 FPGA
│ ├─ 逻辑资源中等
│ └─ 适合大多数应用
└─ Z-7045/Z-7100
├─ 基于 Kintex-7 FPGA
├─ 逻辑资源最多
└─ 适合高端应用
ZYNQ-7000 的关键特性:
| 型号 | Z-7010 | Z-7020 | Z-7045 |
|---|---|---|---|
| FPGA 基础 | Artix-7 | Kintex-7 | Kintex-7 |
| 逻辑单元 (LUT) | 28K | 85K | 350K |
| Block RAM(KB) | 1.8MB | 4.9MB | 19.2MB |
| DSP48E1 | 80 | 240 | 900 |
| 高速收发器 | 4 | 4 | 16 |
| 最大时钟频率 | 1GHz | 1GHz | 1GHz |
┌─────────────────────────────────────────────────────┐
│ ZYNQ-7000 SoC │
├─────────────────────────────────────────────────────┤
│ │
│ ┌──────────────────────┐ ┌──────────────────────┐ │
│ │ PS(处理系统) │ │ PL(可编程逻辑) │ │
│ │ │ │ │ │
│ │ ┌────────────────┐ │ │ ┌────────────────┐ │ │
│ │ │ ARM Cortex-A9 │ │ │ │ FPGA 逻辑 │ │ │
│ │ │ (双核) │ │ │ │ (LUT/FF) │ │ │
│ │ └────────────────┘ │ │ └────────────────┘ │ │
│ │ │ │ │ │
│ │ ┌────────────────┐ │ │ ┌────────────────┐ │ │
│ │ │ DDR 控制器 │ │ │ │ Block RAM │ │ │
│ │ │ 存储管理 │ │ │ │ DSP48E1 │ │ │
│ │ └────────────────┘ │ │ └────────────────┘ │ │
│ │ │ │ │ │
│ │ ┌────────────────┐ │ │ ┌────────────────┐ │ │
│ │ │ 外设接口 │ │ │ │ 高速收发器 │ │ │
│ │ │ (USB/ETH/SPI) │ │ │ │ (GTX/GTP) │ │ │
│ │ └────────────────┘ │ │ └────────────────┘ │ │
│ │ │ │ │ │
│ └──────────────────────┘ └──────────────────────┘ │
│ │
│ ┌──────────────────┐ │
│ │ AXI 互连 │ │
│ └──────────────────┘ │
└─────────────────────────────────────────────────────┘
纯 FPGA 设计的问题:
ZYNQ 融合设计的优点:
PS-PL 架构适用的典型应用:
PS-PL 协同的性能提升:
| 任务类型 | 纯 CPU | 纯 FPGA | PS+PL |
|---|---|---|---|
| 控制逻辑 | 100% | 50% | 100% |
| 数据处理 | 50% | 100% | 100% |
| 综合性能 | 60% | 70% | 95%+ |
| 功耗效率 | 中等 | 高 | 最高 |
系统成本对比:
| 指标 | CPU+FPGA | 纯 FPGA | ZYNQ |
|---|---|---|---|
| 芯片成本 | 高 | 中等 | 低 |
| PCB 面积 | 大 | 中等 | 小 |
| 功耗 | 高 | 中等 | 低 |
| 集成度 | 低 | 中等 | 高 |
| 总体成本 | 最高 | 中等 | 最低 |
开发周期对比:
| 开发阶段 | CPU+FPGA | 纯 FPGA | ZYNQ |
|---|---|---|---|
| 硬件设计 | 复杂 | 中等 | 简单 |
| 软件开发 | 标准 | 困难 | 标准 |
| 集成测试 | 困难 | 困难 | 相对简单 |
| 总开发周期 | 长 | 长 | 短 |
| 维护成本 | 高 | 中等 | 低 |
ARM Cortex-A9 的核心特性:
ARM Cortex-A9 是一款应用级处理器,是 ZYNQ PS 端的核心。ZYNQ-7000 系列采用双核对称多处理 (SMP) 架构。
处理器特性:
📊 ARM Cortex-A9 处理器特性
├─ 架构特点
│ ├─ 32 位 RISC 架构
│ ├─ 支持 Thumb-2 指令集
│ ├─ 乱序执行 (Out-of-Order Execution)
│ └─ 动态功率管理
├─ 性能指标
│ ├─ 最高频率:1GHz
│ ├─ 每周期指令数 (IPC): 2.5
│ ├─ 峰值性能:2.5 GIPS
│ └─ 浮点性能:2.5 GFLOPS
├─ 缓存系统
│ ├─ L1 指令缓存:32KB/核
│ ├─ L1 数据缓存:32KB/核
│ ├─ L2 统一缓存:256KB(共享)
│ └─ 缓存一致性:SCU 管理
└─ 功能单元
├─ 浮点单元 (FPU)
├─ NEON 媒体处理引擎
├─ 存储管理单元 (MMU)
└─ 中断控制器
双核架构的优势:
NEON 的功能:
NEON 是 ARM Cortex-A9 的一个协处理器,实现单指令多数据 (SIMD) 功能。
📊 NEON 处理引擎特性
├─ 数据类型支持
│ ├─ 8 位整数
│ ├─ 16 位整数
│ ├─ 32 位整数
│ ├─ 64 位整数
│ └─ 32 位浮点
├─ 寄存器组
│ ├─ 16 个 128 位寄存器
│ ├─ 可视为 32 个 64 位寄存器
│ └─ 可视为 64 个 32 位寄存器
├─ 指令集
│ ├─ 算术运算 (加、减、乘)
│ ├─ 逻辑运算 (与、或、非)
│ ├─ 移位运算
│ ├─ 比较运算
│ └─ 数据转换
└─ 应用场景
├─ 图像处理
├─ 视频编解码
├─ 音频处理
├─ 信号处理
└─ 科学计算
NEON 性能示例:
| 操作类型 | 标准 ARM | NEON |
|---|---|---|
| 8 位加法 | 1 次/周期 | 16 次/周期 |
| 16 位乘法 | 1 次/周期 | 8 次/周期 |
| 32 位乘法 | 1 次/周期 | 4 次/周期 |
| 性能提升 | 基准 | 4-16 倍 |
FPU 的功能:
浮点单元支持 IEEE 754 标准的浮点运算。
📊 FPU 特性
├─ 支持的数据类型
│ ├─ 单精度浮点 (32 位)
│ ├─ 双精度浮点 (64 位)
│ └─ 特殊值 (NaN, Inf)
├─ 支持的运算
│ ├─ 加法/减法
│ ├─ 乘法/除法
│ ├─ 平方根
│ ├─ 比较
│ └─ 转换
└─ 性能指标
├─ 单精度:1 GFLOPS
├─ 双精度:0.5 GFLOPS
└─ 吞吐量:1 个操作/周期
OCM(On-Chip Memory) 的特点:
📊 OCM 存储结构
├─ 容量
│ ├─ 总容量:256KB
│ ├─ 分为两个 128KB 块
│ └─ 可配置为指令/数据存储
├─ 特性
│ ├─ 低延迟:1-2 个周期
│ ├─ 高带宽:64 位/周期
│ ├─ 低功耗:相对 DDR
│ └─ 可靠性:支持 ECC
├─ 用途
│ ├─ 启动代码存储
│ ├─ 实时关键代码
│ ├─ 中断处理程序
│ └─ 高速缓存
└─ 访问方式
├─ ARM 处理器直接访问
├─ PL 通过 AXI 访问
└─ DMA 访问
OCM 的应用场景:
DDR 接口特性:
📊 DDR 存储系统
├─ 支持的 DDR 类型
│ ├─ DDR3(ZYNQ-7000)
│ ├─ DDR4(Zynq MPSoC)
│ └─ LPDDR2/LPDDR3
├─ 容量范围
│ ├─ 最小:256MB
│ ├─ 常见:512MB-2GB
│ └─ 最大:4GB+
├─ 性能指标
│ ├─ 数据位宽:32 位
│ ├─ 最大频率:533MHz(DDR3-1066)
│ ├─ 理论带宽:4.2GB/s
│ └─ 实际带宽:2-3GB/s
└─ 特性
├─ 硬件控制器 (PS 端)
├─ 自动刷新
├─ 功率管理
└─ 错误检测
DDR 访问方式:
┌─────────────────────────────────────┐
│ DDR3 存储器访问方式 │
├─────────────────────────────────────┤
│ │
│ PS 端 (ARM 处理器) │
│ └─ 直接访问 (通过 DDR 控制器) │
│ │
│ PL 端 (FPGA) │
│ └─ 通过 AXI-HP 接口访问 │
│ (由 PL 中的 DMA 或自定义 IP 发起) │
│ │
│ 共享内存 │
│ └─ PS 和 PL 都可访问 │
│ (用于数据交互) │
└─────────────────────────────────────┘
ZYNQ 提供的通信接口:
📊 通信接口一览
├─ USB 2.0
│ ├─ 1 个 USB 2.0 OTG 接口
│ ├─ 支持主机和设备模式
│ ├─ 最高速率:480Mbps
│ └─ 应用:USB 存储、USB 网络
├─ 以太网 (Gigabit Ethernet)
│ ├─ 1 个 GigE MAC
│ ├─ 支持 RGMII/GMII 接口
│ ├─ 速率:10/100/1000Mbps
│ └─ 应用:网络通信、远程控制
├─ SD/SDIO
│ ├─ 1 个 SD/SDIO 接口
│ ├─ 支持 SD 2.0/3.0
│ ├─ 最高速率:50MHz
│ └─ 应用:存储卡、WiFi 模块
└─ CAN 总线
├─ 1 个 CAN 2.0 接口
├─ 支持标准和扩展帧
├─ 最高速率:1Mbps
└─ 应用:工业控制、汽车
低速接口特性:
📊 低速接口
├─ SPI(Serial Peripheral Interface)
│ ├─ 2 个 SPI 接口
│ ├─ 支持主从模式
│ ├─ 最高速率:50MHz
│ └─ 应用:Flash、传感器
├─ I2C(Inter-Integrated Circuit)
│ ├─ 2 个 I2C 接口
│ ├─ 支持 100K/400K/3.4M 速率
│ ├─ 多主机支持
│ └─ 应用:传感器、EEPROM
├─ UART(Universal Asynchronous Receiver/Transmitter)
│ ├─ 2 个 UART 接口
│ ├─ 支持波特率:300-921600
│ ├─ 硬件流控支持
│ └─ 应用:调试、串口通信
└─ GPIO(General Purpose Input/Output)
├─ 54 个 GPIO 引脚
├─ 可配置为输入/输出
├─ 支持中断
└─ 应用:LED、按钮、传感器
ZYNQ 的中断架构:
📊 中断系统结构
├─ 中断源
│ ├─ 外设中断 (32 个)
│ ├─ PL 中断 (16 个)
│ ├─ SGI(软件生成中断)
│ └─ PPI(私有外设中断)
├─ 中断控制器 (GIC)
│ ├─ 通用中断控制器
│ ├─ 支持优先级
│ ├─ 支持中断分配
│ └─ 支持中断屏蔽
└─ 中断处理
├─ ARM 处理器响应
├─ 中断向量表
├─ 中断服务程序 (ISR)
└─ 中断返回
ZYNQ 的时钟系统:
📊 时钟管理系统
├─ 时钟源
│ ├─ 外部晶振 (33.33MHz)
│ ├─ PLL 倍频
│ └─ 分频器
├─ 主要时钟
│ ├─ ARM 时钟:最高 1GHz
│ ├─ DDR 时钟:533MHz
│ ├─ 外设时钟:100MHz
│ └─ PL 时钟:可配置
├─ 时钟管理功能
│ ├─ 动态频率调整
│ ├─ 时钟门控
│ ├─ 功率管理
│ └─ 时钟监测
└─ 应用
├─ 功耗优化
├─ 性能调整
├─ 热管理
└─ 功率管理
ZYNQ 支持的操作系统:
📊 操作系统支持
├─ Linux
│ ├─ Xilinx Linux(基于 Yocto)
│ ├─ Ubuntu ARM 版本
│ ├─ Debian ARM 版本
│ └─ 其他发行版
├─ 实时操作系统 (RTOS)
│ ├─ FreeRTOS
│ ├─ Xilinx RTOSes
│ ├─ QNX
│ └─ VxWorks
├─ 裸机 (Bare Metal)
│ ├─ 无 OS 运行
│ ├─ 最小化开销
│ ├─ 最高实时性
│ └─ 适合简单应用
└─ 混合模式
├─ 一个核运行 Linux
├─ 另一个核运行 RTOS
├─ 核间通信
└─ 最大灵活性
ZYNQ 开发工具链:
📊 开发工具
├─ Xilinx Vitis
│ ├─ 统一开发环境
│ ├─ C/C++编译器
│ ├─ 调试工具
│ └─ 性能分析
├─ Xilinx SDK(已弃用)
│ ├─ 旧版开发环境
│ ├─ 仍可使用
│ └─ 逐步迁移到 Vitis
├─ 编译工具
│ ├─ ARM GCC 编译器
│ ├─ Linaro 工具链
│ └─ 第三方编译器
└─ 调试工具
├─ JTAG 调试器
├─ 串口调试
└─ 性能分析工具
LUT 的基本概念:
LUT(Look-Up Table) 是 FPGA 的基本逻辑单元,用于实现组合逻辑。
📊 LUT 结构与工作原理
├─ LUT 的组成
│ ├─ 6 输入 LUT(ZYNQ-7000)
│ ├─ 64 个存储单元 (2^6)
│ ├─ 多路选择器
│ └─ 输出缓冲
├─ LUT 的特性
│ ├─ 可实现任意 6 输入逻辑函数
│ ├─ 延迟固定 (约 0.5ns)
│ ├─ 功耗低
│ └─ 灵活性高
├─ LUT 的应用
│ ├─ 组合逻辑实现
│ ├─ 分布式 RAM
│ ├─ 移位寄存器
│ └─ 逻辑函数生成
└─ 性能指标
├─ 最大频率:500MHz+
├─ 延迟:0.5ns
├─ 功耗:极低
└─ 集成度:高
LUT 的使用示例:
// 使用 LUT 实现逻辑函数
// 例:4 输入与门
module lut_example (
input [3:0] in,
output out
);
// 使用 LUT 实现:out = in[0] & in[1] & in[2] & in[3]
assign out = ∈
endmodule
// LUT 作为分布式 RAM
module lut_ram (
input clk,
input [5:0] addr,
input [7:0] din,
input we,
output [7:0] dout
);
reg [7:0] mem [63:0];
always @(posedge clk) begin
if (we) mem[addr] <= din;
end
assign dout = mem[addr];
endmodule
触发器的特性:
📊 触发器 (Flip-Flop) 特性
├─ 类型
│ ├─ D 触发器 (主要)
│ ├─ SR 触发器
│ ├─ 异步复位
│ └─ 异步置位
├─ 特点
│ ├─ 每个 LUT 配套一个 FF
│ ├─ 可选择使用
│ ├─ 支持异步复位/置位
│ └─ 支持时钟使能
├─ 应用
│ ├─ 时序逻辑实现
│ ├─ 寄存器设计
│ ├─ 状态机
│ └─ 流水线
└─ 性能
├─ 最大频率:500MHz+
├─ 建立时间:极短
├─ 保持时间:极短
└─ 功耗:低
MUX 的功能:
📊 多路选择器
├─ 功能
│ ├─ 数据选择
│ ├─ 路由控制
│ ├─ 条件分支
│ └─ 优先级编码
├─ 集成位置
│ ├─ CLB(可配置逻辑块) 内
│ ├─ 与 LUT 集成
│ ├─ 与 FF 集成
│ └─ 高速互连
├─ 应用场景
│ ├─ 数据通路选择
│ ├─ 控制信号路由
│ ├─ 条件执行
│ └─ 优先级处理
└─ 性能
├─ 延迟:0.2-0.5ns
├─ 功耗:极低
├─ 集成度:高
└─ 灵活性:强
BRAM 的特性:
ZYNQ-7000 系列提供大容量的 Block RAM,用于实现缓存、FIFO 等存储功能。
📊 Block RAM 特性
├─ 容量
│ ├─ Z-7010: 1.8MB
│ ├─ Z-7020: 4.9MB
│ ├─ Z-7045: 19.2MB
│ └─ 每个 BRAM 块:36Kb
├─ 工作模式
│ ├─ 单端口 RAM
│ ├─ 双端口 RAM
│ ├─ 真双端口 RAM
│ └─ FIFO 模式
├─ 数据宽度
│ ├─ 1-72 位可配置
│ ├─ 支持奇偶校验
│ ├─ 支持 ECC
│ └─ 灵活的宽度转换
├─ 性能指标
│ ├─ 访问延迟:2-3 个周期
│ ├─ 最大频率:500MHz+
│ ├─ 带宽:高
│ └─ 功耗:中等
└─ 应用
├─ 图像缓存
├─ 音频缓冲
├─ 数据 FIFO
├─ 查找表 (LUT)
└─ 深度缓存
BRAM 的使用示例:
// 双端口 RAM 设计
module dual_port_ram (
input clk,
input [11:0] addr_a,
input [11:0] addr_b,
input [31:0] din_a,
input we_a,
output [31:0] dout_a,
output [31:0] dout_b
);
reg [31:0] mem [4095:0];
always @(posedge clk) begin
if (we_a) mem[addr_a] <= din_a;
end
assign dout_a = mem[addr_a];
assign dout_b = mem[addr_b];
endmodule
// FIFO 设计
module fifo_bram (
input clk,
input rst,
input [31:0] din,
input wr_en,
input rd_en,
output [31:0] dout,
output full,
output empty
);
// FIFO 实现...
endmodule
分布式 RAM 的特点:
📊 分布式 RAM 特性
├─ 实现方式
│ ├─ 使用 LUT 实现
│ ├─ 每个 LUT 可作为 64x1 RAM
│ ├─ 多个 LUT 级联
│ └─ 灵活配置
├─ 容量
│ ├─ 小容量:64-512 字节
│ ├─ 灵活配置
│ ├─ 不占用 BRAM
│ └─ 节省资源
├─ 特性
│ ├─ 低延迟:1 个周期
│ ├─ 高速访问
│ ├─ 灵活宽度
│ └─ 功耗低
├─ 应用
│ ├─ 小型缓存
│ ├─ 寄存器堆
│ ├─ 移位寄存器
│ └─ 临时存储
└─ 对比 BRAM
├─ 容量:BRAM 更大
├─ 延迟:分布式更低
├─ 资源:分布式占用 LUT
└─ 成本:分布式更灵活
DSP 的功能:
DSP48E1 是 ZYNQ-7000 系列的数字信号处理切片,用于高速乘法、加法等运算。
📊 DSP48E1 特性
├─ 数量
│ ├─ Z-7010: 80 个
│ ├─ Z-7020: 240 个
│ ├─ Z-7045: 900 个
│ └─ 高度集成
├─ 功能单元
│ ├─ 乘法器 (25x18 位)
│ ├─ 加法器/减法器
│ ├─ 累加器
│ ├─ 逻辑运算
│ └─ 移位器
├─ 性能指标
│ ├─ 乘法延迟:3 个周期
│ ├─ 最大频率:500MHz+
│ ├─ 峰值性能:240 GMAC(Z-7020)
│ └─ 功耗:中等
├─ 应用
│ ├─ 数字滤波
│ ├─ FFT 运算
│ ├─ 矩阵运算
│ ├─ 信号处理
│ └─ 图像处理
└─ 工作模式
├─ 乘法模式
├─ 乘加模式
├─ 累加模式
└─ 级联模式
DSP 的使用示例:
// 使用 DSP 实现乘法
module dsp_multiplier (
input clk,
input [24:0] a,
input [17:0] b,
output [42:0] p
);
reg [24:0] a_reg;
reg [17:0] b_reg;
reg [42:0] p_reg;
always @(posedge clk) begin
a_reg <= a;
b_reg <= b;
p_reg <= a_reg * b_reg;
end
assign p = p_reg;
endmodule
// 使用 DSP 实现乘加
module dsp_mac (
input clk,
input [24:0] a,
input [17:0] b,
input [42:0] c,
output [42:0] result
);
reg [42:0] result_reg;
always @(posedge clk) begin
result_reg <= a * b + c;
end
assign result = result_reg;
endmodule
乘法器特性:
📊 乘法器特性
├─ 支持的运算
│ ├─ 有符号乘法
│ ├─ 无符号乘法
│ ├─ 混合乘法
│ └─ 级联乘法
├─ 精度
│ ├─ 25x18 位 = 43 位结果
│ ├─ 支持更高精度级联
│ ├─ 精度可配置
│ └─ 支持舍入
├─ 性能
│ ├─ 单周期乘法
│ ├─ 流水线支持
│ ├─ 高吞吐量
│ └─ 低延迟
└─ 应用
├─ 数字滤波器
├─ 相关运算
├─ 卷积运算
└─ 矩阵乘法
高速收发器的特性:
📊 高速收发器特性
├─ 类型
│ ├─ GTX 收发器 (高速)
│ ├─ GTP 收发器 (中速)
│ ├─ 支持多种协议
│ └─ 可配置
├─ 数量
│ ├─ Z-7010: 4 个
│ ├─ Z-7020: 4 个
│ ├─ Z-7045: 16 个
│ └─ 高度集成
├─ 性能指标
│ ├─ 速率:1.25-12.5 Gbps
│ ├─ 延迟:极低
│ ├─ 功耗:中等
│ └─ 集成度:高
├─ 支持的协议
│ ├─ PCIe 2.0/3.0
│ ├─ Gigabit Ethernet
│ ├─ SATA
│ ├─ DisplayPort
│ └─ 自定义协议
└─ 应用
├─ 高速数据传输
├─ 网络通信
├─ 视频传输
└─ 系统互连
PCIe 的功能:
📊 PCIe 接口特性
├─ 版本支持
│ ├─ PCIe 2.0(5 Gbps)
│ ├─ PCIe 3.0(8 Gbps)
│ ├─ 向后兼容
│ └─ 可配置
├─ 功能
│ ├─ 主设备模式
│ ├─ 从设备模式
│ ├─ 双向通信
│ └─ DMA 支持
├─ 应用
│ ├─ 与 PC 通信
│ ├─ 高速数据传输
│ ├─ 系统扩展
│ └─ 加速卡设计
└─ 性能
├─ 带宽:高
├─ 延迟:低
├─ 可靠性:高
└─ 易用性:好
时钟网络的特性:
📊 全局时钟网络
├─ 时钟类型
│ ├─ 全局时钟 (GCLK)
│ ├─ 区域时钟 (RCLK)
│ ├─ 本地时钟 (LCLK)
│ └─ 专用时钟
├─ 特点
│ ├─ 低延迟
│ ├─ 低抖动
│ ├─ 高扇出
│ └─ 低功耗
├─ 数量
│ ├─ 全局时钟:32 个
│ ├─ 区域时钟:多个
│ ├─ 灵活配置
│ └─ 充分冗余
└─ 应用
├─ 系统时钟
├─ 模块时钟
├─ 采样时钟
└─ 同步时钟
PLL 和 MMCM 的功能:
📊 PLL/MMCM 特性
├─ PLL(Phase-Locked Loop)
│ ├─ 倍频/分频
│ ├─ 相位调整
│ ├─ 频率合成
│ └─ 数量:2 个
├─ MMCM(Mixed-Mode Clock Manager)
│ ├─ 更高精度
│ ├─ 更多功能
│ ├─ 动态重配置
│ └─ 数量:2 个
├─ 功能
│ ├─ 频率倍增/分频
│ ├─ 相位移位
│ ├─ 抖动滤波
│ ├─ 多路输出
│ └─ 动态调整
├─ 性能指标
│ ├─ 输入频率:10-800MHz
│ ├─ 输出频率:4.7-800MHz
│ ├─ 相位精度:高
│ ├─ 抖动:低
│ └─ 功耗:中等
└─ 应用
├─ 时钟倍频
├─ 时钟分频
├─ 相位调整
├─ 多时钟域设计
└─ 动态频率调整
PLL/MMCM 的使用示例:
// 使用 MMCM 进行时钟倍频
module clk_pll (
input clk_in,
output clk_out_100m,
output clk_out_200m,
output locked
);
// MMCM 配置
// 输入:50MHz
// 输出 1: 100MHz
// 输出 2: 200MHz
// 使用 Xilinx IP 核实现
endmodule
ZYNQ-7000 系列资源对比:
| 资源类型 | Z-7010 | Z-7020 | Z-7045 |
|---|---|---|---|
| LUT | 28K | 85K | 350K |
| FF | 56K | 170K | 700K |
| BRAM(36Kb) | 50 | 140 | 540 |
| BRAM 容量 | 1.8MB | 4.9MB | 19.2MB |
| DSP48E1 | 80 | 240 | 900 |
| 高速收发器 | 4 | 4 | 16 |
| PLL | 2 | 2 | 2 |
| MMCM | 2 | 2 | 2 |
资源选型建议:
AXI(Advanced eXtensible Interface) 的定义:
AXI 是 ARM 推出的高性能、低延迟的片上互连标准,是 ZYNQ 中 PS 和 PL 通信的核心。
📊 AXI 互连架构
├─ 设计目标
│ ├─ 高带宽
│ ├─ 低延迟
│ ├─ 可扩展性
│ └─ 灵活性
├─ 核心特性
│ ├─ 分离的读写通道
│ ├─ 支持乱序完成
│ ├─ 支持突发传输
│ ├─ 支持多个主设备
│ └─ 支持多个从设备
├─ 版本
│ ├─ AXI3(32 位/64 位)
│ ├─ AXI4(128 位)
│ ├─ AXI4-Lite(简化版)
│ └─ AXI4-Stream(流式)
└─ 应用
├─ PS-PL 通信
├─ 高速数据传输
├─ 实时系统
└─ 多主多从系统
ZYNQ-7000 的 AXI 互连拓扑:
┌─────────────────────────────────────────────────────┐
│ ZYNQ-7000 AXI 互连拓扑 │
├─────────────────────────────────────────────────────┤
│ │
│ ┌──────────────────┐ ┌──────────────────┐ │
│ │ PS(主设备) │ │ PL(从设备) │ │
│ │ │ │ │ │
│ │ ┌──────────────┐ │ │ ┌──────────────┐ │ │
│ │ │ AXI-GP0 │ │ │ │ 用户 IP 核 │ │ │
│ │ │ (通用端口 0) │ │ │ │ │ │ │
│ │ └──────────────┘ │ │ └──────────────┘ │ │
│ │ │ │ │ │
│ │ ┌──────────────┐ │ │ ┌──────────────┐ │ │
│ │ │ AXI-GP1 │ │ │ │ 用户 IP 核 │ │ │
│ │ │ (通用端口 1) │ │ │ │ │ │ │
│ │ └──────────────┘ │ │ └──────────────┘ │ │
│ │ │ │ │ │
│ │ ┌──────────────┐ │ │ ┌──────────────┐ │ │
│ │ │ AXI-HP0-3 │ │ │ │ 用户 IP 核 │ │ │
│ │ │ (高性能端口) │ │ │ │ │ │ │
│ │ └──────────────┘ │ │ └──────────────┘ │ │
│ │ │ │ │ │
│ │ ┌──────────────┐ │ │ ┌──────────────┐ │ │
│ │ │ AXI-ACP │ │ │ │ 用户 IP 核 │ │ │
│ │ │ (缓存一致) │ │ │ │ │ │ │
│ │ └──────────────┘ │ │ └──────────────┘ │ │
│ │ │ │ │ │
│ └──────────────────┘ └──────────────────┘ │
│ │
│ ┌──────────────────┐ │
│ │ AXI 互连矩阵 │ │
│ └──────────────────┘ │
└─────────────────────────────────────────────────────┘
AXI-GP 的特性:
📊 AXI-GP 接口特性
├─ 接口数量
│ ├─ AXI-GP0: 1 个
│ ├─ AXI-GP1: 1 个
│ └─ 总计:2 个
├─ 数据宽度
│ ├─ 地址总线:32 位
│ ├─ 数据总线:32 位
│ ├─ 支持突发
│ └─ 支持乱序
├─ 性能指标
│ ├─ 最大频率:100MHz
│ ├─ 理论带宽:400MB/s
│ ├─ 延迟:中等
│ └─ 功耗:低
├─ 应用场景
│ ├─ 控制信号传输
│ ├─ 配置数据传输
│ ├─ 低速数据交互
│ └─ 中等带宽应用
└─ 特点
├─ 易于使用
├─ 功耗低
├─ 适合控制类应用
└─ 不适合高速数据
AXI-HP 的特性:
📊 AXI-HP 接口特性
├─ 接口数量
│ ├─ AXI-HP0: 1 个
│ ├─ AXI-HP1: 1 个
│ ├─ AXI-HP2: 1 个
│ ├─ AXI-HP3: 1 个
│ └─ 总计:4 个
├─ 数据宽度
│ ├─ 地址总线:32 位
│ ├─ 数据总线:64 位
│ ├─ 支持突发
│ └─ 支持乱序
├─ 性能指标
│ ├─ 最大频率:150MHz
│ ├─ 理论带宽:1.2GB/s(单端口)
│ ├─ 总带宽:4.8GB/s(4 个端口)
│ ├─ 延迟:低
│ └─ 功耗:中等
├─ 应用场景
│ ├─ 高速数据传输
│ ├─ 视频处理
│ ├─ 图像处理
│ ├─ 实时数据流
│ └─ DDR 访问
└─ 特点
├─ 高带宽
├─ 低延迟
├─ 支持多个端口
├─ 适合数据处理
└─ 功耗相对较高
AXI-ACP 的特性:
📊 AXI-ACP 接口特性
├─ 接口数量
│ ├─ AXI-ACP: 1 个
│ └─ 总计:1 个
├─ 数据宽度
│ ├─ 地址总线:32 位
│ ├─ 数据总线:64 位
│ ├─ 支持突发
│ └─ 支持乱序
├─ 核心特性
│ ├─ 缓存一致性
│ ├─ 与 ARM L2 缓存一致
│ ├─ 自动缓存管理
│ └─ 无需软件干预
├─ 性能指标
│ ├─ 最大频率:150MHz
│ ├─ 理论带宽:1.2GB/s
│ ├─ 延迟:低
│ └─ 功耗:中等
├─ 应用场景
│ ├─ 共享内存访问
│ ├─ 缓存一致的数据交互
│ ├─ 多核协同处理
│ ├─ 实时系统
│ └─ 高可靠性应用
└─ 特点
├─ 自动缓存一致性
├─ 无需软件管理
├─ 性能最优
├─ 适合共享数据
└─ 功耗相对较高
ZYNQ-7000 PS-PL 接口带宽对比:
| 接口类型 | 数据宽度 | 频率 | 带宽 |
|---|---|---|---|
| AXI-GP0/1 | 32 位 | 100MHz | 400MB/s |
| AXI-HP0/1/2/3 | 64 位 | 150MHz | 1.2GB/s |
| AXI-ACP | 64 位 | 150MHz | 1.2GB/s |
| 总理论带宽 | - | - | 9.6GB/s |
实际应用中的带宽利用:
PS-PL 地址空间映射:
📊 地址空间分配
├─ PS 端地址空间
│ ├─ 0x00000000 - 0x3FFFFFFF: DDR3(1GB)
│ ├─ 0x40000000 - 0x7FFFFFFF: PL 地址空间
│ ├─ 0x80000000 - 0xBFFFFFFF: 高地址 DDR
│ └─ 0xE0000000 - 0xFFFFFFFF: PS 外设
├─ PL 端地址空间
│ ├─ 0x40000000 - 0x7FFFFFFF: 用户自定义 IP
│ ├─ 0x80000000 - 0xBFFFFFFF: DDR 访问
│ └─ 0xE0000000 - 0xFFFFFFFF: PS 外设访问
└─ 特点
├─ 统一地址空间
├─ 易于编程
├─ 支持虚拟地址
└─ 需要正确配置
PS-PL 时钟域:
📊 时钟域管理
├─ PS 时钟
│ ├─ ARM 时钟:1GHz
│ ├─ DDR 时钟:533MHz
│ ├─ 外设时钟:100MHz
│ └─ 固定频率
├─ PL 时钟
│ ├─ 用户可配置
│ ├─ 通常 100-200MHz
│ ├─ 可动态调整
│ └─ 独立时钟域
├─ 时钟同步
│ ├─ 使用 CDC(Clock Domain Crossing)
│ ├─ 使用同步器
│ ├─ 避免亚稳态
│ └─ 关键设计
└─ 最佳实践
├─ 使用握手信号
├─ 使用 FIFO 缓冲
├─ 避免直接跨域
└─ 充分测试
PS-PL 通信的三种主要方式:
📊 PS-PL 通信方式
├─ 方式 1: 轮询 (Polling)
│ ├─ PS 定期读取 PL 状态
│ ├─ 简单易实现
│ ├─ CPU 占用率高
│ ├─ 延迟不确定
│ └─ 适合低频应用
├─ 方式 2: 中断 (Interrupt)
│ ├─ PL 产生中断信号
│ ├─ PS 响应中断
│ ├─ CPU 占用率低
│ ├─ 延迟低
│ └─ 适合实时应用
└─ 方式 3: DMA(Direct Memory Access)
├─ 直接内存访问
├─ 无需 CPU 干预
├─ 吞吐量最高
└─ 适合高速数据传输
通信方式对比:
| 特性 | 轮询 | 中断 | DMA |
|---|---|---|---|
| CPU 占用率 | 高 | 低 | 极低 |
| 延迟 | 不确定 | 低 | 极低 |
| 吞吐量 | 低 | 中等 | 高 |
| 实现复杂度 | 低 | 中等 | 高 |
| 功耗 | 高 | 中等 | 低 |
| 适用场景 | 低频 | 实时 | 高速 |
握手机制的基本原理:
AXI 协议使用 VALID 和 READY 信号实现握手机制,确保数据的可靠传输。
📊 VALID/READY 握手机制
├─ VALID 信号
│ ├─ 由发送方驱动
│ ├─ 表示数据有效
│ ├─ 高电平表示数据准备好
│ └─ 保持到握手完成
├─ READY 信号
│ ├─ 由接收方驱动
│ ├─ 表示接收方准备好
│ ├─ 高电平表示可以接收
│ └─ 可随时变化
├─ 握手条件
│ ├─ VALID & READY = 1 时握手
│ ├─ 数据在握手时刻被锁存
│ ├─ 握手后信号可变化
│ └─ 无需等待
└─ 特点
├─ 简单高效
├─ 支持背压
├─ 支持流控
└─ 易于实现
握手时序图:
时钟周期:T0 T1 T2 T3 T4 T5
│
│
│
│
│
│
VALID: ─┐ ┌─────┐ ┌─────┐ ┌─
│└────┘ └────┘ └────┘ │
READY: ─┐ ┌─────┐ ┌─────┐ ┌─
│└────┘ └────┘ └────┘ │
握手: ┌─────┐ ┌─────┐ ┌─────┐
✓ │ │ ✓ │ │ ✓ │
└─────┘ └─────┘ └─────┘
说明:
- T0-T1: VALID 和 READY 都为高,发生握手
- T1-T2: VALID 为低,READY 为高,等待数据
- T2-T3: VALID 和 READY 都为高,再次握手
- T3-T4: VALID 为高,READY 为低,接收方忙
- T4-T5: VALID 和 READY 都为高,握手完成
不同场景下的握手:
📊 握手场景分析
├─ 场景 1: 发送方快速,接收方快速
│ ├─ VALID 和 READY 都持续为高
│ ├─ 每个周期都发生握手
│ ├─ 最高效率
│ └─ 理想情况
├─ 场景 2: 发送方快速,接收方慢速
│ ├─ READY 间歇性为低
│ ├─ 发送方需要等待
│ ├─ 流控生效
│ └─ 常见情况
├─ 场景 3: 发送方慢速,接收方快速
│ ├─ VALID 间歇性为低
│ ├─ 接收方等待数据
│ ├─ 接收方空闲
│ └─ 常见情况
└─ 场景 4: 发送方和接收方都慢速
├─ VALID 和 READY 都间歇性为低
├─ 握手不频繁
├─ 系统效率低
└─ 需要优化
AXI 写通道的组成:
📊 AXI 写通道结构
├─ 写地址通道 (Write Address Channel)
│ ├─ AWVALID: 写地址有效
│ ├─ AWREADY: 写地址准备好
│ ├─ AWADDR: 写地址 (32 位)
│ ├─ AWLEN: 突发长度 (0-255)
│ ├─ AWSIZE: 突发大小 (1/2/4/8 字节)
│ ├─ AWBURST: 突发类型 (INCR/FIXED/WRAP)
│ └─ 其他控制信号
├─ 写数据通道 (Write Data Channel)
│ ├─ WVALID: 写数据有效
│ ├─ WREADY: 写数据准备好
│ ├─ WDATA: 写数据 (32/64/128 位)
│ ├─ WSTRB: 写使能 (字节选择)
│ ├─ WLAST: 最后一个数据
│ └─ 其他控制信号
└─ 写响应通道 (Write Response Channel)
├─ BVALID: 响应有效
├─ BREADY: 响应准备好
├─ BRESP: 响应状态 (OKAY/EXOKAY/SLVERR/DECERR)
└─ 其他控制信号
写操作时序:
时钟周期:T0 T1 T2 T3 T4 T5
│
│
│
│
│
│
写地址: ─┐ ┌─────┐ ┌─────┐ ┌─
│└────┘ └────┘ └────┘ │
写数据: ─┐ ┌─────┬─────┬─────┐ ┌─
│└────┘ │ │ └────┘ │ └─────┴─────┘ │
写响应: ─┐ ┌─────────────┐ ┌─
│└────┘ └────┘ 说明:
- T0-T1: 发送写地址
- T1-T3: 发送写数据 (3 个数据)
- T3-T4: 接收写响应
AXI 读通道的组成:
📊 AXI 读通道结构
├─ 读地址通道 (Read Address Channel)
│ ├─ ARVALID: 读地址有效
│ ├─ ARREADY: 读地址准备好
│ ├─ ARADDR: 读地址 (32 位)
│ ├─ ARLEN: 突发长度 (0-255)
│ ├─ ARSIZE: 突发大小 (1/2/4/8 字节)
│ ├─ ARBURST: 突发类型 (INCR/FIXED/WRAP)
│ └─ 其他控制信号
└─ 读数据通道 (Read Data Channel)
├─ RVALID: 读数据有效
├─ RREADY: 读数据准备好
├─ RDATA: 读数据 (32/64/128 位)
├─ RRESP: 响应状态 (OKAY/EXOKAY/SLVERR/DECERR)
├─ RLAST: 最后一个数据
└─ 其他控制信号
读操作时序:
时钟周期:T0 T1 T2 T3 T4 T5
│
│
│
│
│
│
读地址: ─┐ ┌─────┐ ┌─────┐ ┌─
│└────┘ └────┘ └────┘ │
读数据: ─┐ ┌─────┬─────┬─────┐ ┌─
│└────┘ │ │ └────┘ │ └─────┴─────┘ 说明:
- T0-T1: 发送读地址
- T2-T4: 接收读数据 (3 个数据)
- 读延迟通常为 2-3 个周期
突发传输的特性:
📊 突发传输特性
├─ 突发长度 (AWLEN/ARLEN)
│ ├─ 范围:0-255
│ ├─ 实际长度 = AWLEN + 1
│ ├─ 例:AWLEN=3 表示 4 个数据
│ └─ 最大 256 个数据
├─ 突发大小 (AWSIZE/ARSIZE)
│ ├─ 000: 1 字节
│ ├─ 001: 2 字节
│ ├─ 010: 4 字节
│ ├─ 011: 8 字节
│ └─ 100: 16 字节
├─ 突发类型 (AWBURST/ARBURST)
│ ├─ INCR: 递增地址
│ ├─ FIXED: 固定地址
│ ├─ WRAP: 环绕地址
│ └─ 最常用:INCR
└─ 优势
├─ 高效率
├─ 低延迟
├─ 高吞吐量
└─ 灵活性强
突发传输示例:
突发长度=4, 突发大小=4 字节,突发类型=INCR
地址序列:
┌─────────┬─────────┬─────────┬─────────┐
│ 0x1000 │ 0x1004 │ 0x1008 │ 0x100C │
├─────────┼─────────┼─────────┼─────────┤
│ 数据 1 │ 数据 2 │ 数据 3 │ 数据 4 │
└─────────┴─────────┴─────────┴─────────┘
时序:
时钟周期:T0 T1 T2 T3 T4 T5
│
│
│
│
│
│
地址: ─┐ ┌─────┐ ┌─────┐ ┌─
│└────┘ └────┘ └────┘ │
数据: ─┐ ┌─────┬─────┬─────┬─────┐
│└────┘ │ │ │ │
└─────┴─────┴─────┘
写使能的功能:
📊 写使能 (WSTRB) 特性
├─ 功能
│ ├─ 字节级写控制
│ ├─ 选择性写入
│ ├─ 灵活的数据掩码
│ └─ 支持部分写
├─ 位宽
│ ├─ 32 位数据:4 位 WSTRB
│ ├─ 64 位数据:8 位 WSTRB
│ ├─ 128 位数据:16 位 WSTRB
│ └─ 每位对应一个字节
├─ 使用示例
│ ├─ WSTRB=4'b1111: 写入全部 4 字节
│ ├─ WSTRB=4'b1100: 只写入高 2 字节
│ ├─ WSTRB=4'b0011: 只写入低 2 字节
│ ├─ WSTRB=4'b1010: 写入第 1 和第 3 字节
│ └─ WSTRB=4'b0000: 不写入任何字节
└─ 应用
├─ 部分数据更新
├─ 灵活的数据操作
├─ 提高效率
└─ 减少带宽浪费
AXI 响应状态:
📊 AXI 响应状态
├─ OKAY(2'b00)
│ ├─ 传输成功
│ ├─ 无错误
│ ├─ 最常见
│ └─ 正常情况
├─ EXOKAY(2'b01)
│ ├─ 独占传输成功
│ ├─ 用于原子操作
│ ├─ 较少使用
│ └─ 特殊情况
├─ SLVERR(2'b10)
│ ├─ 从设备错误
│ ├─ 地址不存在
│ ├─ 访问权限错误
│ └─ 需要处理
└─ DECERR(2'b11)
├─ 解码错误
├─ 地址无效
├─ 总线错误
└─ 严重错误
错误处理的最佳实践:
❌ 常见错误:
优化策略:
📊 吞吐量优化
├─ 策略 1: 增加突发长度
│ ├─ 使用更长的突发
│ ├─ 减少地址阶段开销
│ ├─ 提高效率
│ └─ 需要缓冲区支持
├─ 策略 2: 并行传输
│ ├─ 同时进行多个传输
│ ├─ 充分利用带宽
│ ├─ 需要多个端口
│ └─ 提高吞吐量
├─ 策略 3: 流水线操作
│ ├─ 地址和数据分离
│ ├─ 提前发送地址
│ ├─ 隐藏延迟
│ └─ 提高效率
└─ 策略 4: 优化时钟频率
├─ 提高工作频率
├─ 增加吞吐量
├─ 需要满足时序
└─ 权衡功耗
延迟优化:
📊 延迟优化
├─ 优化 1: 减少等待时间
│ ├─ 避免背压
│ ├─ 充分缓冲
│ ├─ 提高响应速度
│ └─ 关键指标
├─ 优化 2: 使用 AXI-ACP
│ ├─ 缓存一致性
│ ├─ 减少同步开销
│ ├─ 提高性能
│ └─ 适合共享数据
├─ 优化 3: 合理的突发配置
│ ├─ 平衡突发长度
│ ├─ 避免过长突发
│ ├─ 减少延迟
│ └─ 提高响应性
└─ 优化 4: 时钟域优化
├─ 同步时钟域
├─ 减少 CDC 延迟
├─ 提高性能
└─ 需要仔细设计
PL 访问 DDR 的方式:
📊 PL 访问 DDR 的方式
├─ 方式 1: 通过 AXI-HP 接口
│ ├─ 最常用方式
│ ├─ 高带宽 (1.2GB/s)
│ ├─ 低延迟
│ └─ 适合高速数据
├─ 方式 2: 通过 AXI-ACP 接口
│ ├─ 缓存一致性
│ ├─ 自动缓存管理
│ ├─ 性能最优
│ └─ 适合共享数据
├─ 方式 3: 通过 AXI-GP 接口
│ ├─ 低带宽 (400MB/s)
│ ├─ 简单易用
│ ├─ 功耗低
│ └─ 适合控制
└─ 方式 4: 通过 DMA
├─ 无需 CPU 干预
├─ 吞吐量最高
├─ 延迟最低
└─ 适合批量传输
PL 访问 DDR 的地址映射:
PS 端地址空间 PL 端访问地址
┌──────────────────┐ ┌──────────────────┐
│ 0x00000000 │ │ 0x00000000 │
│ ┌──────────────┐ │ │ ┌──────────────┐ │
│ │ DDR3 │ │ │ │ │ DDR3 │ │ │
│ │ (1GB) │ │ │ │ │ (1GB) │ │ │
│ │ │ │ │ │ │ │ │ │ │ │
│ └──────────────┘ │ │ └──────────────┘ │
│ 0x3FFFFFFF │ │ 0x3FFFFFFF │
│ │ │ │ │ │
│ 0x40000000 │ │ 0x40000000 │
│ ┌──────────────┐ │ │ ┌──────────────┐ │
│ │ PL 地址空间 │ │ │ │ PL 地址空间 │ │
│ │ │ │ │ │ │ │ │ │ │
│ └──────────────┘ │ │ └──────────────┘ │
│ 0x7FFFFFFF │ │ 0x7FFFFFFF │
└──────────────────┘ └──────────────────┘
PL 访问 DDR 的代码示例:
// PL 端通过 AXI-HP 访问 DDR
module ddr_access (
input clk,
input rst,
// AXI-HP 写地址通道
output [31:0] m_axi_awaddr,
output [7:0] m_axi_awlen,
output [2:0] m_axi_awsize,
output m_axi_awvalid,
input m_axi_awready,
// AXI-HP 写数据通道
output [63:0] m_axi_wdata,
output [7:0] m_axi_wstrb,
output m_axi_wlast,
output m_axi_wvalid,
input m_axi_wready,
// AXI-HP 写响应通道
input m_axi_bvalid,
output m_axi_bready
);
// 写入 DDR 的数据
reg [63:0] write_data;
reg [31:0] write_addr;
// 状态机
reg [1:0] state;
always @(posedge clk) begin
if (rst) begin
state <= 2'b00;
write_addr <= 32'h00000000;
end else begin
case (state)
2'b00: begin // 发送写地址
if (m_axi_awready) begin
state <= 2'b01;
end
end
2'b01: begin // 发送写数据
if (m_axi_wready && m_axi_wlast) begin
state <= 2'b10;
end
end
2'b10: begin // 等待写响应
if (m_axi_bvalid) begin
state <= 2'b00;
write_addr <= write_addr + 32'h8;
end
end
endcase
end
end
assign m_axi_awaddr = write_addr;
assign m_axi_awlen = 8'h0;
assign m_axi_awsize = 3'b011;
assign m_axi_awvalid = (state == 2'b00);
assign m_axi_wdata = write_data;
assign m_axi_wstrb = 8'hFF;
assign m_axi_wlast = 1'b1;
assign m_axi_wvalid = (state == 2'b01);
assign m_axi_bready = 1'b1;
endmodule
PS 访问 PL 的方式:
📊 PS 访问 PL 的方式
├─ 方式 1: 通过 AXI-GP 接口
│ ├─ 最常用方式
│ ├─ 简单易用
│ ├─ 适合控制和配置
│ └─ 带宽 400MB/s
├─ 方式 2: 通过内存映射
│ ├─ 将 PL 资源映射到内存
│ ├─ 像访问内存一样访问 PL
│ ├─ 简单直观
│ └─ 易于编程
├─ 方式 3: 通过中断
│ ├─ PL 产生中断
│ ├─ PS 响应中断
│ ├─ 实时性好
│ └─ 适合事件驱动
└─ 方式 4: 通过 DMA
├─ 高速数据传输
├─ 无需 CPU 干预
├─ 吞吐量高
└─ 适合批量数据
PS 访问 PL 的 C 代码示例:
// PS 端通过 AXI-GP 访问 PL
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
#define PL_BASE_ADDR 0x40000000
#define PL_SIZE 0x10000
int main() {
int fd;
void* virt_addr;
unsigned int* pl_reg;
// 打开/dev/mem
fd = open("/dev/mem", O_RDWR | O_SYNC);
if(fd < 0) {
printf("Failed to open /dev/mem\n");
return -1;
}
// 映射 PL 地址空间到虚拟地址
virt_addr = mmap(NULL, PL_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, PL_BASE_ADDR);
if(virt_addr == MAP_FAILED) {
printf("Failed to mmap\n");
close(fd);
return -1;
}
pl_reg = (unsigned int*)virt_addr;
// 读取 PL 寄存器
unsigned int value = pl_reg[0];
printf("PL Register 0: 0x%08x\n", value);
// 写入 PL 寄存器
pl_reg[0] = 0x12345678;
printf("Write 0x12345678 to PL Register 0\n");
// 读取验证
value = pl_reg[0];
printf("PL Register 0 after write: 0x%08x\n", value);
// 解除映射
munmap(virt_addr, PL_SIZE);
close(fd);
return 0;
}
共享内存的设计:
📊 PS-PL 共享内存设计
├─ 内存分配
│ ├─ 在 DDR 中分配共享区域
│ ├─ PS 和 PL 都可访问
│ ├─ 通常使用 DMA 传输
│ └─ 需要同步机制
├─ 同步机制
│ ├─ 使用标志位
│ ├─ 使用信号量
│ ├─ 使用中断
│ └─ 使用握手信号
├─ 缓存一致性
│ ├─ 使用 AXI-ACP
│ ├─ 自动缓存管理
│ ├─ 无需软件干预
│ └─ 性能最优
└─ 应用场景
├─ 数据缓冲
├─ 命令队列
├─ 结果存储
└─ 实时数据交互
共享内存的实现:
// PS 端共享内存管理
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SHARED_MEM_SIZE 0x100000 // 1MB
#define SHARED_MEM_ADDR 0x10000000
typedef struct {
unsigned int cmd; // 命令
unsigned int status; // 状态
unsigned int data_len; // 数据长度
unsigned char data[256]; // 数据缓冲
} shared_mem_t;
int main() {
int fd;
shared_mem_t* shared_mem;
// 映射共享内存
fd = open("/dev/mem", O_RDWR | O_SYNC);
shared_mem = (shared_mem_t*)mmap(NULL, SHARED_MEM_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, SHARED_MEM_ADDR);
// 初始化共享内存
memset(shared_mem, 0, sizeof(shared_mem_t));
// 发送命令给 PL
shared_mem->cmd = 0x01;
shared_mem->data_len = 10;
memcpy(shared_mem->data, "Hello PL!", 10);
// 等待 PL 处理
while(shared_mem->status == 0) {
usleep(100);
}
// 读取 PL 的结果
printf("PL Status: 0x%08x\n", shared_mem->status);
printf("PL Data: %s\n", (char*)shared_mem->data);
// 清理
munmap(shared_mem, SHARED_MEM_SIZE);
close(fd);
return 0;
}
中断驱动的优势:
📊 中断驱动的优势
├─ 优势 1: 实时性好
│ ├─ 立即响应事件
│ ├─ 无需轮询
│ ├─ 延迟低
│ └─ 适合实时系统
├─ 优势 2: 功耗低
│ ├─ CPU 可以休眠
│ ├─ 事件发生时唤醒
│ ├─ 功耗优化
│ └─ 适合便携设备
├─ 优势 3: 效率高
│ ├─ 无需轮询开销
│ ├─ CPU 可做其他工作
│ ├─ 系统效率高
│ └─ 吞吐量高
└─ 应用场景
├─ 实时数据处理
├─ 事件驱动系统
├─ 低功耗应用
└─ 高性能系统
中断处理的代码示例:
// PS 端中断处理
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
volatile int interrupt_flag = 0;
void interrupt_handler(int sig) {
interrupt_flag = 1;
printf("Received interrupt from PL\n");
}
int main() {
// 注册中断处理函数
signal(SIGUSR1, interrupt_handler);
printf("Waiting for interrupt from PL...\n");
while(1) {
if(interrupt_flag) {
interrupt_flag = 0;
// 处理 PL 的数据
printf("Processing data from PL\n");
// 发送响应给 PL
printf("Sending response to PL\n");
}
sleep(1);
}
return 0;
}
视频处理的 PS-PL 分工:
📊 视频处理应用架构
├─ PS 端职责
│ ├─ 视频输入管理
│ ├─ 帧缓冲管理
│ ├─ 算法参数配置
│ ├─ 结果后处理
│ └─ 显示输出
├─ PL 端职责
│ ├─ 实时图像处理
│ ├─ 高速数据处理
│ ├─ 滤波运算
│ ├─ 特征提取
│ └─ 结果生成
├─ 数据流
│ ├─ 输入:视频帧 (DDR)
│ ├─ 处理:PL 加速
│ ├─ 输出:处理结果 (DDR)
│ └─ 显示:PS 输出
└─ 性能指标
├─ 帧率:30-60fps
├─ 延迟:毫秒级
├─ 吞吐量:高
└─ 功耗:优化
视频处理的数据流:
┌─────────────────────────────────────────────────┐
│ 视频处理应用数据流 │
├─────────────────────────────────────────────────┤
│ │
│ 摄像头 → PS(输入管理) → DDR(输入缓冲) │
│ ↓ │
│ PL(处理) │
│ ↓ │
│ DDR(输出缓冲) │
│ ↓ │
│ PS(后处理) → 显示器 │
│ │
└─────────────────────────────────────────────────┘
实时控制的 PS-PL 分工:
📊 实时控制应用架构
├─ PS 端职责
│ ├─ 控制算法
│ ├─ 参数管理
│ ├─ 日志记录
│ ├─ 通信接口
│ └─ 用户交互
├─ PL 端职责
│ ├─ 实时数据采集
│ ├─ 高速信号处理
│ ├─ 实时反馈控制
│ ├─ 硬件接口
│ └─ 时间同步
├─ 通信方式
│ ├─ 中断驱动
│ ├─ 低延迟
│ ├─ 高实时性
│ └─ 可靠传输
└─ 性能指标
├─ 延迟:微秒级
├─ 抖动:低
├─ 可靠性:高
└─ 功耗:优化
常见问题:
ZYNQ 的启动过程:
📊 ZYNQ 启动流程
├─ 阶段 1: BootROM 阶段
│ ├─ 芯片上电
│ ├─ BootROM 执行
│ ├─ 初始化基本硬件
│ ├─ 加载 FSBL
│ └─ 时间:毫秒级
├─ 阶段 2: FSBL 阶段 (First Stage Boot Loader)
│ ├─ 初始化 PS 系统
│ ├─ 配置 DDR
│ ├─ 加载 PL 比特流
│ ├─ 加载 U-Boot
│ └─ 时间:数百毫秒
├─ 阶段 3: U-Boot 阶段
│ ├─ 初始化外设
│ ├─ 设置网络
│ ├─ 加载 Linux 内核
│ └─ 时间:数秒
└─ 阶段 4: Linux 内核阶段
├─ 启动 Linux 系统
├─ 加载驱动程序
└─ 启动应用程序
启动流程时序图:
上电 → BootROM → FSBL → U-Boot → Linux → 应用
│
│
│
│
│
│
├─ 初始化基本硬件
├─ 初始化 PS
│
│
│
│
│
│
├─ 配置 DDR
│
│
│
│
│
│
├─ 加载 PL
│
│
│
│
│
│
├─ 加载 U-Boot
│
│
│
│
│
│
├─ 初始化外设
│
│
│
│
│
│
├─ 设置网络
│
│
│
│
│
│
├─ 加载内核
│
│
│
│
│
│
├─ 启动系统
│
│
│
│
│
│
├─ 加载驱动
│
│
│
│
│
│
└─ 启动应用
└─ 系统运行
FSBL 的功能:
📊 FSBL(First Stage Boot Loader)
├─ 主要功能
│ ├─ 初始化 PS 系统
│ ├─ 配置 DDR 控制器
│ ├─ 初始化时钟
│ ├─ 配置 PL(加载比特流)
│ ├─ 初始化中断
│ └─ 加载 U-Boot 到 DDR
├─ 执行位置
│ ├─ 存储位置:QSPI Flash 或 SD 卡
│ ├─ 运行位置:OCM(On-Chip Memory)
│ ├─ 大小:通常<256KB
│ └─ 速度:快速
├─ 配置项
│ ├─ DDR 配置
│ ├─ 时钟配置
│ ├─ PL 比特流路径
│ ├─ U-Boot 加载地址
│ └─ 启动设备选择
└─ 生成方式
├─ Xilinx Vitis 自动生成
├─ 基于硬件设计
├─ 可定制修改
└─ 需要重新编译
FSBL 的启动流程:
FSBL 启动流程:
┌─────────────────────────────────────┐
│ 1. 初始化 PS 系统 │
│ ├─ 初始化时钟 │
│ ├─ 初始化中断 │
│ └─ 初始化 UART(调试) │
├─────────────────────────────────────┤
│ 2. 配置 DDR │
│ ├─ 初始化 DDR 控制器 │
│ ├─ 配置 DDR 参数 │
│ └─ 测试 DDR │
├─────────────────────────────────────┤
│ 3. 加载 PL 比特流 │
│ ├─ 从存储设备读取比特流 │
│ ├─ 配置 FPGA │
│ └─ 验证配置 │
├─────────────────────────────────────┤
│ 4. 加载 U-Boot │
│ ├─ 从存储设备读取 U-Boot │
│ ├─ 放入 DDR │
│ └─ 跳转执行 │
└─────────────────────────────────────┘
ZYNQ 的时钟源:
📊 ZYNQ 时钟源
├─ 外部晶振
│ ├─ 频率:33.33MHz
│ ├─ 精度:高
│ ├─ 稳定性:好
│ └─ 用途:系统时钟源
├─ PLL(Phase-Locked Loop)
│ ├─ 数量:2 个
│ ├─ 功能:倍频/分频
│ ├─ 输出:多个时钟
│ └─ 用途:生成各种时钟
├─ MMCM(Mixed-Mode Clock Manager)
│ ├─ 数量:2 个
│ ├─ 功能:高精度时钟管理
│ ├─ 输出:多个时钟
│ └─ 用途:精细时钟调整
└─ 分频器
├─ 数量:多个
├─ 功能:分频
├─ 输出:低频时钟
└─ 用途:外设时钟
ZYNQ 的时钟树:
外部晶振 (33.33MHz)
│
├─ PLL0 ─┬─ ARM 时钟 (1GHz)
│ ├─ DDR 时钟 (533MHz)
│ └─ 其他时钟
├─ PLL1 ─┬─ 外设时钟 (100MHz)
│ ├─ USB 时钟
│ └─ 其他时钟
└─ MMCM ─┬─ PL 时钟 (可配置)
├─ 其他时钟
└─ 相位调整
PS 端时钟配置:
📊 PS 端时钟配置
├─ ARM 时钟
│ ├─ 默认频率:1GHz
│ ├─ 可调范围:100MHz-1GHz
│ ├─ 影响:CPU 性能
│ └─ 配置:FSBL/U-Boot
├─ DDR 时钟
│ ├─ 默认频率:533MHz
│ ├─ 可调范围:有限
│ ├─ 影响:内存性能
│ └─ 配置:FSBL
├─ 外设时钟
│ ├─ 默认频率:100MHz
│ ├─ 可调范围:有限
│ ├─ 影响:外设速率
│ └─ 配置:FSBL/U-Boot
└─ 特殊时钟
├─ USB 时钟:60MHz
├─ UART 时钟:100MHz
├─ SPI 时钟:100MHz
└─ I2C 时钟:100MHz
PL 端时钟配置:
📊 PL 端时钟配置
├─ 时钟来源
│ ├─ 外部时钟输入
│ ├─ PS 时钟输出
│ ├─ PLL/MMCM 生成
│ └─ 用户自定义
├─ 时钟频率
│ ├─ 范围:1MHz-500MHz+
│ ├─ 精度:高
│ ├─ 稳定性:好
│ └─ 可配置
├─ 时钟管理
│ ├─ 全局时钟网络
│ ├─ 区域时钟网络
│ ├─ 本地时钟网络
│ └─ 时钟缓冲
└─ 配置方式
├─ Vivado 设计
├─ IP 核配置
├─ 约束文件
└─ 动态重配置
时钟配置的代码示例:
# Vivado 中配置 ZYNQ 时钟
# 创建时钟约束
create_clock -period 10.000 -name clk_100m [get_ports clk_100m]
# 配置 PLL
create_ip -name clk_wiz -vendor xilinx.com -library ip -version 6.0 -module_name clk_pll
set_property -dict [list \
CONFIG.PRIMITIVE {PLL} \
CONFIG.PRIM_IN_FREQ {100} \
CONFIG.CLKOUT1_REQUESTED_OUT_FREQ {200} \
CONFIG.CLKOUT2_REQUESTED_OUT_FREQ {100} \
] [get_ips clk_pll]
# 配置 MMCM
create_ip -name clk_wiz -vendor xilinx.com -library ip -version 6.0 -module_name clk_mmcm
set_property -dict [list \
CONFIG.PRIMITIVE {MMCM} \
CONFIG.PRIM_IN_FREQ {100} \
CONFIG.CLKOUT1_REQUESTED_OUT_FREQ {150} \
CONFIG.CLKOUT1_REQUESTED_PHASE {0} \
] [get_ips clk_mmcm]
启动流程优化:
时钟系统优化:
通过本文的深入学习,我们已经完整地理解了 ZYNQ PS-PL 架构的各个方面。让我们对关键概念进行总结:
🏗️ ZYNQ SoC 架构三层理解:
第一层 - 物理层
├─ PS(处理系统)
│ ├─ ARM Cortex-A9 双核处理器
│ ├─ 256KB L2 缓存 + 32KB L1 缓存
│ ├─ 存储系统 (OCM + DDR3/DDR4)
│ └─ 丰富的外设接口
├─ PL(可编程逻辑)
│ ├─ LUT/FF/BRAM/DSP 资源
│ ├─ 高速收发器 (GTX/GTP)
│ └─ 时钟管理 (PLL/MMCM)
└─ 互连系统
├─ AXI-GP(通用端口)
├─ AXI-HP(高性能端口)
└─ AXI-ACP(缓存一致性端口)
第二层 - 通信层
├─ AXI 协议
│ ├─ VALID/READY 握手机制
│ ├─ 写通道 (地址/数据/响应)
│ ├─ 读通道 (地址/数据)
│ └─ 突发传输支持
└─ 时钟域同步
├─ CDC 技术
├─ 同步器设计
└─ 亚稳态处理
第三层 - 应用层
├─ PS-PL 协同设计
│ ├─ 硬件加速
│ ├─ 实时控制
│ └─ 数据处理
└─ 软硬件协同
├─ Linux 驱动开发
├─ 设备树配置
└─ 用户空间应用
| 设计方面 | 关键要点 | 注意事项 |
|---|---|---|
| 处理器配置 | 双核 ARM Cortex-A9 | 最高 1GHz 频率 |
| 存储设计 | OCM 用于关键代码 | DDR 用于大数据 |
| 外设选择 | 根据应用需求 | 避免资源冲突 |
| 时钟管理 | PS 时钟固定 | 由 FSBL 配置 |
| 中断处理 | GIC 管理中断 | 优先级配置 |
| 设计方面 | 关键要点 | 注意事项 |
|---|---|---|
| 资源规划 | 合理分配 LUT/BRAM | 避免过度使用 |
| 时钟设计 | 使用 PLL/MMCM | 满足时序要求 |
| 接口设计 | AXI 协议标准 | 握手机制正确 |
| 功耗管理 | 动态功耗控制 | 考虑散热 |
| 可靠性 | 错误检测/纠正 | 关键路径优化 |
| 通信方式 | 适用场景 | 性能指标 |
|---|---|---|
| 轮询 | 低频率数据交互 | 延迟高,CPU 占用高 |
| 中断 | 事件驱动应用 | 延迟低,实时性好 |
| DMA | 大数据块传输 | 吞吐量高,CPU 占用低 |
| 共享内存 | 频繁数据交互 | 延迟最低,需同步 |
应用架构:
┌─────────────────────────────────────┐
│ Linux 应用 (PS) │
│ ├─ 视频编码/解码控制 │
│ ├─ 用户界面 │
│ └─ 文件管理 │
└────────────┬────────────────────────┘
│ AXI-HP
┌────────────▼────────────────────────┐
│ 视频处理加速器 (PL) │
│ ├─ 图像缩放 │
│ ├─ 色彩空间转换 │
│ ├─ 滤波处理 │
│ └─ 编码加速 │
└─────────────────────────────────────┘
性能指标:
- 吞吐量:1080p@60fps
- 延迟:<50ms
- 功耗:<5W
应用架构:
┌─────────────────────────────────────┐
│ 实时控制应用 (PS) │
│ ├─ 控制算法 │
│ ├─ 状态机 │
│ └─ 通信协议 │
└────────────┬────────────────────────┘
│ AXI-GP + 中断
┌────────────▼────────────────────────┐
│ 硬件控制接口 (PL) │
│ ├─ PWM 生成 │
│ ├─ 传感器采集 │
│ ├─ 实时反馈 │
│ └─ 故障检测 │
└─────────────────────────────────────┘
性能指标:
- 控制周期:1ms
- 响应延迟:<100μs
- 可靠性:99.99%
应用架构:
┌─────────────────────────────────────┐
│ 数据处理应用 (PS) │
│ ├─ 数据存储 │
│ ├─ 算法处理 │
│ └─ 网络传输 │
└────────────┬────────────────────────┘
│ AXI-HP + DMA
┌────────────▼────────────────────────┐
│ 数据采集加速器 (PL) │
│ ├─ 多通道采集 │
│ ├─ 实时滤波 │
│ ├─ 数据压缩 │
│ └─ 缓冲管理 │
└─────────────────────────────────────┘
性能指标:
- 采样率:100MSPS
- 通道数:16
- 吞吐量:1.6GB/s
✅ 必做事项:
❌ 避免事项:
✅ 必做事项:
❌ 避免事项:
✅ 必做事项:
❌ 避免事项:
初级阶段 (1-2 周)
├─ 理解 PS-PL 基本概念
├─ 学习 AXI 协议基础
├─ 完成简单的 Hello World 项目
└─ 目标:能够理解基本架构
中级阶段 (2-4 周)
├─ 深入学习 AXI 协议
├─ 掌握时钟域同步技术
├─ 完成 PS-PL 通信项目
└─ 目标:能够设计简单的 PS-PL 系统
高级阶段 (4-8 周)
├─ 学习高级优化技术
├─ 掌握 DMA 和中断处理
├─ 完成复杂的应用项目
└─ 目标:能够设计高性能系统
专家阶段 (8 周+)
├─ 研究前沿技术
├─ 优化系统性能
├─ 参与开源项目
└─ 目标:成为领域专家
官方文档:
学习资源:
社区资源:
Q1: PS 和 PL 应该如何划分功能?
A: 遵循以下原则:
Q2: 如何优化 PS-PL 通信性能?
A: 采用以下策略:
Q3: 时钟域同步为什么重要?
A: 因为:
Q4: 如何调试 PS-PL 系统?
A: 使用以下工具:
Q5: ZYNQ 适合哪些应用?
A: 适合以下应用:
ZYNQ PS-PL 架构代表了现代嵌入式系统设计的发展方向,它完美地结合了 ARM 处理器的灵活性和 FPGA 的性能优势。通过本文的学习,您已经掌握了:
下一步建议:
希望本文能够帮助您深入理解 ZYNQ PS-PL 架构,为您的嵌入式系统设计之路提供坚实的基础!

微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online
将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML 转 Markdown 互为补充。 在线工具,Markdown 转 HTML在线工具,online
将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML 转 Markdown在线工具,online
通过删除不必要的空白来缩小和压缩JSON。 在线工具,JSON 压缩在线工具,online