跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客我的书AI学习GitHub 精选镜像AI 生图工具UI配色美学关于
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
C算法

ZYNQ PS-PL 架构解析:ARM 与 FPGA 融合设计及通信机制

ZYNQ 是 Xilinx 推出的 SoC 产品,将 ARM 处理器与 FPGA 融合。文章详细解析了 PS(处理系统)和 PL(可编程逻辑)的架构、组成及优势。PS 端包含双核 ARM Cortex-A9、存储系统及外设接口;PL 端提供 LUT、BRAM、DSP 等逻辑资源。重点阐述了 PS-PL 互联技术,基于 AXI 总线协议,包括 GP、HP、ACP 接口特性及带宽对比。介绍了 AXI 握手机制、通道结构、突发传输及错误处理。通过 DDR 访问、共享内存、中断驱动等实战案例展示了数据交互方法。最后总结了启动流程、时钟系统及最佳实践,适用于视频处理、实时控制等场景。

灰度发布发布于 2026/4/6更新于 2026/9/978 浏览

概述

ZYNQ 是 Xilinx 推出的革命性 SoC(System on Chip) 产品,它首次将高性能 ARM 处理器与 FPGA 完美融合在一个芯片上。这种融合设计打破了传统 FPGA 和处理器的界限,为嵌入式系统设计带来了全新的可能性。

ZYNQ 的核心价值:

  • 充分发挥 ARM 处理器的控制能力和 FPGA 的并行计算能力
  • 实现硬件和软件的完美协同
  • 降低系统成本和功耗
  • 加快产品上市时间

本文将帮助您:

  1. 深入理解 PS 和 PL 的概念及其各自的特点
  2. 掌握 ZYNQ 的基本架构和组成部分
  3. 理解 PS-PL 之间的通信机制
  4. 学会设计 PS-PL 协同工作的系统
  5. 通过实战案例巩固理论知识

一、PS-PL 架构基础概念

1.1 什么是 PS 和 PL

在 ZYNQ 芯片中,有两个核心概念需要理解:PS(Processing System) 和 PL(Programmable Logic)。

1.1.1 PS(处理系统) 定义

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 的特点:

  • 🔧 硬核处理器:不占用 FPGA 逻辑资源
  • ⚡ 高性能:ARM Cortex-A9 可运行完整操作系统 (Linux/RTOS)
  • 🎯 专用设计:针对控制和串行处理优化
  • 📦 集成丰富:包含完整的外设和存储接口
1.1.2 PL(可编程逻辑) 定义

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 的特点:

  • 🔄 可重构:可根据需要动态配置
  • ⚙️ 并行处理:天生支持并行计算
  • 🚀 高吞吐量:适合数据流处理
  • 🎨 灵活性:可实现任意数字逻辑功能
1.1.3 PS vs PL 对比
特性PS(处理系统)PL(可编程逻辑)
处理方式串行处理并行处理
适用场景控制、算法、OS数据处理、加速
资源占用硬核,不占用逻辑占用 FPGA 逻辑资源
时钟频率最高 1GHz最高 500MHz+
功耗相对较低可配置
开发语言C/C++/汇编Verilog/VHDL
启动时间毫秒级需要配置
可重构性固定动态可重构

1.2 ZYNQ 基本结构
1.2.1 ZYNQ-7000 系列架构

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 的关键特性:

# 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 │ └─────────────────┴──────────┴──────────┴──────────┘ 
1.2.2 ZYNQ-7000 的整体架构
┌─────────────────────────────────────────────────────┐ │ ZYNQ-7000 SoC │ ├─────────────────────────────────────────────────────┤ │ │ │ ┌──────────────────────┐ ┌──────────────────────┐ │ │ │ PS(处理系统) │ │ PL(可编程逻辑) │ │ │ │ │ │ │ │ │ │ ┌────────────────┐ │ │ ┌────────────────┐ │ │ │ │ │ ARM Cortex-A9 │ │ │ │ FPGA 逻辑 │ │ │ │ │ │ (双核) │ │ │ │ (LUT/FF) │ │ │ │ │ └────────────────┘ │ │ └────────────────┘ │ │ │ │ │ │ │ │ │ │ ┌────────────────┐ │ │ ┌────────────────┐ │ │ │ │ │ DDR 控制器 │ │ │ │ Block RAM │ │ │ │ │ │ 存储管理 │ │ │ │ DSP48E1 │ │ │ │ │ └────────────────┘ │ │ └────────────────┘ │ │ │ │ │ │ │ │ │ │ ┌────────────────┐ │ │ ┌────────────────┐ │ │ │ │ │ 外设接口 │ │ │ │ 高速收发器 │ │ │ │ │ │ (USB/ETH/SPI) │ │ │ │ (GTX/GTP) │ │ │ │ │ └────────────────┘ │ │ └────────────────┘ │ │ │ │ │ │ │ │ │ └──────────────────────┘ └──────────────────────┘ │ │ │ │ │ │ └──────────────────────────┘ │ │ AXI 互连 │ │ │ └─────────────────────────────────────────────────────┘ 

1.3 为什么需要 PS-PL 架构
1.3.1 传统 FPGA 的局限性

纯 FPGA 设计的问题:

❌ 问题 1: 资源浪费 - 处理器功能占用大量 FPGA 逻辑资源 - 软核处理器 (MicroBlaze) 性能有限 - 成本高,功耗大 ❌ 问题 2: 性能瓶颈 - 软核处理器频率低 (100-200MHz) - 无法运行复杂操作系统 - 难以处理复杂控制逻辑 ❌ 问题 3: 开发效率低 - 所有功能都需要用 HDL 实现 - 开发周期长 - 调试困难 ❌ 问题 4: 集成度低 - 需要外接处理器芯片 - 系统复杂度高 - 可靠性降低 
1.3.2 PS-PL 架构的优势

ZYNQ 融合设计的优点:

✅ 优势 1: 性能优化 - ARM 处理器频率高 (1GHz) - 可运行 Linux/RTOS 等完整 OS - FPGA 提供并行加速 ✅ 优势 2: 资源高效 - 硬核处理器不占用 FPGA 资源 - FPGA 资源专注于加速功能 - 成本更低 ✅ 优势 3: 开发效率高 - 控制逻辑用 C/C++ 实现 - 加速功能用 HDL 实现 - 充分利用各自优势 ✅ 优势 4: 集成度高 - 单芯片集成 - 系统简洁 - 可靠性高 
1.3.3 应用场景分析

PS-PL 架构适用的典型应用:

📱 消费电子 ├─ 智能摄像头 (视频处理 + 控制) ├─ 无人机 (图像识别 + 飞控) └─ 智能家居 (多传感器融合) 🏭 工业控制 ├─ 实时控制系统 ├─ 机器视觉 └─ 工业网关 📡 通信设备 ├─ 基站处理 ├─ 网络加速 └─ 信号处理 🎮 多媒体 ├─ 视频编解码 ├─ 图像处理 └─ 音频处理 🔬 科研仪器 ├─ 高速数据采集 ├─ 实时信号处理 └─ 科学计算加速 

1.4 PS-PL 架构的优势
1.4.1 性能优势

PS-PL 协同的性能提升:

