🏠

Alveo Ethernet Kernel Connectivity 模块深度解析

一句话概括

本模块展示了如何在 AMD Alveo 数据中心加速卡上,通过 Vitis 流程将包含 GTY 收发器的 RTL Kernel 集成到硬件设计中,实现与外部网络的 10G 以太网数据通路连接。它就像是一座"数字桥梁"——将 FPGA 内部的计算逻辑与物理世界的网络线缆连接起来。


问题空间:为什么需要这个模块?

背景挑战

AMD Alveo 加速卡(如 U200、U250、U280、U50)配备了 QSFP28 网络接口,支持 10GbE/25GbE/40GbE/100GbE 等多种以太网配置。然而,在 Vitis 统一开发流程中使用这些高速收发器面临几个核心挑战:

  1. 物理层复杂性:GTY 收发器涉及差分时钟、参考时钟、高速串行信号等复杂的模拟电路接口
  2. 平台依赖性:不同 Alveo 卡片的 GT 位置、时钟频率、引脚分配各不相同
  3. 工具链集成:需要将底层 RTL 设计与 Vitis 的高级综合流程无缝衔接
  4. 协议栈抽象:开发者希望专注于业务逻辑,而非以太网 MAC/PCS 的底层细节

设计动机

传统上,使用 Alveo 的网络功能需要直接在 Vivado 中进行底层设计,这违背了 Vitis "软件定义硬件"的理念。本模块的核心价值在于:

证明可以在 Vitis 流程中,以近乎普通 RTL Kernel 的方式使用 GTY 收发器,仅需处理少量的 GT 专用信号连接。

这是一个方法论教程——它本身不提供复杂的业务功能,而是展示集成模式的正确打开方式。


心智模型:如何理解这个系统?

类比:邮局分拣系统

想象一个现代化的邮局分拣中心:

  • ethernet_krnl = 邮局的大门和前台

    • 负责与外部世界(公路上的邮车)对接
    • 管理进出的信件流(以太网帧)
    • 提供控制面板(AXI-Lite 寄存器)供管理员配置
  • data_fifo_krnl = 内部传送带

    • 简单地将接收的信件转发出去(loopback 模式)
    • 在本示例中只是演示连通性,实际应用中会替换为真正的处理逻辑
  • QSFP28 接口 = 连接外部公路的卡车码头

    • GTY 收发器就是这里的装卸设备
    • 差分时钟如同码头的同步调度系统

核心抽象层次

┌─────────────────────────────────────────────────────────────┐
│                    用户业务逻辑 (Your Logic)                  │
│                      (替换 data_fifo_krnl)                   │
├─────────────────────────────────────────────────────────────┤
│              AXI4-Stream 接口 (标准流式接口)                  │
│              tx_axis / rx_axis (64-bit 数据)                 │
├─────────────────────────────────────────────────────────────┤
│              ethernet_krnl (网络内核封装层)                   │
│    ┌─────────────┐    ┌─────────────┐    ┌─────────────┐   │
│    │ AXI-Stream  │◄──►│   xxv_      │◄──►│    GTY      │   │
│    │   FIFOs     │    │  ethernet   │    │ Transceivers│   │
│    └─────────────┘    │   (MAC/PCS) │    └─────────────┘   │
│                       └─────────────┘                        │
│    ┌─────────────┐                                           │
│    │ AXI-Lite    │ ← 控制寄存器访问 (复位、环回、状态)        │
│    │  Control    │                                           │
│    └─────────────┘                                           │
└─────────────────────────────────────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────┐
│              Alveo Platform (固定资源)                        │
│         ┌─────────────┐    ┌─────────────┐                   │
│         │  GT RefClk  │    │  QSFP28     │                   │
│         │ (161.132MHz)│    │   Connector │                   │
│         └─────────────┘    └─────────────┘                   │
└─────────────────────────────────────────────────────────────┘

架构详解

组件拓扑图

