4. FPGA fabric与HPS接口

在Agilex SoC中,HPS(Hard Processor System)与FPGA fabric并不是简单地“连在一起”,而是通过一组分工明确的AXI桥接器构成层次化互连。理解这些桥的角色,是后续在Platform Designer中正确添加HPS组件、分配地址、生成系统并让软件访问FPGA外设的前提。本节先厘清四类接口的定位,再落到Platform Designer的实际配置操作。

一、四类接口的定位与差异

Agilex HPS对外暴露的FPGA相关接口可归纳为四类:FPGA-to-HPS AXI桥、HPS-to-FPGA AXI桥、轻量级HPS-to-FPGA AXI桥,以及MPU接口。它们的方向、位宽、性能与用途各不相同。

  • FPGA-to-HPS桥:方向为FPGA主设备→HPS从设备。FPGA逻辑中的主端口(如自定义DMA、加速器)通过它访问HPS侧的DDR、片上RAM、外设寄存器。它是高带宽通道,通常支持较宽数据位宽与多主并发。
  • HPS-to-FPGA桥:方向为HPS主设备→FPGA从设备。HPS中的处理器、DMA控制器通过它访问FPGA中实现的从设备(如自定义IP寄存器、片上存储)。这是软件“看到”FPGA外设的主要路径。
  • 轻量级HPS-to-FPGA桥:同样是HPS→FPGA方向,但为低带宽、低延迟、小位宽通道,主要用于访问FPGA中的控制/状态寄存器(CSR),不适合大数据搬运。它通常与HPS-to-FPGA桥共享地址空间但独立编址,避免控制流量与数据流量互相阻塞。
  • MPU接口:指HPS内部微处理器单元(Cortex-A系列)与互连之间的接口,是软件发起访问的源头。它决定了CPU如何通过上述桥到达FPGA,也涉及缓存属性、地址映射与访问权限。

关键区别在于:方向决定谁发起访问,位宽与带宽决定适合传什么。控制寄存器走轻量级桥,批量数据走全功能桥,FPGA主动访问HPS内存走FPGA-to-HPS桥。若把大数据流错误地放到轻量级桥上,会出现吞吐瓶颈;若把高频控制寄存器放到全功能桥上,则可能因仲裁与位宽转换引入额外延迟。

Agilex SoC:HPS 与 FPGA Fabric 接口关系 HPS(硬核处理器系统) MPU(Cortex-A 集群) 软件访问发起源 · 缓存/MMU 属性 HPS 互连 / 从设备 DDR · 片上RAM · 外设寄存器 HPS-to-FPGA 主端口 高带宽 · 数据搬运 轻量级 HPS-to-FPGA 主端口 低带宽 · 控制/状态寄存器 FPGA-to-HPS 从端口 接收 FPGA 主设备访问 FPGA Fabric(可编程逻辑) FPGA 从设备(数据类) DMA 缓冲 · 片上存储 · 加速器 FPGA 从设备(控制类) 自定义 IP 的 CSR 寄存器组 FPGA 主设备 自定义 DMA · 数据采集引擎 H2F AXI 桥 宽位宽/高带宽 LWH2F 桥 窄位宽/低延迟 F2H AXI 桥 FPGA 主动访问 HPS→FPGA 数据流 HPS→FPGA 控制流 FPGA→HPS 访问 MPU 发起

二、地址映射与位宽:配置前必须确定的参数

在Platform Designer中,桥接器不是“自动魔法”,而是需要显式分配地址与位宽。以典型Agilex配置为例,HPS-to-FPGA桥可配置为32/64/128位数据宽度,轻量级桥通常为32位,FPGA-to-HPS桥则取决于HPS侧从端口能力。地址方面,HPS-to-FPGA与轻量级HPS-to-FPGA各自拥有独立的地址窗口,例如全功能桥映射到 0x4000_0000 起始的1GB窗口,轻量级桥映射到 0xC000_0000 起始的128MB窗口(具体数值以器件手册与设计为准,此处为示例)。

软件侧通过MPU访问这些地址时,必须注意缓存属性。若FPGA从设备是寄存器,应配置为Device或Strongly Ordered,避免缓存导致读写顺序错乱;若FPGA从设备是共享内存,可配置为Normal Non-cacheable或Write-Through,视一致性需求而定。这些属性在设备树或裸机MMU表中设置,而不是在Platform Designer里设置,但Platform Designer生成的地址信息是软件配置的依据。

三、在Platform Designer中添加并配置HPS组件