性能对比示例:┌──────────────────┬─────────┬─────────┬──────────┐ │ 任务类型 │ 纯 CPU │ 纯 FPGA │ PS+PL │ ├──────────────────┼─────────┼─────────┼──────────┤ │ 控制逻辑 │ 100% │ 50% │ 100% │ │ 数据处理 │ 50% │ 100% │ 100% │ │ 综合性能 │ 60% │ 70% │ 95%+ │ │ 功耗效率 │ 中等 │ 高 │ 最高 │ └──────────────────┴─────────┴─────────┴──────────┘ 
1.4.2 成本优势

系统成本对比:

成本分析:┌──────────────────┬──────────┬──────────┬──────────┐ │ 指标 │ CPU+FPGA │ 纯 FPGA │ ZYNQ │ ├──────────────────┼──────────┼──────────┼──────────┤ │ 芯片成本 │ 高 │ 中等 │ 低 │ │ PCB 面积 │ 大 │ 中等 │ 小 │ │ 功耗 │ 高 │ 中等 │ 低 │ │ 集成度 │ 低 │ 中等 │ 高 │ │ 总体成本 │ 最高 │ 中等 │ 最低 │ └──────────────────┴──────────┴──────────┴──────────┘ 
1.4.3 开发效率优势

开发周期对比:

开发效率分析:┌──────────────────┬──────────┬──────────┬──────────┐ │ 开发阶段 │ CPU+FPGA │ 纯 FPGA │ ZYNQ │ ├──────────────────┼──────────┼──────────┼──────────┤ │ 硬件设计 │ 复杂 │ 中等 │ 简单 │ │ 软件开发 │ 标准 │ 困难 │ 标准 │ │ 集成测试 │ 困难 │ 困难 │ 相对简单 │ │ 总开发周期 │ 长 │ 长 │ 短 │ │ 维护成本 │ 高 │ 中等 │ 低 │ └──────────────────┴──────────┴──────────┴──────────┘ 

💡 关键要点总结:

  1. PS 是硬核处理器系统,包含 ARM Cortex-A9、存储、外设等
  2. PL 是可编程逻辑部分,基于 Xilinx 7 系列 FPGA
  3. PS-PL 架构的核心优势是充分发挥各自特点,实现最优性能
  4. 应用场景广泛,从消费电子到工业控制都有应用
  5. 开发效率高,可用 C/C++ 和 HDL 分别开发

二、PS 端详解

2.1 应用处理单元 (APU)
2.1.1 ARM Cortex-A9 处理器

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) └─ 中断控制器 

双核架构的优势:

✅ 优势 1: 并行处理 - 两个核可独立执行不同任务 - 充分利用多核处理能力 - 提高系统吞吐量 ✅ 优势 2: 灵活配置 - 可运行同一 OS 的两个实例 - 可运行不同 OS(如 Linux+RTOS) - 支持核间通信 ✅ 优势 3: 可靠性 - 一个核故障不影响另一个 - 支持热插拔 - 提高系统可用性 
2.1.2 NEON 媒体处理引擎

NEON 的功能:

NEON 是 ARM Cortex-A9 的一个协处理器,实现单指令多数据 (SIMD) 功能。

📊 NEON 处理引擎特性 │ ├─ 数据类型支持 │ ├─ 8 位整数 │ ├─ 16 位整数 │ ├─ 32 位整数 │ ├─ 64 位整数 │ └─ 32 位浮点 │ ├─ 寄存器组 │ ├─ 16 个 128 位寄存器 │ ├─ 可视为 32 个 64 位寄存器 │ └─ 可视为 64 个 32 位寄存器 │ ├─ 指令集 │ ├─ 算术运算 (加、减、乘) │ ├─ 逻辑运算 (与、或、非) │ ├─ 移位运算 │ ├─ 比较运算 │ └─ 数据转换 │ └─ 应用场景 ├─ 图像处理 ├─ 视频编解码 ├─ 音频处理 ├─ 信号处理 └─ 科学计算 

NEON 性能示例:

性能对比 (以 128 位操作为例):┌──────────────────┬──────────┬──────────┐ │ 操作类型 │ 标准 ARM │ NEON │ ├──────────────────┼──────────┼──────────┤ │ 8 位加法 │ 1 次/周期 │ 16 次/周期│ │ 16 位乘法 │ 1 次/周期 │ 8 次/周期 │ │ 32 位乘法 │ 1 次/周期 │ 4 次/周期 │ │ 性能提升 │ 基准 │ 4-16 倍 │ └──────────────────┴──────────┴──────────┘ 
2.1.3 浮点单元 (FPU)

FPU 的功能:

浮点单元支持 IEEE 754 标准的浮点运算。

📊 FPU 特性 │ ├─ 支持的数据类型 │ ├─ 单精度浮点 (32 位) │ ├─ 双精度浮点 (64 位) │ └─ 特殊值 (NaN, Inf) │ ├─ 支持的运算 │ ├─ 加法/减法 │ ├─ 乘法/除法 │ ├─ 平方根 │ ├─ 比较 │ └─ 转换 │ └─ 性能指标 ├─ 单精度:1 GFLOPS ├─ 双精度:0.5 GFLOPS └─ 吞吐量:1 个操作/周期 

2.2 存储系统
2.2.1 片内存储 (OCM)

OCM(On-Chip Memory) 的特点:

📊 OCM 存储结构 │ ├─ 容量 │ ├─ 总容量:256KB │ ├─ 分为两个 128KB 块 │ └─ 可配置为指令/数据存储 │ ├─ 特性 │ ├─ 低延迟:1-2 个周期 │ ├─ 高带宽:64 位/周期 │ ├─ 低功耗:相对 DDR │ └─ 可靠性:支持 ECC │ ├─ 用途 │ ├─ 启动代码存储 │ ├─ 实时关键代码 │ ├─ 中断处理程序 │ └─ 高速缓存 │ └─ 访问方式 ├─ ARM 处理器直接访问 ├─ PL 通过 AXI 访问 └─ DMA 访问 

OCM 的应用场景:

✅ 最佳实践:1. 启动代码 (FSBL) 存储在 OCM 2. 实时中断处理程序放在 OCM 3. 高频访问的数据放在 OCM 4. 关键算法代码放在 OCM ❌ 不适合:1. 大数据缓存 (容量有限) 2. 低优先级代码 3. 不经常访问的数据 
2.2.2 外部 DDR 存储

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 都可访问 │ │ (用于数据交互) │ │ │ └─────────────────────────────────────┘ 

2.3 外设接口
2.3.1 通信接口

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 └─ 应用:工业控制、汽车 
2.3.2 低速接口

低速接口特性:

📊 低速接口 │ ├─ 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、按钮、传感器 

2.4 中断和时钟管理
2.4.1 中断系统

ZYNQ 的中断架构:

📊 中断系统结构 │ ├─ 中断源 │ ├─ 外设中断 (32 个) │ ├─ PL 中断 (16 个) │ ├─ SGI(软件生成中断) │ └─ PPI(私有外设中断) │ ├─ 中断控制器 (GIC) │ ├─ 通用中断控制器 │ ├─ 支持优先级 │ ├─ 支持中断分配 │ └─ 支持中断屏蔽 │ └─ 中断处理 ├─ ARM 处理器响应 ├─ 中断向量表 ├─ 中断服务程序 (ISR) └─ 中断返回 
2.4.2 时钟管理

ZYNQ 的时钟系统:

