ADRV9371与DVB-S2 IP集成:从JESD204B采样到基带帧处理

发布时间:2026/9/13 9:08:09
ADRV9371与DVB-S2 IP集成:从JESD204B采样到基带帧处理 简介面向无线通信与卫星通信开发者的 ADRV9371 与 DVB-S2IP 集成示例包以 Verilog 和 Tcl 为主要载体完整演示 RF 收发器与第二代数字视频广播卫星接口的对接流程适合需要设计 Zynq/FPGA 射频链路的工程师学习参考。包体共 1826 个文件压缩后约 2.95MB其中包含 569 个 Verilog 源文件、533 个 Tcl 脚本、297 个 Makefile、177 个 XDC 约束和 68 个 Markdown 文档另有大量 *_tb 仿真测试平台覆盖 JESD204B 寄存器配置、DMA 读写、加扰/解扰、8b/10b 编解码等关键模块便于对照验证。资源聚焦 ADRV9371 与 DVB-S2IP 集成中的时钟同步、接口配置、功率增益控制、错误检测与恢复等核心问题可通过 Tcl 脚本完成环境配置、FPGA 编译与仿真调试。源码目录以功能模块划分包含完整 Testbench可帮助开发者快速理解 ADRV9371 数字接口时序并迁移到自身项目中。已有 151 人学习下载适合具备 FPGA/Verilog 基础、正在从事卫星通信或软件无线电开发的工程师深入研读。1. ADRV9371 与 DVB-S2 IP 集成示例从射频采样到基带帧的一条完整链路ADRV9371 把射频信号变成 JESD204B 链路里的 IQ 采样流DVB-S2 IP 把比特变成带纠错和星座映射的符号帧。把两者接在一起看起来只是一根 AXI-Stream 总线的事实际上要同时解决时钟关系、位宽转换、帧同步和射频配置四类问题。这类集成示例通常以 Verilog 数据通路和 Tcl 工程脚本的形式出现追求的是一套能复用的参考框架而不是单一功能仿真。适合做卫星通信地面站、射频前端验证平台以及在 Zynq 上做 AD9371 相关基带开发的工程师。标题里没有算法细节但真正决定集成成败的参数全藏在采样率、符号率和 JESD204B LMFC 的整数倍关系里。下面按数据流方向把这条链路拆开讲。2. ADRV9371 的 JESD204B 数据通路与 DVB-S2 IP 的接口模型2.1 ADRV9371 在收发链路里的角色射频采样与 IQ 流之间的移动边界ADRV9371 是 ADI 的一款宽带收发器射频覆盖范围在 400 MHz 到 6 GHz片上集成 12 位 ADC 与 DAC、模拟抗混叠滤波、数字上变频DUC和下变频DDC。对 FPGA 工程师来说它更像一个带 SPI 配置口的黑盒配置好本振频率、衰减和数字增益后发射方向就按照 JESD204B 协议把 IQ 采样流交给链路接收方向则相反。这里要区分两个概念DVB-S2 信号里的“符号”和 ADRV9371 数据通路里的“采样”。DVB-S2 的符号是星座点QPSK 每符号对应 2 bit32APSK 对应 5 bit而 ADRV9371 的采样是一对固定的 16 bit 复数数据。符号率和采样率的比值必须是一个确定整数否则成型滤波之后的频谱会出现周期性混叠。常见做法是让 ADRV9371 的 DAC 采样率等于符号率的 4 倍或 8 倍DVB-S2 IP 内部完成半带滤波和插值。注意ADRV9371 的 JESD204B 链路工作在 subclass 1必须提供 SYSREF 来对齐 LMFC。SYSREF 和 device clock 的来源必须在硬件设计阶段就规划好不能靠软件补偿。2.2 DVB-S2 IP 的数据接口AXI-Stream 与 BBFRAME 对齐规则一般 DVB-S2 调制 IP 输出的是 AXI-Stream 总线数据位宽为 16 位或 32 位。16 位格式下高字节是 I 路、低字节是 Q 路数据点按符号率产生。IP 核内部会把 MPEG-TS 包组装成 BBFRAME经过 BCH 与 LDPC 编码后形成 64800 bit 的 normal FECFRAME 或 16200 bit 的 short FECFRAME再映射成对应调制方式的符号序列。IP 在输出时会用 tlast 标出每一帧的边界用 tuser 带出帧类型或 MODCOD 信息。我在集成时习惯把 tuser 信号同步到 ADRV9371 的采样时钟域里用作系统级的帧计数。若 DVB-S2 IP 不自动插入导频而接收端又需要导频辅助同步可以在外部加一个导频插入模块但要注意导频符号会拉高有效符号率后端滤波器带宽要按含导频的符号率计算。2.3 JESD204B 采样率、SYSREF 与 DVB-S2 符号率的对齐关系下面给出一组比较典型的设计参数假设 DVB-S2 符号率取 10 MSps过采样倍数取 8则 DAC 采样率为 80 MSps。JESD204B 的 lane rate 由采样率、样本位宽和 lane 数量决定。参数数值说明DVB-S2 符号率 Rs10 MSps取决于 MODCOD 与可用带宽过采样倍数8DVB-S2 IP 内部插值后的输出率DAC 采样率 Fdac80 MSpsRs × 8JESD204B 样本位宽16 bitI/Q 各 16 bitJESD204B lane 数4子类 1K32SYSREF 频率1.25 MHz由 LMFC 频率推导这个组合下 SYSREF 必须与 Fdac 分频后的 LMFC 对齐。我在调试时见过不少集成问题都出在“寄存器里采样率配对了但 SYSREF 和 device clock 的相位跑了”这种场合。先用 ILA 或示波器确认 SYNC 引脚不再周期性拉低再去查数据内容顺序不要反过来。SYSREF 的建立时间余量不足时可以在 ADRV9371 寄存器里微调 SYSREF 采样延迟而不是去改 FPGA 侧的约束。3. 用 Tcl 脚本在 Vivado 中搭建 ADRV9371 与 DVB-S2 的集成工程3.1 最小 Tcl 工程脚本create_project 到 add_files用 Tcl 脚本建工程的优势在于可复现机器换掉之后跑一遍脚本就能拿到一模一样的环境。下面是一段最小脚本完成建工程、加 RTL、加约束、指定顶层四件事# 最小可运行的 Vivado 工程创建脚本 set proj_name ad9371_dvbs2_demo set proj_dir ./${proj_name} set part xc7z045ffg900-2 # 若目录已存在则先删除避免增量合并带来的旧文件残留 if {[file exists $proj_dir]} { file delete -force $proj_dir } create_project $proj_name $proj_dir -part $part -force # 添加 RTL 源文件-norecurse 避免把子目录里不需要的文件一并加入 add_files -norecurse [glob ../rtl/*.v ../rtl/*.sv] # 添加 XDC 约束文件 add_files -fileset constrs_1 ../constrs/ad9371_dvbs2_top.xdc # 指定顶层模块 set_property top ad9371_dvbs2_top [current_fileset] update_compile_order -fileset sources_1 # 打印工程根目录便于后续日志定位 puts project root: [pwd]脚本里的[pwd]打印的是当前工作目录。很多刚接触 Tcl 的工程师会用错相对路径原因就是add_files的相对路径是相对于 Vivado 启动目录而非脚本所在目录。稳妥写法是先cd到脚本目录再取绝对路径。整个过程和 Design CompilerDC里通过 source 读 Tcl 文件的方式类似理解了“工具驻留底层解释器、脚本只是批量喂命令”这一点就不会再纠结 GUI 里的按钮在哪里。3.2 例化 ADI axi_ad9371 与 DVB-S2 调制核的 Tcl 参数设置工程骨架搭好后下一步是例化 IP 核。ADI 官方提供 axi_ad9371 的 Vivado IP使用方式是在 Tcl 里设置参数后生成输出文件。# 例化 ADI axi_ad9371 IP create_ip -name axi_ad9371 -vendor analog.com -library analog \ -version 1.0 -modules {rx tx} -dir ./ip set_property -dict [list \ CONFIG.DEVICE_TYPE ADRV9371 \ CONFIG.LANE_RATE 10.0 \ CONFIG.LANE_COUNT 4 \ CONFIG.SAMPLES_PER_FRAME 32 \ ] [get_ips axi_ad9371] # 例化 DVB-S2 调制 IP这里使用工程内已有的 dvbs2_mod 核 create_ip -name dvbs2_mod -vendor xilinx.com -library ip \ -version 1.0 -dir ./ip set_property -dict [list \ CONFIG.MODCOD 12 \ CONFIG.FECFRAME NORMAL \ CONFIG.SYMBOL_RATE 10000000 \ CONFIG.INTERPOLATION 8 \ ] [get_ips dvbs2_mod]CONFIG.MODCOD 的取值与 DVB-S2 标准里 PLHEADER 的 5 bit MODCOD 字段一一对应低段数值对应 QPSK中段对应 8PSK具体索引要以所用 IP 核文档为准不同核的编码方式并不统一。关键参数是INTERPOLATION它必须与上一节里的过采样倍数一致否则 DVB-S2 核输出的符号速率和 axi_ad9371 期望的采样速率对不上链路表现为星座图旋转或误码率居高不下。3.3 XDC 约束文件生成与工程复用的注意点XDC 约束在集成示例里容易被当成最后一步实际应该先于综合规划。JESD204B 的收发时钟是高速差分时钟需要在 XDC 里显式声明create_clock并把 SYSREF 约束为周期信号DVB-S2 IP 的基带时钟通常是单端时钟由 MMCM/PLL 生成。# ad9371_dvbs2_top.xdc create_clock -name dev_clk -period 12.500 [get_ports dev_clk_p] create_clock -name ref_clk -period 5.000 [get_ports ref_clk_p] create_clock -name bb_clk -period 10.000 [get_pins mmcm_inst/CLKOUT0] set_input_delay -clock [get_clocks ref_clk] 0.100 [get_ports sysref_p]工程复用时最容易踩的坑是 IP 的-dir参数与源文件 glob 混在一起导致文件集合不完整。我一般会把 IP 单独放在ip/目录、用户 RTL 放在rtl/脚本里按目录分开 add_files避免后加的文件覆盖掉 IP 生成的文件。set_input_delay那条约束是针对 SYSREF 的采样窗口数值要按 PCB 走线长度换算不要随手抄。4. 用 Verilog 打通 DVB-S2 基带帧与 ADRV9371 采样通道的数据通路4.1 异步 FIFO 处理多字节收发与跨时钟域DVB-S2 基带时钟和 JESD204B 用户时钟来自不同 PLL必须通过异步 FIFO 隔离。DVB-S2 的调制核输出通常一次给一个符号也就是 32 bitI/Q 各 16 bit而 ADRV9371 的数据接口在 4 lane 下经常按 128 bit 组织多字节收发的位宽转换和跨时钟域可以合并处理。// 异步 FIFODVB-S2 基带时钟 - ADRV9371 JESD 用户时钟 axis_data_fifo_0 u_bb2jesd ( .s_axis_aclk (clk_bb), // DVB-S2 基带时钟100 MHz .s_axis_tvalid (bb_tvalid), // 调制核符号有效 .s_axis_tready (bb_tready), // FIFO 反压 .s_axis_tdata (bb_tdata), // 32 bit: {I[15:0], Q[15:0]} .m_axis_aclk (clk_jesd), // JESD204B 用户时钟80 MHz .m_axis_tvalid (jesd_tvalid), .m_axis_tready (jesd_tready), .m_axis_tdata (jesd_tdata) // 32 bit宽度与上游保持一致 );axis_data_fifo_0是 Xilinx 的标准 IP内部用 BRAM 做指针同步tready反压机制天然适配 ADRV9371 可能出现的短暂背压。需要留意 FIFO 深度DVB-S2 是恒定码流ADRV9371 端如果因为链路重同步短暂暂停FIFO 溢出会丢帧。我一般把深度设到 4096同时保证调制核的 tready 常高。FIFO 的 tlast 要配置成 forward 模式透传到输出端这样下游才能识别帧边界。4.2 AXI-Stream 握手与 IQ 位宽转换的 Verilog 骨架DVB-S2 调制核与 FIFO 之间的 AXI-Stream 握手逻辑上是一个 valid-ready 交叉逻辑。为了避免组合逻辑环路valid 必须由寄存器打拍后产生ready 则由下游 FIFO 直接给出。// AXI-Stream valid 打拍避免组合环路 reg axis_valid_ff; always (posedge clk_bb) begin if (!rst_n) axis_valid_ff 1b0; else if (bb_tready) axis_valid_ff bb_tvalid; end assign bb_tvalid axis_valid_ff; // 32bit IQ 转为 128bit 四符号打包适配 JESD204B 用户数据宽度 reg [127:0] iq_packed; reg [1:0] pack_cnt; always (posedge clk_jesd) begin if (jesd_tvalid jesd_tready) begin iq_packed {iq_packed[95:0], jesd_tdata}; pack_cnt pack_cnt 1b1; end end这个代码片段把 4 个连续的 32 bit 符号在clk_jesd域里打包成 128 bit。打包计数器pack_cnt用来标记当前是第几个符号当 FIFO 把 tlast 透传过来时如果pack_cnt不是 3说明这一帧的符号数不是 4 的倍数需要做周期扩展或补零对齐。多字节收发在这种场景下的要点不是位宽扩展本身而是保证“第一个字节”对应的符号语义不漂移。4.3 用 verilog 计数器生成符号使能与帧定时DVB-S2 帧在调制前需要按物理层帧PLFRAME组织PLHEADER 固定 90 bit。当调制 IP 不代做 PL 组帧时用户逻辑需要自己维护一个帧计数器。下面是一段最简的符号使能计数器// 由 100 MHz 时钟分频生成 10 MSps 符号使能 localparam DIV_RATIO 100_000_000 / 10_000_000 - 1; // 9 reg [3:0] div_cnt; reg sym_ce; always (posedge clk_fast or negedge rst_n) begin if (!rst_n) begin div_cnt 0; sym_ce 0; end else if (div_cnt DIV_RATIO) begin div_cnt 0; sym_ce 1b1; end else begin div_cnt div_cnt 1b1; sym_ce 1b0; end end计数器的错误用法是把sym_ce直接当成时钟沿使用正确做法是当sym_ce为高时对数据进行采样也就是把时钟域内的“有效脉冲”当成数据有效信号。我见过有人在sym_ce的 if 分支里例化 FIFO导致跨时钟域标志位出现毛刺这种问题用 RTL 里的$display单步仿真是看不出来的必须上 ILA 抓实际波形。5. DVB-S2 调制参数与 ADRV9371 射频配置的对齐和排错5.1 MODCOD、FECFRAME 与符号率参数选择表DVB-S2 标准定义了多种 MODCOD。在 ADRV9371 这种宽带收发器上基带符号率通常不高于几十 MSps实际可选范围集中在 QPSK、8PSK 与 16APSK。MODCOD调制方式LDPC 码率典型场景0QPSK1/4雨衰严重的恶劣信道128PSK2/3高清卫星广播1816APSK3/4宽带 VSAT 下行2432APSK4/5高信噪比点对点链路选型时要注意FECFRAME 用 normal64800 bit时延迟更大但纠错增益更高short16200 bit适合低延迟链路。ADRV9371 的带宽要按含成型滤波滚降常见 0.2 到 0.35之后的占用带宽来算。符号率提高后ADC 采样率与输出数据率同步上涨需要确认 JESD204B lane rate 没有超过链路上限超过时只能降低过采样倍数或者改用频谱效率更高的调制方式。5.2 通过 SPI 初始化 ADRV9371 的 Verilog 配置状态机ADRV9371 的寄存器配置通过 SPI 接口完成FPGA 侧通常用一个小状态机写寄存器。其行为类似于低速串行外设和 UART 或 I2C 的时序表驱动方式相通核心是片选拉低、按位写地址和数据。// 极简 SPI 写状态机每状态传送 1 bit localparam IDLE 2d0, WR 2d1, DONE 2d2; reg [1:0] spi_state; reg [4:0] bit_idx; reg [23:0] spi_tx; always (posedge clk_spi) begin case (spi_state) IDLE: begin if (cfg_start) begin spi_tx {16h0021, 8h01}; // 地址 0x21 写入数据 0x01 bit_idx 5d23; spi_state WR; end end WR: begin sclk ~sclk; // 半周期后更新数据位 if (sclk) begin spi_tx {spi_tx[22:0], 1b0}; bit_idx bit_idx - 1b1; if (bit_idx 0) spi_state DONE; end end DONE: spi_state IDLE; endcase end这段代码的思路是每两个 sclk 沿发送一个 bit24 位数据占 48 个时钟周期。配置顺序上要先配 PLL 的参考时钟分频和 SYSREF 延迟再启用 JESD204B 链路最后打开发射或接收通道顺序反了容易触发 JESD204B 的 unexpected sync 中断。工程里真正的初始化序列会是几百条寄存器写入建议把寄存器表放到 ROM 或 Tcl 生成的头文件里不要在手写状态机里硬编码。5.3 常见失败JESD204B 失同步与 Verilog 仿真 license 错误集成调试中最常见的两个问题表现完全不同。JESD204B 失同步时链路层的 sync_n 会周期性拉低接收数据出现明显的错位。排查顺序按三步走用 ILA 同时采样 sysref 和 lmfc_counter确认二者相位是否固定检查 device clock 和 SYSREF 的约束是否正确重点看set_input_delay在 ADRV9371 寄存器里调整 SYSREF 采样延迟步进一般取 20 ps 到 40 ps。另一个高频报错是仿真阶段出现的17.1 error: failure to obtain a verilog simulation license。这类报错看起来像许可证缺失实际大多是仿真库没编译、或 Vivado 启动脚本里没有正确设置库路径。处理方式是确认环境变量指向统一安装目录然后运行compile_simlib重新编译仿真库。把这条命令写进 Tcl 启动脚本里比每次打开 GUI 后手工操作可靠得多。6. 用 ILA 探针与 Tcl 脚本验证 ADRV9371-DVB-S2 收发链路6.1 在 Verilog 顶层例化 ILA 观察星座图与同步头验证 DVB-S2 链路最直观的手段是在基带 IQ 信号上挂 ILA。把 ILA 的采样深度设为 16384触发条件设为tlast1就能看到完整一帧 PLFRAME 的 IQ 轨迹。// ILA 例化观察调制后的 IQ 与帧边界 ila_0 u_ila ( .clk (clk_jesd), .probe0 (jesd_tvalid), .probe1 (jesd_tlast), .probe2 (jesd_tdata) // 128 bit4 符号打包后的数据 );看波形时要在 ILA 窗口把数据格式改成 Signed Decimal再把高 64 位和低 64 位拆开看 I/Q。星座图如果呈现一个旋转的圆环说明载波频偏没有被 DVB-S2 IP 内部的载波恢复环压住如果星座点聚成四个团但边界模糊说明符号定时对齐有偏差优先查成型滤波的插值系数而不是先怀疑射频部分。6.2 用 Tcl 批量回放仿真与误码率统计技巧当硬件回环通路稳定后批量验证 MODCOD 表格就交给 Tcl。常见做法是循环修改 IP 参数、重新综合、运行行为仿真再把误码率结果写回日志文件。使用 Vivado 的 batch mode 时可用-tclargs传入 MODCOD 索引。测试台里留一个$display按帧打印 BER再用 Tcl 正则抓取。下面是在同一套工程里连续跑两个 MODCOD 的最小骨架# 批量仿真两个 MODCOD foreach mod {12 18} { set_property CONFIG.MODCOD $mod [get_ips dvbs2_mod] update_compile_order -fileset sources_1 launch_simulation -mode behavioral # 等待仿真结束并抓取 log 中的 BER 行 set logfile sim_mod$mod.log set fd [open $logfile r] while {[gets $fd line] 0} { if {[string match *BER* $line]} { puts MODCOD $mod : $line } } close $fd }注意每次修改 IP 参数后要执行update_compile_order否则综合和仿真用的还是旧参数仿真的$display输出要以文件形式落盘Tcl 拿不足一行文本就无法做统计。这一步比硬件排错快得多适合在集成后期每天跑一遍回归。本文还有配套的精品资源点击获取