下面以Quartus Prime Pro + Platform Designer为例,说明从零添加HPS并连接桥接器的关键操作。假设目标系统为:HPS通过轻量级桥访问一个自定义PIO控制寄存器,通过全功能桥访问一个片上RAM,FPGA侧一个自定义DMA通过FPGA-to-HPS桥向HPS DDR写数据。

  1. 新建系统并添加HPS:在Platform Designer中创建 .qsys 系统,从IP Catalog搜索“Agilex HPS”或“Hard Processor System”,双击添加。此时HPS组件会出现在System Contents中,并展开出大量接口。
  2. 启用所需桥接器:双击HPS组件进入参数编辑器,在“FPGA Interfaces”或“AXI Bridges”页中,勾选 Enable HPS-to-FPGA AXI Bridge、Enable Lightweight HPS-to-FPGA AXI Bridge、Enable FPGA-to-HPS AXI Bridge。若不需要FPGA主动访问HPS,可关闭F2H桥以节省资源。
  3. 设置位宽与时钟:为HPS-to-FPGA桥选择数据宽度(示例选64位),为轻量级桥保持32位。注意桥接器时钟通常来自HPS的 h2f_axi_clk、lwh2f_axi_clk、f2h_axi_clk,需与FPGA逻辑时钟域正确连接,跨时钟域时Platform Designer会提示插入桥或FIFO。
  4. 添加FPGA侧从设备:从IP Catalog添加PIO(用于控制寄存器)和On-Chip Memory(用于数据缓冲),以及自定义DMA IP。分别将PIO的 s1 从端口连接到HPS的 lwh2f_axi 主端口;将On-Chip Memory的 s1 连接到HPS的 h2f_axi 主端口;将DMA的主端口连接到HPS的 f2h_axi 从端口。
  5. 分配地址:在Address Map标签页中,为每个从设备分配基地址。例如PIO分配 0xC000_0000,On-Chip Memory分配 0x4000_0000,确保不与HPS内部外设冲突。Platform Designer会自动检查重叠并报错。
  6. 连接时钟与复位:将所有FPGA侧IP的时钟连接到对应的HPS桥时钟,复位连接到HPS输出的复位或自定义复位控制器。注意轻量级桥与全功能桥可能处于不同时钟域,若FPGA逻辑统一使用一个时钟,需确认频率满足桥接器要求。
  7. 生成系统:点击Generate HDL,选择Verilog或VHDL,生成后得到 soc_system.qsys 对应的RTL、地址映射头文件(如 soc_system.h)和设备树片段。头文件中会定义 PIO_BASE、ONCHIP_MEM_BASE 等宏,软件直接引用即可。
生成后务必检查 soc_system.h 中的基地址与设备树是否一致。若使用Linux,设备树中的 reg 属性必须与Platform Designer分配的地址完全对应,否则驱动会访问到错误区域。

四、一个可参考的配置片段

以下为Platform Designer生成后,软件侧访问PIO与On-Chip Memory的裸机示例(地址为示例值,实际以生成头文件为准):

#include "soc_system.h"

/* 通过轻量级桥写控制寄存器 */
#define PIO_CTRL   (PIO_BASE + 0x00)
#define PIO_STATUS (PIO_BASE + 0x04)

*(volatile uint32_t *)PIO_CTRL   = 0x1;      /* 启动 FPGA 逻辑 */
while ((*(volatile uint32_t *)PIO_STATUS & 0x1) == 0) {
    /* 等待 FPGA 就绪 */
}

/* 通过全功能桥读写片上 RAM */
uint32_t *buf = (uint32_t *)ONCHIP_MEM_BASE;
buf[0] = 0xDEADBEEF;
uint32_t val = buf[0];

若FPGA侧DMA通过F2H桥向HPS DDR写数据,则HPS软件需要先分配一段物理连续、非缓存的DDR缓冲区,把物理地址通过轻量级桥写入DMA的源/目的寄存器,再启动DMA。完成后通过中断或状态寄存器轮询确认传输结束。这里的关键是:控制路径走轻量级桥,数据路径走全功能桥或F2H桥,两者地址空间独立,互不干扰。

五、常见配置错误与判断依据

  • 地址重叠:Platform Designer在Address Map中会以红色提示重叠。若忽略,生成后软件访问会命中错误从设备。
  • 时钟未连接:桥接器时钟悬空会导致生成失败或运行时挂死。检查每个桥的 *_axi_clk 是否已连接。
  • 位宽不匹配:若HPS-to-FPGA桥设为64位,而FPGA从设备为32位,Platform Designer会自动插入位宽转换器,但会引入额外延迟。对性能敏感的数据路径应尽量保持位宽一致。
  • 缓存属性错误:软件访问寄存器却配置为Cacheable,可能出现读不到最新状态。判断方法是:连续读同一寄存器,若值不变但FPGA侧确实在更新,应检查MMU/设备树属性。