📊 时钟管理系统 │ ├─ 时钟源 │ ├─ 外部晶振 (33.33MHz) │ ├─ PLL 倍频 │ └─ 分频器 │ ├─ 主要时钟 │ ├─ ARM 时钟:最高 1GHz │ ├─ DDR 时钟:533MHz │ ├─ 外设时钟:100MHz │ └─ PL 时钟:可配置 │ ├─ 时钟管理功能 │ ├─ 动态频率调整 │ ├─ 时钟门控 │ ├─ 功率管理 │ └─ 时钟监测 │ └─ 应用 ├─ 功耗优化 ├─ 性能调整 ├─ 热管理 └─ 功率管理 

2.5 PS 端的软件支持
2.5.1 操作系统支持

ZYNQ 支持的操作系统:

📊 操作系统支持 │ ├─ Linux │ ├─ Xilinx Linux(基于 Yocto) │ ├─ Ubuntu ARM 版本 │ ├─ Debian ARM 版本 │ └─ 其他发行版 │ ├─ 实时操作系统 (RTOS) │ ├─ FreeRTOS │ ├─ Xilinx RTOSes │ ├─ QNX │ └─ VxWorks │ ├─ 裸机 (Bare Metal) │ ├─ 无 OS 运行 │ ├─ 最小化开销 │ ├─ 最高实时性 │ └─ 适合简单应用 │ └─ 混合模式 ├─ 一个核运行 Linux ├─ 另一个核运行 RTOS ├─ 核间通信 └─ 最大灵活性 
2.5.2 开发工具

ZYNQ 开发工具链:

📊 开发工具 │ ├─ Xilinx Vitis │ ├─ 统一开发环境 │ ├─ C/C++ 编译器 │ ├─ 调试工具 │ └─ 性能分析 │ ├─ Xilinx SDK(已弃用) │ ├─ 旧版开发环境 │ ├─ 仍可使用 │ └─ 逐步迁移到 Vitis │ ├─ 编译工具 │ ├─ ARM GCC 编译器 │ ├─ Linaro 工具链 │ └─ 第三方编译器 │ └─ 调试工具 ├─ JTAG 调试器 ├─ 串口调试 ├─ 性能分析工具 └─ 内存分析工具 

💡 关键要点总结:

  1. APU 是 PS 的核心,包含双核 ARM Cortex-A9 处理器
  2. NEON 引擎提供 SIMD 加速,适合媒体处理
  3. OCM 提供低延迟存储,适合启动代码和实时代码
  4. DDR 提供大容量存储,用于应用程序和数据
  5. 丰富的外设接口支持各种通信和控制应用
  6. 灵活的操作系统支持,可运行 Linux 或 RTOS

三、PL 端详解

3.1 逻辑资源
3.1.1 查找表 (LUT)

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
3.1.2 触发器 (FF)

触发器的特性:

📊 触发器 (Flip-Flop) 特性 │ ├─ 类型 │ ├─ D 触发器 (主要) │ ├─ SR 触发器 │ ├─ 异步复位 │ └─ 异步置位 │ ├─ 特点 │ ├─ 每个 LUT 配套一个 FF │ ├─ 可选择使用 │ ├─ 支持异步复位/置位 │ └─ 支持时钟使能 │ ├─ 应用 │ ├─ 时序逻辑实现 │ ├─ 寄存器设计 │ ├─ 状态机 │ └─ 流水线 │ └─ 性能 ├─ 最大频率:500MHz+ ├─ 建立时间:极短 ├─ 保持时间:极短 └─ 功耗:低 
3.1.3 多路选择器 (MUX)

MUX 的功能:

📊 多路选择器 │ ├─ 功能 │ ├─ 数据选择 │ ├─ 路由控制 │ ├─ 条件分支 │ └─ 优先级编码 │ ├─ 集成位置 │ ├─ CLB(可配置逻辑块) 内 │ ├─ 与 LUT 集成 │ ├─ 与 FF 集成 │ └─ 高速互连 │ ├─ 应用场景 │ ├─ 数据通路选择 │ ├─ 控制信号路由 │ ├─ 条件执行 │ └─ 优先级处理 │ └─ 性能 ├─ 延迟:0.2-0.5ns ├─ 功耗:极低 ├─ 集成度:高 └─ 灵活性:强 

3.2 存储资源
3.2.1 Block RAM(BRAM)

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
3.2.2 分布式 RAM

分布式 RAM 的特点:

📊 分布式 RAM 特性 │ ├─ 实现方式 │ ├─ 使用 LUT 实现 │ ├─ 每个 LUT 可作为 64x1 RAM │ ├─ 多个 LUT 级联 │ └─ 灵活配置 │ ├─ 容量 │ ├─ 小容量:64-512 字节 │ ├─ 灵活配置 │ ├─ 不占用 BRAM │ └─ 节省资源 │ ├─ 特性 │ ├─ 低延迟:1 个周期 │ ├─ 高速访问 │ ├─ 灵活宽度 │ └─ 功耗低 │ ├─ 应用 │ ├─ 小型缓存 │ ├─ 寄存器堆 │ ├─ 移位寄存器 │ └─ 临时存储 │ └─ 对比 BRAM ├─ 容量:BRAM 更大 ├─ 延迟:分布式更低 ├─ 资源:分布式占用 LUT └─ 成本:分布式更灵活 

3.3 计算资源
3.3.1 DSP48E1 切片

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
3.3.2 乘法器和累加器

乘法器特性:

📊 乘法器特性 │ ├─ 支持的运算 │ ├─ 有符号乘法 │ ├─ 无符号乘法 │ ├─ 混合乘法 │ └─ 级联乘法 │ ├─ 精度 │ ├─ 25x18 位 = 43 位结果 │ ├─ 支持更高精度级联 │ ├─ 精度可配置 │ └─ 支持舍入 │ ├─ 性能 │ ├─ 单周期乘法 │ ├─ 流水线支持 │ ├─ 高吞吐量 │ └─ 低延迟 │ └─ 应用 ├─ 数字滤波器 ├─ 相关运算 ├─ 卷积运算 └─ 矩阵乘法 

3.4 高速接口
3.4.1 高速收发器 (GTX/GTP)

高速收发器的特性:

📊 高速收发器特性 │ ├─ 类型 │ ├─ 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 │ └─ 自定义协议 │ └─ 应用 ├─ 高速数据传输 ├─ 网络通信 ├─ 视频传输 └─ 系统互连 
3.4.2 PCIe 接口

PCIe 的功能:

📊 PCIe 接口特性 │ ├─ 版本支持 │ ├─ PCIe 2.0(5 Gbps) │ ├─ PCIe 3.0(8 Gbps) │ ├─ 向后兼容 │ └─ 可配置 │ ├─ 功能 │ ├─ 主设备模式 │ ├─ 从设备模式 │ ├─ 双向通信 │ └─ DMA 支持 │ ├─ 应用 │ ├─ 与 PC 通信 │ ├─ 高速数据传输 │ ├─ 系统扩展 │ └─ 加速卡设计 │ └─ 性能 ├─ 带宽:高 ├─ 延迟:低 ├─ 可靠性:高 └─ 易用性:好 

3.5 时钟资源
3.5.1 全局时钟网络

时钟网络的特性:

