基于FPGA实现Aurora协议,概念 FPGA实现Aurora协议完整指南Aurora协议是Xilinx开发的一种轻量级、可扩展的高速串行通信协议专为FPGA之间的点对点数据传输而设计。本文将极其详细地讲解如何基于FPGA实现Aurora协议从原理到实战让你彻底掌握这一关键技术。一、Aurora协议概述1.1 什么是Aurora协议Aurora是一个用于在点对点串行链路间移动数据的可扩展轻量级链路层协议。它由Xilinx开发为物理层提供透明接口让专有协议或业界标准协议能方便地使用FPGA的高速收发器资源。核心特点高带宽仅受限于收发器的数据速率支持1~16个通道绑定实现更高的总带宽支持全双工和单工通信模式无限帧尺寸灵活组帧小型逻辑封装采用标准的AXI4-Stream接口内置流控和热插拔支持1.2 Aurora的两种编码方式Aurora协议在Xilinx FPGA上有两种实现方式特性Aurora 8B/10BAurora 64B/66B编码效率80%20%开销约96.97%3.125%开销线速率范围0.5 Gbps ~ 6.6 Gbps更高可达10GbpsDC平衡通过编码本身保证通过加扰保证适用场景芯片间、板间短距离通信背板、长距离传输Aurora 8B/10B将8bit数据编码成10bit码字传输尽量平衡数据中0和1的个数以实现DC平衡连续的1或0不超过5位。这种编码方式的效率是80%意味着线速率3.125Gbps时有效数据带宽为2.5Gbps。二、Aurora协议架构深度解析2.1 分层架构Aurora协议建立在GT高速收发器之上可分为两个核心层次┌─────────────────────────────────────┐ │ 用户应用层 │ ├─────────────────────────────────────┤ │ Aurora 链路层协议 │ │ (帧封装/解封、流控、初始化) │ ├─────────────────────────────────────┤ │ PCS (物理编码子层) │ │ (8B/10B编解码、通道绑定、对齐) │ ├─────────────────────────────────────┤ │ PMA (物理介质适配层) │ │ (串并转换、时钟恢复、驱动) │ ├─────────────────────────────────────┤ │ GT收发器硬核 │ └─────────────────────────────────────┘PMA层Physical Media Attachment串行器/解串器SerDes将并行数据转换为高速串行流时钟数据恢复CDR从串行数据中提取时钟差分驱动与接收处理实际电信号PCS层Physical Coding Sublayer8B/10B编解码保证DC平衡提供足够边沿密度通道绑定多通道对齐帧封装添加帧头SCP、帧尾ECP和空闲码2.2 数据发送与接收流程发送流程用户数据 → 串行信号用户数据 → Padding填充 → 链路层封装 → 8B/10B编码 → 串行化 → 差分输出Padding填充数据以2个symbols为基础发送若数据为奇数个字节需填充1个字节通常为0x9C链路层封装添加帧头SCPStart of Channel Protocol2字节和帧尾ECPEnd of Channel Protocol2字节8B/10B编码8位数据编码为10位码字保持DC平衡串行化与时钟编码将并行数据转为串行比特流发送接收流程串行信号 → 用户数据差分输入 → 解串 → 8B/10B解码 → 链路层剥离 → Padding剥离 → 用户数据三、Aurora IP核的两种数据接口Aurora IP核提供两种数据传输接口Framing接口帧接口和Streaming接口流接口。3.1 Framing接口帧接口Framing接口保留帧的概念IP核自动处理帧边界适合需要明确帧结构的数据传输。发送端信号信号方向含义s_axi_tx_tdata用户→IP发送数据s_axi_tx_tvalid用户→IP数据有效标志s_axi_tx_treadyIP→用户IP准备好接收数据s_axi_tx_tlast用户→IP当前是帧最后一个数据s_axi_tx_tkeep用户→IP最后一个数据的有效字节指示接收端信号信号方向含义m_axi_rx_tdataIP→用户接收数据m_axi_rx_tvalidIP→用户数据有效标志m_axi_rx_tlastIP→用户当前是帧最后一个数据m_axi_rx_tkeepIP→用户最后一个数据的有效字节指示Framing接口帧结构帧开始SOF添加2字节SCP码组帧结束EOF添加2字节ECP码组数据不可用时插入空闲码组用户侧收发代码示例可直接复用下面给出基于 Framing 接口的用户侧 Verilog 实现。假设Lane Width 4 bytes即tdata为 32bit、tkeep为 4bit用户时钟为user_clk。// // TX 侧按 AXI4-Stream 握手发送一帧数据 // 帧长 FRAME_LEN 个 32bit 字最后一拍用 tlast 标记帧尾 // module aurora_tx_frame #( parameter FRAME_LEN 16 // 一帧包含的 32bit 字数 )( input wire user_clk, input wire user_rst, // 高有效复位 input wire tx_start, // 单周期脉冲触发发送一帧 input wire [31:0] tx_data, // 待发送数据可由 FIFO/ROM 提供 output reg tx_busy, // 正在发送标志 // 连接到 Aurora IP 的 TX 接口 output reg [31:0] s_axi_tx_tdata, output reg s_axi_tx_tvalid, input wire s_axi_tx_tready, output reg s_axi_tx_tlast, output reg [3:0] s_axi_tx_tkeep ); reg [15:0] word_cnt; always (posedge user_clk) begin if (user_rst) begin s_axi_tx_tvalid 1b0; s_axi_tx_tdata 32d0; s_axi_tx_tlast 1b0; s_axi_tx_tkeep 4hF; word_cnt 16d0; tx_busy 1b0; end else begin // 启动一帧发送 if (tx_start !tx_busy) begin tx_busy 1b1; s_axi_tx_tvalid 1b1; s_axi_tx_tdata tx_data; s_axi_tx_tlast (FRAME_LEN 1); s_axi_tx_tkeep 4hF; // 整字有效 word_cnt 16d1; end // 握手成功tvalid tready 同时为高时数据被接收 else if (s_axi_tx_tvalid s_axi_tx_tready) begin if (word_cnt FRAME_LEN - 1) begin // 最后一拍已发出撤销 tvalid s_axi_tx_tvalid 1b0; s_axi_tx_tlast 1b0; tx_busy 1b0; word_cnt 16d0; end else begin word_cnt word_cnt 1b1; s_axi_tx_tdata tx_data; // 下一拍数据 s_axi_tx_tlast (word_cnt 1 FRAME_LEN - 1); s_axi_tx_tkeep 4hF; end end end end endmodule// // RX 侧接收 Framing 帧并拼接 tdata // 按 tkeep 剔除最后一拍中的无效字节输出完整字节流 // module aurora_rx_frame ( input wire user_clk, input wire user_rst, // 来自 Aurora IP 的 RX 接口 input wire [31:0] m_axi_rx_tdata, input wire m_axi_rx_tvalid, input wire m_axi_rx_tlast, input wire [3:0] m_axi_rx_tkeep, // 拼接后的字节流输出 output reg [7:0] rx_byte, output reg rx_byte_vld, output reg rx_frame_done ); integer i; always (posedge user_clk) begin if (user_rst) begin rx_byte 8d0; rx_byte_vld 1b0; rx_frame_done 1b0; end else begin rx_byte_vld 1b0; rx_frame_done 1b0; if (m_axi_rx_tvalid) begin // 逐字节输出tkeep 决定该字节是否有效 // tkeep[0] 对应 tdata[7:0]tkeep[3] 对应 tdata[31:24] for (i 0; i 4; i i 1) begin if (m_axi_rx_tkeep[i]) begin rx_byte m_axi_rx_tdata[i*8 : 8]; rx_byte_vld 1b1; end end // tlast 有效表示一帧结束 if (m_axi_rx_tlast) rx_frame_done 1b1; end end end endmodule关于tkeep在最后一拍的处理方式tkeep是字节有效指示位宽等于tdata字节数4 字节宽度时为 4bit每一位对应tdata中的一个字节tkeep[0]→tdata[7:0]tkeep[1]→tdata[15:8]依此类推。非最后一拍tkeep必须为全 14hF表示 4 个字节全部有效。最后一拍帧长度不一定是 4 的整数倍此时tkeep只把实际有效的低位字节置 1。例如帧尾只剩 2 个有效字节则tkeep 4b0011接收端只能取tdata[15:0]高 16bit 为填充数据需丢弃。发送侧若帧长不是 4 字节整数倍需在最后一拍把无效字节填任意值常用0x00或0x9C并把对应tkeep位清 0同时拉高tlast。接收侧必须用tkeep做字节级过滤不能直接按 4 字节整字写入 FIFO否则会把填充字节当成有效数据导致帧内容错位。注意tkeep只在tvalid tready握手成功的那一拍才被采样未握手时保持原值即可。3.2 Streaming接口流接口Streaming接口去掉了帧的概念数据像流水一样连续传输更加简洁高效。发送端信号s_axi_tx_tdata发送数据s_axi_tx_tvalid数据有效s_axi_tx_treadyIP准备好接收端信号m_axi_rx_tdata接收数据m_axi_rx_tvalid数据有效使用场景对比Framing接口适合需要明确帧边界的应用如网络数据包Streaming接口适合连续数据流如视频、采集数据用户侧收发代码示例可直接复用下面给出基于 Streaming 接口的用户侧 Verilog 实现。同样假设Lane Width 4 bytes即tdata为 32bit用户时钟为user_clk。与 Framing 接口最大的区别是没有tlast/tkeep数据是无限长的连续流因此发送侧只需处理tvalid/tready握手与背压接收侧只需在tvalid有效时采样tdata。// // TX 侧Streaming 连续发送模块 // 从上游 FIFO 取数按 AXI4-Stream 握手推给 Aurora IP // 关键差异无 tlast / tkeep数据流无边界永不主动结束 // module aurora_tx_stream ( input wire user_clk, input wire user_rst, // 高有效复位 // 上游数据源FIFO 读口 input wire [31:0] fifo_dout, input wire fifo_empty, output reg fifo_rd_en, // 连接到 Aurora IP 的 TX 接口Streaming 无 tlast/tkeep output reg [31:0] s_axi_tx_tdata, output reg s_axi_tx_tvalid, input wire s_axi_tx_tready ); // 背压处理只有 tready 为高IP 能接收且上游有数据时才推进 // 若 tready 拉低tvalid 与 tdata 必须保持不变等待握手 always (posedge user_clk) begin if (user_rst) begin s_axi_tx_tvalid 1b0; s_axi_tx_tdata 32d0; fifo_rd_en 1b0; end else begin fifo_rd_en 1b0; if (!s_axi_tx_tvalid) begin // 空闲态上游有数据就装载一拍并拉高 tvalid if (!fifo_empty) begin s_axi_tx_tdata fifo_dout; s_axi_tx_tvalid 1b1; fifo_rd_en 1b1; // 弹出该数据 end end else if (s_axi_tx_tready) begin // 握手成功本拍已被 IP 接收尝试装载下一拍 if (!fifo_empty) begin s_axi_tx_tdata fifo_dout; fifo_rd_en 1b1; // tvalid 保持为 1实现背靠背连续传输 end else begin s_axi_tx_tvalid 1b0; // 上游断流撤销 tvalid end end // elsetvalid1 且 tready0保持 tdata/tvalid 不变背压等待 end end endmodule// // RX 侧Streaming 连续接收模块 // tvalid 有效即采样 tdata直接写入下游 FIFO // 关键差异无 tlast/tkeep不需要帧边界判断与字节过滤 // module aurora_rx_stream ( input wire user_clk, input wire user_rst, // 来自 Aurora IP 的 RX 接口Streaming 无 tlast/tkeep input wire [31:0] m_axi_rx_tdata, input wire m_axi_rx_tvalid, // 下游 FIFO 写口 output reg [31:0] fifo_din, output reg fifo_wr_en, input wire fifo_full ); always (posedge user_clk) begin if (user_rst) begin fifo_din 32d0; fifo_wr_en 1b0; end else begin fifo_wr_en 1b0; // tvalid 为高表示 IP 输出了一拍有效数据直接整字写入 // 无需像 Framing 那样按 tkeep 逐字节过滤 if (m_axi_rx_tvalid !fifo_full) begin fifo_din m_axi_rx_tdata; fifo_wr_en 1b1; end // 若 fifo_full本拍数据被丢弃——实际工程中应通过 // Native Flow ControlUFC反压对端避免丢数 end end endmodule与 Framing 接口的关键差异无tlastStreaming 数据流没有帧边界发送侧不需要在最后一拍拉高tlast接收侧也无法判断一帧结束帧语义需由用户在数据内容中自行约定如加长度头。无tkeep数据始终按整字4 字节传输不存在最后一拍部分字节有效的问题接收侧可直接整字写入 FIFO无需字节级过滤。背压更关键由于没有帧边界一旦下游 FIFO 满而 IP 仍在推数据就会丢数。Streaming 模式下Flow Control选项不可用见 4.2 节因此必须保证下游消费带宽 ≥ 链路带宽或自行在用户侧实现反压/缓存。握手逻辑相同tvalid/tready的 AXI4-Stream 握手规则与 Framing 完全一致——tvalid拉高后必须保持到tready为高的那一拍期间tdata不得变化。四、IP核配置详细步骤4.1 新建工程与IP核定制步骤1创建Vivado工程打开Vivado创建新工程选择对应FPGA型号如xcvu9p-flga2104-2L-e或开发板如VCU118。步骤2添加Aurora IP核在IP Catalog中搜索Aurora 8B/10B双击打开配置界面。4.2 第一页配置核心参数物理层Physical Layer配置参数选项说明Lane Width2 bytes / 4 bytes链路位宽4字节可降低用户时钟频率Line Rate0.5~6.25 Gbps线速率根据PCB和连接器能力选择GT Refclk125MHz / 156.25MHz等GT收发器参考时钟与板卡匹配INIT clk≤ Refclk初始化时钟推荐50-100MHzDRP clk50MHz动态重配置时钟链路层Link Layer配置参数选项说明Dataflow ModeDuplex / Simplex TX / Simplex RX全双工/单工InterfaceFraming / Streaming数据接口类型Flow ControlNone / Native / User流控模式Streaming不可选Scrambler可选加扰减少EMILittle Endian Support可选小端模式建议勾选4.3 第二页配置GT位置选择根据FPGA芯片实际布局选择GT Quad和ChannelQuad选择FPGA有多个GT Quad每个Quad包含4个通道Channel选择在Quad内选择具体通道Refclk选择每个Quad有2路参考时钟输入4.4 第三页配置共享逻辑位置这是影响工程结构的关键选项选项说明适用场景Include Shared Logic in core共享逻辑在IP核内部单核设计简化操作Include Shared Logic in example design共享逻辑在例程中多核设计需要精细控制关键理解同一个Quad下的多个通道必须共用GT Common资源。如果需要在一个Quad中使用多个Aurora通道必须配置为一个主核带多个从核。4.5 生成示例设计IP核定制完成后右键点击IP核选择Open IP Example Design。Vivado会自动生成完整的示例工程包含数据生成模块frame_gen数据检查模块frame_checkSupport模块时钟、复位管理Testbench回环测试五、官方例程深度解析5.1 例程架构分析官方例程的层次结构如下aurora_8b10b_0_exdes (顶层) ├── support (核心模块) │ ├── clock_module # 时钟生成 │ ├── support_reset_logic # 复位逻辑 │ ├── gt_common_support # GT公共资源 │ └── aurora_8b10b_0 # IP核例化 ├── frame_gen (发送模块) # 生成测试数据 ├── frame_check (接收模块) # 校验接收数据 ├── LL_AXI (总线转换) # LL→AXI └── AXI_LL (总线转换) # AXI→LLTestbench结构例化两个Aurora模块形成回环测试模块A发送 → 模块B接收模块B发送 → 模块A接收5.2 Support模块解析Support模块是IP核例化的核心封装了clock_module处理用户时钟user_clk、初始化时钟init_clk、GT参考时钟support_reset_logic管理复位时序包括PMA初始化复位和软复位gt_common_supportGT Quad公共资源QPLL等5.3 数据生成模块frame_genframe_gen模块使用LFSR生成伪随机测试数据关键逻辑// 等待通道初始化完成 if (CHANNEL_UP) begin channel_up_cnt channel_up_cnt 1; if (channel_up_cnt 5b11111) dly_data_xfer 1b1; end // LFSR生成伪随机序列 lfsr_data {lfsr_data[14:0], lfsr_data[15] ^ lfsr_data[13]};5.4 数据检查模块frame_checkframe_check模块接收数据并与本地生成的LFSR序列比较// 数据校验 if (rx_data ! lfsr_data) begin error_flag 1b1; ERR_COUNT ERR_COUNT 1; end5.5 用户时钟频率计算用户时钟频率由线速率、编码效率和总线宽度决定用户时钟 线速率 × 编码效率 / 总线宽度bits示例计算线速率3.125Gbps4字节宽度编码效率 80% (8B/10B) 总线宽度 4 × 8 32 bits 用户时钟 3.125Gbps × 0.8 / 32 78.125 MHz 时钟周期 12.8ns这个计算结果可以在仿真中验证与实际波形一致。六、复位序列与时序6.1 上电复位序列Aurora IP核需要正确的复位时序才能正常工作channel_uplane_upreset_pbpma_initinit_clk / gt_refclk上电/电源channel_uplane_upreset_pbpma_initinit_clk / gt_refclk上电/电源阶段1上电pma_init / reset_pb 保持高电平复位有效阶段2时钟稳定等待 ≥ 10 个 init_clk 周期阶段3pma_init 拉低后PMA 开始初始化需保持 ≥ 1μs阶段4reset_pb 拉低软复位释放需在 pma_init 之后 ≥ 1μs阶段5链路建立A7 约 1msK7/V7 约 50μs上电电源与参考时钟开始建立1init_clk 稳定推荐 50~100MHz2gt_refclk 稳定125/156.25MHz偏差 ±300ppm3释放 pma_init拉低4释放 reset_pb拉低5lane_up 拉高各 Lane 对齐完成6channel_up 拉高链路建立成功7各阶段最小等待时间要求上电阶段pma_init与reset_pb必须保持高电平直到电源与gt_refclk完全稳定通常需等待电源纹波进入 ±5% 以内。时钟稳定阶段init_clk与gt_refclk稳定后至少再等待10 个init_clk周期约 100~200ns才能释放复位确保 GT 内部逻辑已获得稳定时钟。释放pma_init阶段pma_init拉低后PMA 初始化过程需保持≥ 1μs期间init_clk不得中断。释放reset_pb阶段reset_pb必须在pma_init拉低之后≥ 1μs再释放避免 PMA 尚未就绪就启动链路层复位。链路建立阶段lane_up先于channel_up拉高channel_up建立时间与器件相关——Artix-7 约1msKintex-7/Virtex-7 约50μs仿真时需预留足够时间。正确操作步骤上电时pma_init和reset_pb信号保持高电平等待INIT_CLK和GT_REFCLK稳定将pma_init置为低电平将reset_pb置为低电平等待channel_up和lane_up变为高电平表示链路建立成功6.2 复位注意事项INIT_CLK在GT复位期间必须保持稳定GT_REFCLK在上电期间需稳定频率偏差应小于±300ppm复位释放顺序先释放pma_init再释放reset_pb七、多核配置与GT主从概念7.1 问题场景当一个Quad中有多个通道需要配置为独立的Aurora核时不能简单地分别配置——因为同一个Quad下的通道必须共用GT Common资源。7.2 主从核配置主核Master配置Shared Logic选择Include Shared Logic in core负责例化GT Common资源从核Slave配置Shared Logic选择Include Shared Logic in example design不例化GT Common直接使用主核提供的时钟资源连接方式主核提供: gt_qpllclk, gt_qpllrefclk, gt_qplllock ↓ ↓ ↓ 从核1 从核2 ... 从核N7.3 配置示例以ZCU106的FMC接口4路GTH为例需要配置为1个主核3个从核在Vivado中分别创建4个Aurora IP核实例将第一个实例的Shared Logic设为in core主核其余三个实例设为in example design从核在顶层手动连接主核输出的QPLL时钟到各从核八、仿真与调试8.1 仿真避坑指南1. 器件选择影响仿真速度不同FPGA系列的仿真模型差异很大Artix-7 (A7)channel_up可能需要长达1ms才能建立Kintex-7 (K7)约50μs建立Virtex-7 (V7)约50μs建立如果仿真时间过长建议改用K7或V7器件模型测试。2. 仿真观察要点确认channel_up信号在合理时间内变高确认user_clk频率符合计算值确认发送数据和接收数据一致8.2 硬件调试信号完整性检查使用示波器测量GT参考时钟频率和抖动检查差分信号眼图是否张开确认电源纹波在可接受范围状态指示信号lane_up单条Lane初始化完成channel_up整个通道初始化完成hard_err硬错误物理层soft_err软错误编解码错误8.3 回环测试官方例程默认配置为外部回环测试模块A的TX连接模块B的RX模块B的TX连接模块A的RX验证数据收发一致性通过ILA观察波形确认发送数据与接收数据匹配。九、实际应用案例Aurora光纤通信9.1 系统架构以两个FPGA通过SFP光模块进行光纤通信为例FPGA-A FPGA-B ┌──────────────┐ ┌──────────────┐ │ 用户数据源 │ │ 用户数据接收 │ │ ↓ │ │ ↑ │ │ TX FIFO │ │ RX FIFO │ │ ↓ │ │ ↑ │ │ Aurora IP │───光纤───→ │ Aurora IP │ │ (Master) │←───光纤─── │ (Slave) │ └──────────────┘ └──────────────┘9.2 时钟设计要点参考时钟SFP光模块通常需要125MHz或156.25MHz参考时钟用户时钟由Aurora IP核的tx_out_clk提供通过BUFG缓冲后驱动用户逻辑跨时钟域用户逻辑时钟与系统时钟可能不同需使用异步FIFO隔离9.3 延迟评估实测3.125Gbps Aurora链路的延迟组成TX FIFO约84nsAurora IP核处理约424nsRX FIFO约52ns总延迟约560ns单程十、总结与最佳实践10.1 配置清单步骤关键操作注意事项1选择线速率和Lane宽度考虑编码开销20%2配置GT参考时钟必须与板卡匹配3选择接口模式Streaming更简单Framing有帧边界4决定共享逻辑位置多核必须正确配置主从5生成示例设计学习参考6添加用户数据源替换frame_gen模块10.2 常见问题排查问题可能原因解决方案channel_up不拉高复位时序错误检查pma_init/reset_pb释放顺序仿真时间过长器件模型差异换用K7/V7仿真误码率高信号完整性差调整GT均衡参数多核冲突共享逻辑配置错误设置主从核模式10.3 最佳实践建议始终从官方例程开始Xilinx提供的例程是最可靠的起点优先使用Streaming接口除非需要明确的帧边界否则Streaming更简洁正确设计复位时序上电后先释放pma_init再释放reset_pb注意时钟域隔离用户逻辑与Aurora接口可能在不同时钟域需使用FIFO多核务必用主从模式同一个Quad的多个通道必须共享GT CommonAurora协议作为Xilinx FPGA上的轻量级高速串行通信方案学习曲线平缓官方支持完善。掌握了本文的内容你已经具备了独立实现Aurora通信的能力。如果在实践中遇到问题建议从官方例程开始调试逐步添加自定义功能这是最稳妥的开发路径。