graph TB subgraph "Host Software" HOST["XRT Runtime
ap_ctrl_hs 执行模型"] end subgraph "Alveo FPGA Fabric" subgraph "ethernet_krnl_axis_x1/x4" CTRL["ethernet_control_s_axi
AXI-Lite 控制接口"] ETH_IP["xxv_ethernet IP
10G MAC/PCS"] TX_FIFO["TX AXI-Stream FIFO"] RX_FIFO["RX AXI-Stream FIFO"] end subgraph "data_fifo_krnl(s)" LOOPBACK["Loopback FIFOs
rx_axis → tx_axis"] end subgraph "Platform Resources" GT["GTY Transceivers
4 lanes"] REFCLK["GT Refclk
161.1328125 MHz"] FREERUN["Free Run Clock"] end end subgraph "External Network" QSFP["QSFP28 Port"] NET["Ethernet Network"] end HOST -->|"s_axi_control
配置寄存器"| CTRL CTRL -->|"scalar[31:0]
控制信号"| ETH_IP ETH_IP <-->|"axi_str_txd/rxd
64-bit stream"| TX_FIFO ETH_IP <-->|"axi_str_txd/rxd
64-bit stream"| RX_FIFO TX_FIFO -->|"tx0_axis"| LOOPBACK LOOPBACK -->|"rx0_axis"| RX_FIFO ETH_IP <-->|"gt_txp/n gt_rxp/n
高速差分信号"| GT GT <-->|"物理连接"| QSFP QSFP <-->|"光纤/铜缆"| NET REFCLK -->|"gt_refclk_p/n
差分时钟"| ETH_IP FREERUN -->|"clk_gt_freerun
自由运行时钟"| ETH_IP style HOST fill:#e1f5ff style ETH_IP fill:#fff4e1 style GT fill:#ffe1e1 style QSFP fill:#f0e1ff

关键组件职责

1. ethernet_krnl_axis_x1.sv / ethernet_krnl_axis_x4.sv

这是以太网内核的 RTL 顶层,有两种变体:

特性 x1 版本 x4 版本
通道数 1 lane 4 lanes
数据流接口 rx0_axis, tx0_axis rx0-3_axis, tx0-3_axis
控制寄存器 scalar00 scalar00-03
适用场景 单通道测试 多通道聚合

核心设计要点:

  • 参数化设计:通过 C_NUM_LANES 局部参数区分两种变体的大部分共享逻辑
  • 时钟域处理rx_core_clktx_clk_out 驱动,确保收发时钟同源
  • 跨时钟域同步:使用 xpm_cdc_single/xpm_cdc_array_singlestat_rx_block_lock 从以太网时钟域同步到 ap_clk
// 关键 CDC (Clock Domain Crossing) 实例
xpm_cdc_array_single #(
    .DEST_SYNC_FF(4),      // 4级同步,降低亚稳态概率
    .WIDTH(C_NUM_LANES)
) ap_rx_block_lock_sync_i (
    .dest_out(ap_stat_rx_block_lock_sync),
    .dest_clk(ap_clk),
    .src_clk(1'b0),        // 源时钟未使用,因为是电平信号
    .src_in(stat_rx_block_lock)
);

2. ethernet_control_s_axi_x1.v / ethernet_control_s_axi_x4.v

AXI-Lite 从接口控制器,提供寄存器访问能力:

寄存器映射(x1 版本):

地址 名称 权限 描述
0x10 scalar00 R/W 控制寄存器,位定义见下表
0x14 status0 RO bit[0] = rx_block_lock

scalar00 位域定义:

bit[2:0]   : gt_loopback        // GT 环回模式
bit[4]     : gtwiz_reset_rx_datapath  // RX 数据通路复位
bit[5]     : gtwiz_reset_tx_datapath  // TX 数据通路复位
bit[8]     : fifo 单独复位控制
bit[12]    : sys_reset          // 全局系统复位

设计权衡:

  • 使用简单的状态机实现 AXI-Lite 协议,而非完整的 AXI Interconnect
  • 省略了 ID、SIZE、BURST 等信号以节省逻辑资源(注释中明确说明)
  • x4 版本扩展为 4 组独立的 scalar/status 寄存器,每通道独立控制

3. data_fifo_krnl.sv

简化的数据通路内核,用于演示 loopback:

// 结构:RX_FIFO → 内部连线 → TX_FIFO
axis_data_fifo_0 rx_fifo_0 (...);  // 接收外部数据
axis_data_fifo_0 tx_fifo_0 (...);  // 发送数据到外部

关键特性:

  • 使用 ap_ctrl_none 执行模型——无需主机启动,上电即运行
  • 两个 FIFO 背靠背连接形成 loopback
  • 实际应用中应替换为真正的处理逻辑

4. IP 生成脚本 (gen_ip_x1.tcl, gen_ip_x4.tcl)

xxv_ethernet IP 配置要点:

# 通用配置
CONFIG.LINE_RATE           10          ;# 10Gbps
CONFIG.BASE_R_KR          BASE-R       ;# 使用 BASE-R 模式
CONFIG.INCLUDE_AXI4_INTERFACE 0        ;# 禁用 AXI4-MM DMA 接口,仅用 Stream
CONFIG.ENABLE_PIPELINE_REG 1           ;# 启用流水线寄存器提升时序

# 板卡特定配置(以 U200 为例)
CONFIG.GT_REF_CLK_FREQ    161.1328125  ;# 精确参考时钟频率
CONFIG.GT_GROUP_SELECT    Quad_X1Y12   ;# GT Quad 选择
CONFIG.LANE1_GT_LOC       X1Y48        ;# 具体 GT 位置

axis_data_fifo 配置:

CONFIG.IS_ACLK_ASYNC      1            ;# 异步时钟模式
CONFIG.TDATA_NUM_BYTES    8            ;# 64-bit 数据宽度
CONFIG.FIFO_MODE          2            ;# 特定 FIFO 模式
CONFIG.HAS_TKEEP          1            ;# 支持字节使能
CONFIG.HAS_TLAST          1            ;# 支持包边界指示

数据流分析

接收路径 (Network → FPGA)

QSFP28 → GTY (gt_rxp/n) → xxv_ethernet → RX_FIFO → rx_axis → data_fifo_krnl
                                              ↓
                                         stat_rx_block_lock → 控制寄存器
  1. 物理层:光/电信号通过 QSFP28 进入 GTY 收发器
  2. PCS/MAC 层xxv_ethernet IP 完成解码、对齐、CRC 校验
  3. FIFO 缓冲axis_data_fifo 吸收时钟域差异和突发流量
  4. 流式输出:标准的 AXI4-Stream 接口提供给下游逻辑

发送路径 (FPGA → Network)

data_fifo_krnl → tx_axis → TX_FIFO → xxv_ethernet → GTY (gt_txp/n) → QSFP28
  1. 流式输入:上游逻辑通过 AXI4-Stream 提供数据
  2. FIFO 缓冲:平滑数据流,处理反压 (backpressure)
  3. PCS/MAC 层:添加前导码、FCS,编码后发送
  4. 物理层:GTY 将并行数据转换为高速串行信号

控制路径 (Host → Kernel)

XRT → xclbin → s_axi_control → ethernet_control_s_axi → scalar → xxv_ethernet
                                                        → rx_block_lock (回读)

系统集成:连接配置详解

connectivity_x1.cfg 解析

[connectivity]
# 内核实例化声明
nk=ethernet_krnl_axis_x1:1:eth0    # 类型:数量:实例名
nk=data_fifo_krnl:1:df0

# AXI-Stream 连接:以太网 RX → FIFO RX
stream_connect=eth0.rx0_axis:df0.rx_axis
# AXI-Stream 连接:FIFO TX → 以太网 TX
stream_connect=df0.tx_axis:eth0.tx0_axis

# === GT 专用信号连接(平台相关)===
# Free-running 时钟连接(用于 GT 初始化期间的稳定时钟源)
connect=eth0/clk_gt_freerun:ii_level0_wire/ulp_m_aclk_freerun_ref_00

# GT 参考时钟(来自板载晶振,经平台路由)
connect=io_clk_qsfp_refclka_00:eth0/gt_refclk

# GT 数据端口(连接到物理 QSFP 接口)
connect=eth0/gt_port:io_gt_qsfp_00

connectivity_x4.cfg 差异点

# 4个以太网通道 + 4个 FIFO 实例
nk=ethernet_krnl_axis_x4:1:eth0
nk=data_fifo_krnl:4:df0.df1.df2.df3

# 每通道独立的 stream 连接
stream_connect=eth0.rx0_axis:df0.rx_axis
stream_connect=eth0.rx1_axis:df1.rx_axis
stream_connect=eth0.rx2_axis:df2.rx_axis
stream_connect=eth0.rx3_axis:df3.rx_axis
stream_connect=df0.tx_axis:eth0.tx0_axis
stream_connect=df1.tx_axis:eth0.tx1_axis
stream_connect=df2.tx_axis:eth0.tx2_axis
stream_connect=df3.tx_axis:eth0.tx3_axis

关键设计决策与权衡

1. 为什么选择 RTL Kernel 而非 HLS?

决策:使用 SystemVerilog/Verilog 手写 RTL 而非 C++/OpenCL HLS

理由

  • GTY 接口是高度专用的硬件资源,需要精确的引脚控制和时序约束
  • xxv_ethernet IP 的集成需要精细的端口映射和参数配置
  • RTL 提供了对 AXI-Stream 握手信号的完全控制

代价

  • 开发门槛更高,需要硬件设计经验
  • 调试复杂度增加(需要理解波形和时序)

2. 为什么使用 ap_ctrl_hs 而非 ap_ctrl_chain

决策:以太网内核使用 ap_ctrl_hs(单次执行),FIFO 内核使用 ap_ctrl_none

理由

  • 以太网内核需要显式的启动/停止控制来进行链路初始化和复位
  • 控制寄存器需要运行时动态修改(如设置环回模式)
  • FIFO 是纯数据通路,无需状态机控制

3. 为什么采用双 FIFO 结构?

决策data_fifo_krnl 中包含两个独立的 axis_data_fifo 实例

理由

  • 物理隔离收发路径,避免 head-of-line blocking
  • 允许独立的时钟门控和复位控制
  • 符合 AXI-Stream 的单向流语义

4. 平台可移植性策略

决策:通过 Tcl 脚本中的条件分支支持多板卡

if {[string compare -nocase $board "u200"] == 0} {
    # U200 特定配置
} elseif {[string compare -nocase $board "u250"] == 0} {
    # U250 特定配置
}

权衡

  • 优点:一份源码适配多款 Alveo 卡
  • 代价:新增板卡需要修改脚本并验证时序

5. 省略 AXI4 内存映射接口

决策CONFIG.INCLUDE_AXI4_INTERFACE {0}

理由

  • 本设计专注于纯流式处理(类似 SmartNIC 的数据面)
  • 避免了复杂的 DMA 描述符管理
  • 数据直接流经 FIFO,不经过 DDR

替代方案:若需要大包缓冲或复杂调度,可启用 AXI4-MM 接口连接 DDR


新贡献者必读:陷阱与注意事项

🔴 关键前提条件

  1. 许可证要求:需要 xxv_eth_mac_pcsx_eth_mac 两个 IP 许可证
  2. 物理连接:需要实际的光模块和光纤/网线进行测试
  3. 平台版本:确保 platform 版本与 connect= 语句中的信号名匹配

⚠️ 常见错误

1. GT 时钟连接错误

# 错误:使用了错误的时钟名
connect=eth0/clk_gt_freerun:wrong_clock_name

# 正确:使用 platforminfo 命令查询正确的信号名
# platforminfo -p xilinx_u200_gen3x16_xdma_1_202110_1 -v

2. 参考时钟频率不匹配

不同板卡的 GT 参考时钟频率可能不同:

  • U200/U250/U50: 161.1328125 MHz
  • U280: 156.25 MHz

使用错误的频率会导致链路无法锁定。

3. GT 位置冲突

每个 GT Quad 有固定的物理位置,两个设计不能分配到重叠的 GT。检查 LANE1_GT_LOC 等参数。

4. 复位顺序敏感

// 注意复位信号的依赖关系
areset <= ~ap_rst_n || sys_reset;           // 组合复位
fifo_resetn[ii] <= !(areset || scalar[ii][8]); // FIFO 单独复位

必须先释放 areset,再释放 fifo_resetn,否则可能导致 FIFO 处于不确定状态。

🛠️ 调试技巧

  1. 检查 rx_block_lock:读取控制寄存器 0x14,bit0 应该为 1 表示链路已锁定
  2. 使用 GT 环回模式:设置 scalar00[2:0] 为 3'b010 (近端 PCS 环回) 进行自测
  3. Vivado ILA:在 _x/link/vivado/vpl/prj/prj.xpr 中添加 Integrated Logic Analyzer
  4. 查看实现结果:检查 xxv_ethernet 的 placement 是否符合预期

📋 扩展指南

若要基于此设计开发真实应用:

  1. 替换 data_fifo_krnl:插入你的处理逻辑(如协议解析、加密、压缩等)
  2. 增加 DDR 访问:如需大包缓冲,添加 m_axi 接口和 DDR 控制器
  3. 多队列支持:参考 x4 设计,扩展更多独立的数据通路
  4. 中断支持:当前设计使用轮询,可添加 interrupt 接口实现事件驱动

文件清单

文件 用途
rtl/ethernet_krnl_axis_x1.sv 单通道以太网内核 RTL
rtl/ethernet_krnl_axis_x4.sv 四通道以太网内核 RTL
rtl/ethernet_control_s_axi_x1.v 单通道 AXI-Lite 控制器
rtl/ethernet_control_s_axi_x4.v 四通道 AXI-Lite 控制器
rtl/data_fifo_krnl.sv Loopback FIFO 内核 RTL
gen_ip_x1.tcl / gen_ip_x4.tcl IP 生成脚本
pack_eth_x1_kernel.tcl / pack_eth_x4_kernel.tcl 内核打包脚本
pack_data_fifo_kernel.tcl FIFO 内核打包脚本
connectivity_x1.cfg / connectivity_x4.cfg Vitis 链接配置
Makefile 构建流程控制

子模块文档

本模块包含以下子模块,每个都有详细的独立文档:

子模块 文档链接 描述
connectivity_x1 connectivity_x1 配置详解 单通道以太网连接配置
connectivity_x4 connectivity_x4 配置详解 四通道以太网连接配置

相关模块


总结

alveo_ethernet_kernel_connectivity 模块是一个方法论示范,它证明了:

在 Vitis 流程中集成 GTY 收发器并非黑魔法——只要正确处理 gt_portgt_refclkclk_gt_freerun 三个关键接口,其余部分与普通 RTL Kernel 无异。

这个设计的优雅之处在于其分层抽象

  • 底层:xxv_ethernet IP 隐藏了 PCS/MAC 的复杂性
  • 中层:RTL wrapper 提供标准化的 AXI-Stream 接口
  • 上层:Vitis 工具链处理平台连接和比特流生成

对于新加入团队的工程师,建议按以下顺序学习:

  1. 通读本文档理解架构
  2. 阅读 README.md 了解构建流程
  3. 研究 connectivity_x1.cfg 理解信号连接
  4. 在 Vivado 中打开实现后的设计查看实际布线
  5. 尝试修改 data_fifo_krnl 加入简单逻辑(如计数器、包头解析)
On this page