📊 全局时钟网络 │ ├─ 时钟类型 │ ├─ 全局时钟 (GCLK) │ ├─ 区域时钟 (RCLK) │ ├─ 本地时钟 (LCLK) │ └─ 专用时钟 │ ├─ 特点 │ ├─ 低延迟 │ ├─ 低抖动 │ ├─ 高扇出 │ └─ 低功耗 │ ├─ 数量 │ ├─ 全局时钟:32 个 │ ├─ 区域时钟:多个 │ ├─ 灵活配置 │ └─ 充分冗余 │ └─ 应用 ├─ 系统时钟 ├─ 模块时钟 ├─ 采样时钟 └─ 同步时钟 
3.5.2 PLL 和 MMCM

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

3.6 PL 资源对比与选型

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 │ └──────────────────┴──────────┴──────────┴──────────┘ 

资源选型建议:

✅ Z-7010 适用场景:
- 入门学习项目
- 简单控制应用
- 低成本产品
- 原型验证

✅ Z-7020 适用场景:
- 中等复杂度应用
- 图像处理 (低分辨率)
- 信号处理
- 大多数工业应用

✅ Z-7045 适用场景:
- 高性能应用
- 高分辨率视频处理
- 复杂信号处理
- 高端产品 

💡 关键要点总结:

  1. LUT 是 FPGA 的基本逻辑单元,可实现任意 6 输入逻辑函数
  2. BRAM 提供大容量存储,支持多种工作模式
  3. DSP48E1 提供高速计算,适合信号处理和数据处理
  4. 高速收发器支持多种协议,用于高速通信
  5. 时钟资源丰富,支持灵活的时钟管理
  6. 不同型号资源差异大,需根据应用选择合适型号

四、PS-PL 互联技术

4.1 AXI 互连架构
4.1.1 AXI 总线概述

AXI(Advanced eXtensible Interface) 的定义:

AXI 是 ARM 推出的高性能、低延迟的片上互连标准,是 ZYNQ 中 PS 和 PL 通信的核心。

📊 AXI 互连架构 │ ├─ 设计目标 │ ├─ 高带宽 │ ├─ 低延迟 │ ├─ 可扩展性 │ └─ 灵活性 │ ├─ 核心特性 │ ├─ 分离的读写通道 │ ├─ 支持乱序完成 │ ├─ 支持突发传输 │ ├─ 支持多个主设备 │ └─ 支持多个从设备 │ ├─ 版本 │ ├─ AXI3(32 位/64 位) │ ├─ AXI4(128 位) │ ├─ AXI4-Lite(简化版) │ └─ AXI4-Stream(流式) │ └─ 应用 ├─ PS-PL 通信 ├─ 高速数据传输 ├─ 实时系统 └─ 多主多从系统 
4.1.2 AXI 互连的拓扑

ZYNQ-7000 的 AXI 互连拓扑:

┌─────────────────────────────────────────────────────┐ │ ZYNQ-7000 AXI 互连拓扑 │ ├─────────────────────────────────────────────────────┤ │ │ │ ┌──────────────────┐ ┌──────────────────┐ │ │ │ PS(主设备) │ │ PL(从设备) │ │ │ │ │ │ │ │ │ │ ┌──────────────┐ │ │ ┌──────────────┐ │ │ │ │ │ AXI-GP0 │ │ │ │ 用户 IP 核 │ │ │ │ │ │ (通用端口 0) │ │ │ │ │ │ │ │ │ └──────────────┘ │ │ └──────────────┘ │ │ │ │ │ │ │ │ │ │ │ │ ┌──────────────┐ │ │ ┌──────────────┐ │ │ │ │ │ AXI-GP1 │ │ │ │ 用户 IP 核 │ │ │ │ │ │ (通用端口 1) │ │ │ │ │ │ │ │ │ └──────────────┘ │ │ └──────────────┘ │ │ │ │ │ │ │ │ │ │ │ │ ┌──────────────┐ │ │ ┌──────────────┐ │ │ │ │ │ AXI-HP0-3 │ │ │ │ 用户 IP 核 │ │ │ │ │ │ (高性能端口) │ │ │ │ │ │ │ │ │ └──────────────┘ │ │ └──────────────┘ │ │ │ │ │ │ │ │ │ │ │ │ ┌──────────────┐ │ │ ┌──────────────┐ │ │ │ │ │ AXI-ACP │ │ │ │ 用户 IP 核 │ │ │ │ │ │ (缓存一致) │ │ │ │ │ │ │ │ │ └──────────────┘ │ │ └──────────────┘ │ │ │ │ │ │ │ │ │ └──────────────────┘ └──────────────────┘ │ │ │ │ │ │ └─────────────────────────┘ │ │ AXI 互连矩阵 │ │ │ └─────────────────────────────────────────────────────┘ 

4.2 PS-PL 的 9 个物理接口
4.2.1 AXI-GP 接口 (通用端口)

AXI-GP 的特性:

📊 AXI-GP 接口特性 │ ├─ 接口数量 │ ├─ AXI-GP0: 1 个 │ ├─ AXI-GP1: 1 个 │ └─ 总计:2 个 │ ├─ 数据宽度 │ ├─ 地址总线:32 位 │ ├─ 数据总线:32 位 │ ├─ 支持突发 │ └─ 支持乱序 │ ├─ 性能指标 │ ├─ 最大频率:100MHz │ ├─ 理论带宽:400MB/s │ ├─ 延迟:中等 │ └─ 功耗:低 │ ├─ 应用场景 │ ├─ 控制信号传输 │ ├─ 配置数据传输 │ ├─ 低速数据交互 │ └─ 中等带宽应用 │ └─ 特点 ├─ 易于使用 ├─ 功耗低 ├─ 适合控制类应用 └─ 不适合高速数据 
4.2.2 AXI-HP 接口 (高性能端口)

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 访问 │ └─ 特点 ├─ 高带宽 ├─ 低延迟 ├─ 支持多个端口 ├─ 适合数据处理 └─ 功耗相对较高 
4.2.3 AXI-ACP 接口 (缓存一致性端口)

AXI-ACP 的特性:

📊 AXI-ACP 接口特性 │ ├─ 接口数量 │ ├─ AXI-ACP: 1 个 │ └─ 总计:1 个 │ ├─ 数据宽度 │ ├─ 地址总线:32 位 │ ├─ 数据总线:64 位 │ ├─ 支持突发 │ └─ 支持乱序 │ ├─ 核心特性 │ ├─ 缓存一致性 │ ├─ 与 ARM L2 缓存一致 │ ├─ 自动缓存管理 │ └─ 无需软件干预 │ ├─ 性能指标 │ ├─ 最大频率:150MHz │ ├─ 理论带宽:1.2GB/s │ ├─ 延迟:低 │ └─ 功耗:中等 │ ├─ 应用场景 │ ├─ 共享内存访问 │ ├─ 缓存一致的数据交互 │ ├─ 多核协同处理 │ ├─ 实时系统 │ └─ 高可靠性应用 │ └─ 特点 ├─ 自动缓存一致性 ├─ 无需软件管理 ├─ 性能最优 ├─ 适合共享数据 └─ 功耗相对较高 

4.3 PS-PL 接口带宽对比

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 │ └──────────────────┴──────────┴──────────┴──────────┘ 

实际应用中的带宽利用:

✅ 最优实践:1. 高速数据传输使用 AXI-HP 2. 控制信号使用 AXI-GP 3. 共享内存使用 AXI-ACP 4. 合理分配多个 AXI-HP 端口 5. 避免单个端口过载 ❌ 常见误区:1. 所有数据都用 AXI-GP(带宽不足) 2. 忽视缓存一致性问题 3. 不合理的突发长度配置 4. 未充分利用多个端口 5. 忽视时钟域同步 

4.4 PS-PL 通信的关键考虑
4.4.1 地址映射

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 外设访问 │ └─ 特点 ├─ 统一地址空间 ├─ 易于编程 ├─ 支持虚拟地址 └─ 需要正确配置 
4.4.2 时钟域同步

PS-PL 时钟域:

📊 时钟域管理 │ ├─ PS 时钟 │ ├─ ARM 时钟:1GHz │ ├─ DDR 时钟:533MHz │ ├─ 外设时钟:100MHz │ └─ 固定频率 │ ├─ PL 时钟 │ ├─ 用户可配置 │ ├─ 通常 100-200MHz │ ├─ 可动态调整 │ └─ 独立时钟域 │ ├─ 时钟同步 │ ├─ 使用 CDC(Clock Domain Crossing) │ ├─ 使用同步器 │ ├─ 避免亚稳态 │ └─ 关键设计 │ └─ 最佳实践 ├─ 使用握手信号 ├─ 使用 FIFO 缓冲 ├─ 避免直接跨域 └─ 充分测试 

4.5 PS-PL 互联的实现方式

PS-PL 通信的三种主要方式:

📊 PS-PL 通信方式 │ ├─ 方式 1: 轮询 (Polling) │ ├─ PS 定期读取 PL 状态 │ ├─ 简单易实现 │ ├─ CPU 占用率高 │ ├─ 延迟不确定 │ └─ 适合低频应用 │ ├─ 方式 2: 中断 (Interrupt) │ ├─ PL 产生中断信号 │ ├─ PS 响应中断 │ ├─ CPU 占用率低 │ ├─ 延迟低 │ └─ 适合实时应用 │ └─ 方式 3: DMA(Direct Memory Access) ├─ 直接内存访问 ├─ 无需 CPU 干预 ├─ 吞吐量最高 ├─ 延迟最低 └─ 适合高速数据传输 

通信方式对比:

┌──────────────────┬──────────┬──────────┬──────────┐ │ 特性 │ 轮询 │ 中断 │ DMA │ ├──────────────────┼──────────┼──────────┼──────────┤ │ CPU 占用率 │ 高 │ 低 │ 极低 │ │ 延迟 │ 不确定 │ 低 │ 极低 │ │ 吞吐量 │ 低 │ 中等 │ 高 │ │ 实现复杂度 │ 低 │ 中等 │ 高 │ │ 功耗 │ 高 │ 中等 │ 低 │ │ 适用场景 │ 低频 │ 实时 │ 高速 │ └──────────────────┴──────────┴──────────┴──────────┘ 

💡 关键要点总结:

  1. AXI 是 PS-PL 通信的核心,提供高带宽、低延迟的互连
  2. AXI-GP 适合控制类应用,带宽 400MB/s
  3. AXI-HP 适合数据处理,单端口带宽 1.2GB/s
  4. AXI-ACP 提供缓存一致性,自动管理缓存
  5. 合理选择通信方式,轮询/中断/DMA 各有优缺点
  6. 时钟域同步很关键,需要使用 CDC 技术

五、AXI 接口协议详解

5.1 AXI 握手机制
5.1.1 VALID/READY 握手

握手机制的基本原理:

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 都为高,握手完成 
5.1.2 握手的应用场景

不同场景下的握手:

📊 握手场景分析 │ ├─ 场景 1: 发送方快速,接收方快速 │ ├─ VALID 和 READY 都持续为高 │ ├─ 每个周期都发生握手 │ ├─ 最高效率 │ └─ 理想情况 │ ├─ 场景 2: 发送方快速,接收方慢速 │ ├─ READY 间歇性为低 │ ├─ 发送方需要等待 │ ├─ 流控生效 │ └─ 常见情况 │ ├─ 场景 3: 发送方慢速,接收方快速 │ ├─ VALID 间歇性为低 │ ├─ 接收方等待数据 │ ├─ 接收方空闲 │ └─ 常见情况 │ └─ 场景 4: 发送方和接收方都慢速 ├─ VALID 和 READY 都间歇性为低 ├─ 握手不频繁 ├─ 系统效率低 └─ 需要优化 

5.2 AXI 通道结构
5.2.1 写通道 (Write Channel)

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: 接收写响应 
5.2.2 读通道 (Read Channel)

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 个周期 

5.3 AXI 数据传输
5.3.1 突发传输 (Burst Transfer)

突发传输的特性:

📊 突发传输特性 │ ├─ 突发长度 (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 │ │ │ │ │ │ 地址:─┐ ┌─────┐ ┌─────┐ ┌─ │└────┘ └────┘ └────┘ │ 数据:─┐ ┌─────┬─────┬─────┬─────┐ │└────┘ │ │ │ │ │ └─────┴─────┴─────┘ 
5.3.2 写使能 (Write Strobe)

写使能的功能:

📊 写使能 (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: 不写入任何字节 │ └─ 应用 ├─ 部分数据更新 ├─ 灵活的数据操作 ├─ 提高效率 └─ 减少带宽浪费 

5.4 AXI 错误处理
5.4.1 响应状态 (Response)

AXI 响应状态:

📊 AXI 响应状态 │ ├─ OKAY(2'b00) │ ├─ 传输成功 │ ├─ 无错误 │ ├─ 最常见 │ └─ 正常情况 │ ├─ EXOKAY(2'b01) │ ├─ 独占传输成功 │ ├─ 用于原子操作 │ ├─ 较少使用 │ └─ 特殊情况 │ ├─ SLVERR(2'b10) │ ├─ 从设备错误 │ ├─ 地址不存在 │ ├─ 访问权限错误 │ └─ 需要处理 │ └─ DECERR(2'b11) ├─ 解码错误 ├─ 地址无效 ├─ 总线错误 └─ 严重错误 
5.4.2 错误处理机制

错误处理的最佳实践:

错误处理建议
✅:
1. 检查响应状态
2. 记录错误信息
3. 实现重试机制
4. 设置超时保护
5. 记录日志便于调试

❌ 常见错误:
1. 忽视响应状态
2. 无限重试
3. 地址配置错误
4. 时钟域同步问题
5. 缓冲区溢出

六、PS-PL 通信实战

6.1 DDR 访问实战
6.1.1 PL 访问 PS 端 DDR

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
6.1.2 PS 访问 PL 资源

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;
}

6.2 数据交互实战
6.2.1 PS-PL 共享内存

共享内存的设计:

📊 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;
}
6.2.2 中断驱动的数据交互

中断驱动的优势:

📊 中断驱动的优势
│
├─ 优势 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;
}

6.3 应用场景实战
6.3.1 视频处理应用

视频处理的 PS-PL 分工:

