3. Kria PCIe 系统架构设计

在 Kria 平台上做 PCIe 系统设计,第一步不是写代码,而是把“通路”想清楚。Kria 的 SoC 器件(如 K26/K24)内部同时存在两条与 PCIe 相关的硬件路径:一条是 PS(Processing System)侧集成的 PCIe 控制器,另一条是通过 PL(Programmable Logic)侧 PCIe 硬核(Integrated Block for PCIe)实现的通路。二者在带宽、延迟、DMA 能力、可定制性和软件栈上差异明显,选错通路往往在后期才发现瓶颈,返工代价很高。

PS-PCIe 与 PL-PCIe 通路对比

PS-PCIe 由 Zynq UltraScale+ MPSoC 的 PS 端 PCIe 控制器提供,通常挂在 AXI 互联上,直接由 ARM Cortex-A53 通过寄存器访问,Linux 下有成熟的 xilinx-pcie 驱动支持。它的优势是“开箱即用”:配置简单、软件栈完整、中断走 GIC,适合把 Kria 当作标准 PCIe 设备或标准主机使用。缺点是通道数、BAR 空间和 DMA 引擎受 PS 固定资源限制,难以做深度定制。

PL-PCIe 则使用 PL 中的 PCIe 硬核,配合 XDMA 或 QDMA IP 构建。它的优势是灵活:可以自定义 BAR 数量与大小、自定义 DMA 描述符格式、把数据直接搬进 PL 的 BRAM/URAM 或 DDR,甚至做多队列、多通道并行。代价是需要在 Vivado 中完成 IP 集成、约束、时钟与复位设计,软件侧也要处理驱动或裸机寄存器编程。简单判断:如果只是标准主机/设备通信,优先 PS-PCIe;如果需要高吞吐、低延迟、定制协议或与 PL 算法紧耦合,选 PL-PCIe。

Kria PCIe 双通路架构与数据/中断路径 PS 侧通路(PS-PCIe) Cortex-A53 Linux / 裸机 PS PCIe 控制器 Gen2 x1/x2 GIC 中断 MSI / INTx PS DDR DMA 目标 PL 侧通路(PL-PCIe) PCIe 硬核 Gen3 x4 XDMA / QDMA 多队列 DMA PL BRAM/URAM 片上缓冲 PL DDR / PS DDR 大容量缓冲 AXI / NoC RC 与 EP 模式选择 RC:Kria 作主机,枚举下游设备 EP:Kria 作设备,被主机枚举 地址映射 BAR → AXI 地址段 CPU 物理地址 ↔ PCIe 地址 中断路由 MSI/MSI-X → GIC / PL IRQ INTx 兼容路径 DMA 路径规划 Host DDR ↔ BAR/描述符 ↔ XDMA 引擎 ↔ PL 缓冲 / PS DDR 关键参数:描述符环深度、突发长度、通道数、地址对齐

RC 与 EP 模式选择

RC(Root Complex)与 EP(Endpoint)是 PCIe 拓扑中的两种角色。Kria 作为 RC 时,负责枚举下游设备、分配总线号和 BAR 空间,典型场景是 Kria 作为主控连接 NVMe SSD、采集卡或另一块 FPGA 板卡。Kria 作为 EP 时,被上游主机枚举,典型场景是 Kria 作为加速卡插入服务器,由服务器 CPU 发起访问。

模式选择在硬件上由 PCIe 硬核的配置决定,PS-PCIe 通过 psu_pcie 的 mode 参数设置,PL-PCIe 在 IP 配置界面选择 Root Port 或 Endpoint。软件侧,RC 模式需要运行枚举逻辑(Linux 内核自动完成,裸机需自行实现配置空间读写);EP 模式需要正确配置 BAR、实现配置空间响应,并等待主机枚举。一个常见误区是:EP 模式下 Kria 不能主动发起枚举,所有配置访问都由主机发起,Kria 只做响应。

地址映射

地址映射是 PCIe 设计中最容易出错的部分。核心是三层地址的转换:CPU 物理地址、PCIe 总线地址(BAR 空间)、设备内部地址。以 PL-PCIe 的 XDMA 为例,主机侧看到的 BAR0 通常映射到 XDMA 的控制寄存器,BAR1/BAR2 映射到 AXI 地址段。在 Vivado 中,需要为每个 BAR 指定大小和对齐,例如 BAR0 设为 64 KB、BAR1 设为 1 MB,并在 Address Editor 中把 BAR 映射到 PL 的 AXI 从设备地址。

Linux 下可以用 lspci -vv 查看 BAR 分配结果,用 resource0 等 sysfs 节点做 mmap 访问。裸机 EP 模式下,需要手动实现 BAR 命中判断:当主机访问某个 BAR 地址时,硬件根据 bar_hit 信号把访问路由到对应的内部 AXI 从设备。地址映射一旦错位,表现为读写返回全 0 或总线挂死,因此建议先用小范围 BAR 做回环测试。

中断路由

PCIe 中断有 INTx、MSI、MSI-X 三种。INTx 是传统电平中断,通过配置空间的 Interrupt Pin 传递,适合兼容旧设备;MSI 通过写内存方式发送中断,MSI-X 支持更多向量和独立地址。在 Kria 上,PS-PCIe 的 MSI 中断最终进入 GIC,由 Linux 的 pcieport 驱动处理;PL-PCIe 的 MSI-X 中断可以路由到 PS 的 GIC,也可以路由到 PL 内部的中断控制器,由 PL 逻辑直接响应。

实际设计中,中断路由要和 DMA 完成事件绑定:XDMA 每完成一个描述符,产生一次中断,主机在中断服务程序里读取完成计数并回收缓冲。如果中断太频繁,可以合并中断(interrupt coalescing),例如每 16 个描述符或每 10 微秒触发一次,降低 CPU 占用。

DMA 路径规划

DMA 路径决定了系统的实际吞吐。以 PL-PCIe + XDMA 为例,典型路径是:主机 DDR → PCIe 链路 → XDMA 引擎 → AXI → PL BRAM/URAM 或 PS DDR。规划时要关注四个参数:描述符环深度(如 64~256)、突发长度(如 256 字节)、通道数(如 H2C 和 C2H 各 4 通道)、地址对齐(4 KB 对齐可减少 TLB 压力)。

一个可参考的示例配置:XDMA 设为 Gen3 x4,H2C 通道 2 个、C2H 通道 2 个,描述符环深度 128,突发长度 256 字节,BAR0 64 KB 用于控制寄存器,BAR1 1 MB 用于数据窗口。主机侧用 xdma 驱动,通过 /dev/xdma0_h2c_0 等字符设备发起传输。测试时先用 1 MB 小块传输验证功能,再逐步增大到 64 MB 观察带宽是否稳定。若带宽远低于理论值,优先检查描述符环是否成为瓶颈、地址是否跨 4 KB 边界、以及中断合并是否过于激进。

通路选择建议:标准主机/设备通信优先 PS-PCIe,快速落地;高吞吐、定制协议、与 PL 算法紧耦合优先 PL-PCIe。地址映射和中断路由必须在设计早期确定,避免后期返工。