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。
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 边界、以及中断合并是否过于激进。