📊 视频处理应用架构
│
├─ PS 端职责
│ ├─ 视频输入管理
│ ├─ 帧缓冲管理
│ ├─ 算法参数配置
│ ├─ 结果后处理
│ └─ 显示输出
│
├─ PL 端职责
│ ├─ 实时图像处理
│ ├─ 高速数据处理
│ ├─ 滤波运算
│ ├─ 特征提取
│ └─ 结果生成
│
├─ 数据流
│ ├─ 输入:视频帧 (DDR)
│ ├─ 处理:PL 加速
│ ├─ 输出:处理结果 (DDR)
│ └─ 显示:PS 输出
│
└─ 性能指标
├─ 帧率:30-60fps
├─ 延迟:毫秒级
├─ 吞吐量:高
└─ 功耗:优化 

视频处理的数据流:

┌─────────────────────────────────────────────────┐
│ 视频处理应用数据流
├─────────────────────────────────────────────────┤
│
│ 摄像头 → PS(输入管理) → DDR(输入缓冲)
│ ↓
│ PL(处理)
│ ↓
│ DDR(输出缓冲)
│ ↓
│ PS(后处理) → 显示器
│
└─────────────────────────────────────────────────┘
6.3.2 实时控制应用

实时控制的 PS-PL 分工:

📊 实时控制应用架构
│
├─ PS 端职责
│ ├─ 控制算法
│ ├─ 参数管理
│ ├─ 日志记录
│ ├─ 通信接口
│ └─ 用户交互
│
├─ PL 端职责
│ ├─ 实时数据采集
│ ├─ 高速信号处理
│ ├─ 实时反馈控制
│ ├─ 硬件接口
│ └─ 时间同步
│
├─ 通信方式
│ ├─ 中断驱动
│ ├─ 低延迟
│ ├─ 高实时性
│ └─ 可靠传输
│
└─ 性能指标
├─ 延迟:微秒级
├─ 抖动:低
├─ 可靠性:高
└─ 功耗:优化 

6.4 常见问题与解决方案

常见问题:

❌ 问题 1: 数据传输错误
原因:地址配置错误、时钟域同步问题
解决:检查地址映射、使用 CDC 同步器

❌ 问题 2: 性能不达预期
原因:突发长度不合理、端口选择不当
解决:优化突发配置、选择合适的 AXI 端口

❌ 问题 3: 缓存一致性问题
原因:未使用 AXI-ACP、缓存未刷新
解决:使用 AXI-ACP 或手动刷新缓存

❌ 问题 4: 中断丢失
原因:中断处理不及时、中断屏蔽
解决:优化中断处理、检查中断配置

❌ 问题 5: 死锁
原因:资源竞争、握手信号异常
解决:使用信号量、检查握手逻辑 

💡 关键要点总结:

  1. PL 访问 DDR 通常使用 AXI-HP,带宽高、延迟低
  2. PS 访问 PL 通常使用 AXI-GP,简单易用、功耗低
  3. 共享内存需要同步机制,避免数据竞争
  4. 中断驱动提高实时性,适合事件驱动应用
  5. 视频处理是典型应用,PS 负责管理,PL 负责加速
  6. 实时控制需要低延迟,使用中断和 DMA 优化

七、ZYNQ 启动流程与时钟系统

7.1 ZYNQ 启动流程
7.1.1 启动阶段概述

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
│ │ ├─ 初始化外设
│ │ ├─ 设置网络
│ │ └─ 加载内核
│ │ ├─ 启动系统
│ │ ├─ 加载驱动
│ │ └─ 启动应用
└─ 系统运行 
7.1.2 FSBL 详解

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
│ └─ 跳转执行
└─────────────────────────────────────┘ 

7.2 ZYNQ 时钟系统
7.2.1 时钟源和时钟树

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 时钟 (可配置)
├─ 其他时钟
└─ 相位调整 
7.2.2 时钟配置

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
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
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]

7.3 启动和时钟的最佳实践

启动流程优化:

✅ 最佳实践:1. 合理配置 FSBL - 根据应用选择启动设备 - 优化 DDR 配置 - 加载正确的 PL 比特流 2. 优化启动时间 - 使用快速存储设备 - 压缩比特流 - 并行加载 3. 调试启动问题 - 使用 UART 调试 - 检查 FSBL 日志 - 验证硬件配置 ❌ 常见错误:1. FSBL 配置不当 2. DDR 初始化失败 3. PL 比特流加载错误 4. 启动设备选择错误 5. 时钟配置不匹配 

时钟系统优化:

✅ 最佳实践:1. 合理选择时钟频率 - 根据应用需求 - 考虑功耗 - 满足时序要求 2. 时钟域同步 - 使用 CDC 技术 - 避免亚稳态 - 充分测试 3. 时钟树设计 - 最小化延迟 - 均衡负载 - 低抖动 ❌ 常见错误:1. 时钟频率过高 2. 时钟域同步不足 3. 时钟树设计不合理 4. 缺少时钟约束 5. 忽视时钟抖动 

💡 关键要点总结:

  1. ZYNQ 启动分为四个阶段,从 BootROM 到 Linux 应用
  2. FSBL 是关键阶段,负责初始化 PS 和加载 PL
  3. 时钟系统由 PLL 和 MMCM 管理,支持灵活配置
  4. PS 时钟固定,PL 时钟可配置
  5. 启动流程需要正确配置,避免常见错误
  6. 时钟域同步很关键,需要使用 CDC 技术

总结

📌 核心概念回顾

通过本文的深入学习,我们已经完整地理解了 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 驱动开发
├─ 设备树配置
└─ 用户空间应用 
🎯 设计要点总结
1. PS 端设计要点
设计方面关键要点注意事项
处理器配置双核 ARM Cortex-A9最高 1GHz 频率
存储设计OCM 用于关键代码DDR 用于大数据
外设选择根据应用需求避免资源冲突
时钟管理PS 时钟固定由 FSBL 配置
中断处理GIC 管理中断优先级配置
2. PL 端设计要点
设计方面关键要点注意事项
资源规划合理分配 LUT/BRAM避免过度使用
时钟设计使用 PLL/MMCM满足时序要求
接口设计AXI 协议标准握手机制正确
功耗管理动态功耗控制考虑散热
可靠性错误检测/纠正关键路径优化
3. PS-PL 通信要点
通信方式适用场景性能指标
轮询低频率数据交互延迟高,CPU 占用高
中断事件驱动应用延迟低,实时性好
DMA大数据块传输吞吐量高,CPU 占用低
共享内存频繁数据交互延迟最低,需同步
💼 实战应用场景
场景 1:视频处理系统
应用架构:
┌─────────────────────────────────────┐
│ Linux 应用 (PS)
│ ├─ 视频编码/解码控制
│ ├─ 用户界面
│ └─ 文件管理
└────────────┬────────────────────────┘
│ AXI-HP
┌────────────▼────────────────────────┐
│ 视频处理加速器 (PL)
│ ├─ 图像缩放
│ ├─ 色彩空间转换
│ ├─ 滤波处理
│ └─ 编码加速
└─────────────────────────────────────┘

性能指标:
- 吞吐量:1080p@60fps
- 延迟:<50ms
- 功耗:<5W 
场景 2:实时控制系统
应用架构:
┌─────────────────────────────────────┐
│ 实时控制应用 (PS)
│ ├─ 控制算法
│ ├─ 状态机
│ └─ 通信协议
└────────────┬────────────────────────┘
│ AXI-GP + 中断
┌────────────▼────────────────────────┐
│ 硬件控制接口 (PL)
│ ├─ PWM 生成
│ ├─ 传感器采集
│ ├─ 实时反馈
│ └─ 故障检测
└─────────────────────────────────────┘

