DMA传输可分为BLOCK DMA与SG DMA两种模式,两者在数据组织方式上存在差异。
发送过程(FPGA 向主机写入数据)
- BLOCK DMA:FPGA 向主机发起读请求(或通过中断通知),主机分配一块连续的内存空间,并将该起始地址返回给 FPGA。FPGA 随后通过该地址将数据写入主机内存。
- SG DMA:主机为 FPGA 分配一个由多个离散内存块组成的链表式结构。FPGA 需要依次访问这些不连续的地址块,以完成整个数据包的写入。
接收过程(FPGA 从主机读取数据)
- BLOCK DMA:主机告知 FPGA 数据所在的单一连续内存地址,FPGA 通过该地址发起读请求,一次性获取所有数据。
- SG DMA:主机提供多个离散的内存地址。FPGA 需要分别发起多次读请求,从这些不连续的地址块中读取数据,才能完整接收数据。
赛灵思PCIE3.0架构

在赛灵思 PCIe 3.0 架构中,TLP 的收发路径被明确划分为两类角色:请求器(Requester)与完成器(Completer)。相比早期版本,3.0 架构对职责和流程的定义更加清晰,因此基于该架构来构建 DMA 逻辑是完全可行且更易入手的。
完成器
作为从机角色,主要负责通过 CQ 接口接收来自主机的请求,并通过 CC 接口返回相应的完成包,用于处理主机发起的读写操作。这在计算机网络与系统底层交互中是一个常见模型。
请求器
作为主机角色,FPGA 可通过 RQ 接口主动向主机发起请求(如 DMA 读写),并由主机的 Root Complex(RC)返回相应的完成包,从而实现 FPGA 对主机内存的访问。
MMIO和DMA
通过完成器(Completer)与请求器(Requester)这两类接口,可实现MMIO与DMA两大功能:
- MMIO:用于寄存器读写,完全由完成器实现。主机通过发送写请求来配置寄存器,或通过读请求来读取寄存器状态。
- DMA:其传输行为可分为接收与发送两个方向,具体流程如下。
DMA
Block DMA 本质上是 SG DMA 的一个子集,因此只要掌握了 SG DMA 的完整工作流程,理解 Block DMA 便水到渠成。理解这种高效的数据搬运机制,是进行算法与系统性能优化的关键一环。
DMA 接收流程(主机 → FPGA)
- 通知传输规模:主机通过写请求向 FPGA 写入
rx_length 与 rx_offset,指明待传输数据总量(Completer 参与)。
- 传递 SGL 表地址:主机通过写请求告知 FPGA SGL(Scatter-Gather List)表所在的主机地址(Completer 参与)。
- 获取 SGL 表内容:FPGA 通过该地址发起读请求,读取主机中的 SGL 表(Requester 参与)。
- 读取主机数据:FPGA 解析 SGL 表获取数据实际位置,并发起读请求读取主机内存中的数据(Requester 参与)。
- 确认接收完成:主机通过读请求查询 FPGA 的
RX_DONE 寄存器,确认数据接收是否完成(Completer 参与)。
DMA 发送流程(FPGA → 主机)
- 发起传输请求:FPGA 通过中断或 Doorbell 机制通知主机准备发送数据。
- 获取传输规模:主机发起读请求,从 FPGA 获取
tx_length 与 tx_offset,确定待接收数据量(Completer 参与)。
- 主机分配内存:主机分配接收缓冲区,并将其地址信息填入 SGL 表。(主机参与)
- 传递 SGL 表地址:主机通过写请求将 SGL 表的主机地址告知 FPGA(Completer 参与)。
- 获取 SGL 表内容:FPGA 通过该地址发起读请求,获取 SGL 表(Requester 参与)。
- 向主机写入数据:FPGA 依据 SGL 表信息,发起写请求将数据写入主机内存(Requester 参与)。
- 确认发送完成:主机在接收完成后,通过写请求置位 FPGA 的
TX_DONE 寄存器,通知传输结束(Completer 参与)。
由此可见,在 DMA 传输过程中,Completer 的角色本质上是处理对 FPGA 寄存器的读写操作,以实现控制信息的交互;而 Requester 则负责主动发起数据读写请求,完成在主机内存与 FPGA 之间的大规模数据搬运。这种高效的硬件加速方案,在现代人工智能与计算密集型应用中至关重要。
|