性能指标:
- 控制周期:1ms
- 响应延迟:<100μs
- 可靠性:99.99% 
场景 3:数据采集与处理
应用架构:
┌─────────────────────────────────────┐
│ 数据处理应用 (PS)
│ ├─ 数据存储
│ ├─ 算法处理
│ └─ 网络传输
└────────────┬────────────────────────┘
│ AXI-HP + DMA
┌────────────▼────────────────────────┐
│ 数据采集加速器 (PL)
│ ├─ 多通道采集
│ ├─ 实时滤波
│ ├─ 数据压缩
│ └─ 缓冲管理
└─────────────────────────────────────┘

性能指标:
- 采样率:100MSPS
- 通道数:16
- 吞吐量:1.6GB/s 
🚀 最佳实践总结
设计阶段

✅ 必做事项:

  1. 明确应用需求和性能指标
  2. 进行 PS/PL 功能划分
  3. 设计 PS-PL 通信接口
  4. 规划时钟和电源管理
  5. 进行功耗和散热分析

❌ 避免事项:

  1. 盲目追求高频率
  2. 忽视时钟域同步
  3. 过度使用 PL 资源
  4. 缺少错误处理机制
  5. 忽视可维护性
实现阶段

✅ 必做事项:

  1. 使用 Vivado 进行设计
  2. 编写规范的 HDL 代码
  3. 充分进行仿真验证
  4. 进行时序分析
  5. 编写完整的文档

❌ 避免事项:

  1. 跳过仿真直接综合
  2. 忽视时序约束
  3. 缺少代码注释
  4. 不进行代码审查
  5. 忽视版本管理
调试阶段

✅ 必做事项:

  1. 使用 ILA 进行在线调试
  2. 编写完整的测试用例
  3. 进行压力测试
  4. 检查功耗和温度
  5. 验证可靠性

❌ 避免事项:

  1. 仅进行功能测试
  2. 忽视边界条件
  3. 不进行长时间运行测试
  4. 缺少故障恢复测试
  5. 忽视文档更新
📚 学习路线建议
初级阶段 (1-2 周)
├─ 理解 PS-PL 基本概念
├─ 学习 AXI 协议基础
├─ 完成简单的 Hello World 项目
└─ 目标:能够理解基本架构

中级阶段 (2-4 周)
├─ 深入学习 AXI 协议
├─ 掌握时钟域同步技术
├─ 完成 PS-PL 通信项目
└─ 目标:能够设计简单的 PS-PL 系统

高级阶段 (4-8 周)
├─ 学习高级优化技术
├─ 掌握 DMA 和中断处理
├─ 完成复杂的应用项目
└─ 目标:能够设计高性能系统

专家阶段 (8 周+)
├─ 研究前沿技术
├─ 优化系统性能
├─ 参与开源项目
└─ 目标:成为领域专家 
🔗 相关资源推荐

官方文档:

  • ZYNQ-7000 技术参考手册
  • ZYNQ UltraScale+ 参考手册

学习资源:

  • Xilinx 官方 ZYNQ 培训课程
  • Xilinx 官方 ZYNQ 参考设计

社区资源:

  • Xilinx 官方论坛
  • ZYNQ 在线书籍
💡 常见问题解答

Q1: PS 和 PL 应该如何划分功能?

A: 遵循以下原则:

  • PS 处理:控制流、串行处理、操作系统任务
  • PL 处理:数据流、并行处理、实时任务
  • 根据性能需求和资源约束进行权衡

Q2: 如何优化 PS-PL 通信性能?

A: 采用以下策略:

  • 使用 AXI-HP 而不是 AXI-GP 进行大数据传输
  • 使用 DMA 而不是 CPU 进行数据搬移
  • 合理设计缓冲区大小
  • 使用突发传输提高吞吐量

Q3: 时钟域同步为什么重要?

A: 因为:

  • 不同时钟域的信号可能产生亚稳态
  • 亚稳态会导致不可预测的行为
  • 需要使用 CDC 技术进行同步
  • 不同步会导致系统不稳定

Q4: 如何调试 PS-PL 系统?

A: 使用以下工具:

  • Vivado ILA 进行在线调试
  • UART 进行日志输出
  • GDB 进行软件调试
  • 逻辑分析仪进行硬件调试

Q5: ZYNQ 适合哪些应用?

A: 适合以下应用:

  • 视频处理和图像处理
  • 实时控制系统
  • 数据采集和处理
  • 通信系统
  • 工业控制
  • 医疗设备
🎓 总结

ZYNQ PS-PL 架构代表了现代嵌入式系统设计的发展方向,它完美地结合了 ARM 处理器的灵活性和 FPGA 的性能优势。通过本文的学习,您已经掌握了:

  1. ✅ PS-PL 架构的基本概念和组成
  2. ✅ PS 和 PL 各自的特点和应用场景
  3. ✅ PS-PL 之间的通信机制和协议
  4. ✅ 实战应用中的设计方法和最佳实践
  5. ✅ 常见问题的解决方案

下一步建议:

  • 动手实践:完成一个简单的 PS-PL 项目
  • 深入学习:研究 AXI 协议的细节
  • 性能优化:学习系统优化技术
  • 参与社区:分享您的经验和学习心得

希望本文能够帮助您深入理解 ZYNQ PS-PL 架构,为您的嵌入式系统设计之路提供坚实的基础!


参考资料

📖 官方文档
  1. Xilinx ZYNQ-7000 Technical Reference Manual - ZYNQ 官方技术参考手册,包含详细的硬件规格和接口定义
  2. Xilinx ZYNQ UltraScale+ Reference Manual - ZYNQ UltraScale+ 参考手册,适用于高端应用
  3. ZYNQ-7000 SoC Technical Reference Manual - 详细的技术规格说明
🎓 学习资源
  1. Xilinx 官方 ZYNQ 培训课程 - 官方提供的系统培训课程
  2. Xilinx 官方 ZYNQ 参考设计 - 完整的参考设计和示例代码
  3. ZYNQ 在线书籍 - 系统的 ZYNQ 学习资源
🔧 技术文章
  1. ZYNQ 启动流程详解 - 深入讲解 ZYNQ 启动过程
  2. ZYNQ 时钟系统设计指南 - 时钟系统设计最佳实践
  3. AXI 协议详解与应用 - AXI 协议深度分析
  4. ZYNQ PS-PL 通信实战 - 实战通信设计案例
💻 开源项目
  1. Xilinx Zynq-7000 Base TRD - 官方基础参考设计
  2. GitHub ZYNQ 相关项目 - 社区开源项目集合
  3. Xilinx Embedded Software - 官方嵌入式软件库
🌐 社区资源
  1. Xilinx 官方论坛 - 官方技术支持论坛
  2. Xilinx 技术支持中心 - 常见问题解答
  3. ZYNQ 技术博客 - 中文技术博客
📚 相关协议标准
  1. ARM AMBA AXI 规范 - AXI 协议官方规范
  2. Vivado 设计套件用户指南 - Vivado 工具使用指南
  3. Vivado Tcl 命令参考 - Tcl 脚本编程参考
  4. Vivado 逻辑仿真用户指南 - 仿真工具使用指南

目录

  1. 概述
  2. 一、PS-PL 架构基础概念
  3. 1.1 什么是 PS 和 PL
  4. 1.1.1 PS(处理系统) 定义
  5. 1.1.2 PL(可编程逻辑) 定义
  6. 1.1.3 PS vs PL 对比
  7. 1.2 ZYNQ 基本结构
  8. 1.2.1 ZYNQ-7000 系列架构
  9. 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 │ └─────────────────┴──────────┴──────────┴──────────┘
  10. 1.2.2 ZYNQ-7000 的整体架构
  11. 1.3 为什么需要 PS-PL 架构
  12. 1.3.1 传统 FPGA 的局限性
  13. 1.3.2 PS-PL 架构的优势
  14. 1.3.3 应用场景分析
  15. 1.4 PS-PL 架构的优势
  16. 1.4.1 性能优势
  17. 1.4.2 成本优势
  18. 1.4.3 开发效率优势
  19. 二、PS 端详解
  20. 2.1 应用处理单元 (APU)
  21. 2.1.1 ARM Cortex-A9 处理器
  22. 2.1.2 NEON 媒体处理引擎
  23. 2.1.3 浮点单元 (FPU)
  24. 2.2 存储系统
  25. 2.2.1 片内存储 (OCM)
  26. 2.2.2 外部 DDR 存储
  27. 2.3 外设接口
  28. 2.3.1 通信接口
  29. 2.3.2 低速接口
  30. 2.4 中断和时钟管理
  31. 2.4.1 中断系统
  32. 2.4.2 时钟管理
  33. 2.5 PS 端的软件支持
  34. 2.5.1 操作系统支持
  35. 2.5.2 开发工具
  36. 三、PL 端详解
  37. 3.1 逻辑资源
  38. 3.1.1 查找表 (LUT)
  39. 3.1.2 触发器 (FF)
  40. 3.1.3 多路选择器 (MUX)
  41. 3.2 存储资源
  42. 3.2.1 Block RAM(BRAM)
  43. 3.2.2 分布式 RAM
  44. 3.3 计算资源
  45. 3.3.1 DSP48E1 切片
  46. 3.3.2 乘法器和累加器
  47. 3.4 高速接口
  48. 3.4.1 高速收发器 (GTX/GTP)
  49. 3.4.2 PCIe 接口
  50. 3.5 时钟资源
  51. 3.5.1 全局时钟网络
  52. 3.5.2 PLL 和 MMCM
  53. 3.6 PL 资源对比与选型
  54. 四、PS-PL 互联技术
  55. 4.1 AXI 互连架构
  56. 4.1.1 AXI 总线概述
  57. 4.1.2 AXI 互连的拓扑
  58. 4.2 PS-PL 的 9 个物理接口
  59. 4.2.1 AXI-GP 接口 (通用端口)
  60. 4.2.2 AXI-HP 接口 (高性能端口)
  61. 4.2.3 AXI-ACP 接口 (缓存一致性端口)
  62. 4.3 PS-PL 接口带宽对比
  63. 4.4 PS-PL 通信的关键考虑
  64. 4.4.1 地址映射
  65. 4.4.2 时钟域同步
  66. 4.5 PS-PL 互联的实现方式
  67. 五、AXI 接口协议详解
  68. 5.1 AXI 握手机制
  69. 5.1.1 VALID/READY 握手
  70. 5.1.2 握手的应用场景
  71. 5.2 AXI 通道结构
  72. 5.2.1 写通道 (Write Channel)
  73. 5.2.2 读通道 (Read Channel)
  74. 5.3 AXI 数据传输
  75. 5.3.1 突发传输 (Burst Transfer)
  76. 5.3.2 写使能 (Write Strobe)
  77. 5.4 AXI 错误处理
  78. 5.4.1 响应状态 (Response)
  79. 5.4.2 错误处理机制
  80. 六、PS-PL 通信实战
  81. 6.1 DDR 访问实战
  82. 6.1.1 PL 访问 PS 端 DDR
  83. 6.1.2 PS 访问 PL 资源
  84. 6.2 数据交互实战
  85. 6.2.1 PS-PL 共享内存
  86. 6.2.2 中断驱动的数据交互
  87. 6.3 应用场景实战
  88. 6.3.1 视频处理应用
  89. 6.3.2 实时控制应用
  90. 6.4 常见问题与解决方案
  91. 七、ZYNQ 启动流程与时钟系统
  92. 7.1 ZYNQ 启动流程
  93. 7.1.1 启动阶段概述
  94. 7.1.2 FSBL 详解
  95. 7.2 ZYNQ 时钟系统
  96. 7.2.1 时钟源和时钟树
  97. 7.2.2 时钟配置
  98. Vivado 中配置 ZYNQ 时钟
  99. 创建时钟约束
  100. 配置 PLL
  101. 配置 MMCM
  102. 7.3 启动和时钟的最佳实践
  103. 总结
  104. 📌 核心概念回顾
  105. 架构层面
  106. 🎯 设计要点总结
  107. 1. PS 端设计要点
  108. 2. PL 端设计要点
  109. 3. PS-PL 通信要点
  110. 💼 实战应用场景
  111. 场景 1:视频处理系统
  112. 场景 2:实时控制系统
  113. 场景 3:数据采集与处理
  114. 🚀 最佳实践总结
  115. 设计阶段
  116. 实现阶段
  117. 调试阶段
  118. 📚 学习路线建议
  119. 🔗 相关资源推荐
  120. 💡 常见问题解答
  121. 🎓 总结
  122. 参考资料
  123. 📖 官方文档
  124. 🎓 学习资源
  125. 🔧 技术文章
  126. 💻 开源项目
  127. 🌐 社区资源
  128. 📚 相关协议标准

更多推荐文章

查看全部
  • 数据结构:快慢指针原理及链表环检测
  • Prompt 提示词工程核销逻辑与高效 AI 交互策略
  • 2026 RAG 技术路线:基于 DeepSeek 与 Neo4j 知识图谱构建企业智能体系
  • C++ STL set 与 map 底层封装原理详解
  • 人工智能(AI)常见面试题及答案汇总
  • 国内主流 AI 工具对比:豆包、元宝、千问、Kimi、DeepSeek、MiniMax、GLM
  • 国产大模型全景清单与行业应用趋势分析
  • OpenVLA 模型微调与机器人平台部署实战
  • 基于 FPGA 的北斗导航自适应抗干扰算法设计与实现
  • 医疗 AI 场景下的逻辑回归算法原理与应用实战
  • RabbitMQ 后端消息队列技术详解
  • AI 安全研究:视觉提示词注入与模型鲁棒性分析
  • AI 产品经理成长指南:核心技能与进阶路径
  • Linux Socket 套接字编程基础概念
  • 知网维普 AIGC 检测应对策略:降低论文 AI 率的方法
  • FPGA 光通信开发:Aurora 64B/66B 协议使用指南
  • 4090 显卡实测:圣光艺苑 AI 绘画工具生成古典名画效果展示
  • .NET 集成 GoView 低代码可视化大屏方案详解
  • 8 月初学习复盘:Vue 实践与算法思考
  • Go Web 开发核心理论与实践

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

  • Gemini 图片去水印

    基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online

  • Markdown转HTML

    将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online

  • HTML转Markdown

    将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online