ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

FPGA平台下Gardner环多径信道定时同步测试与抗多径优化

FPGA平台下Gardner环多径信道定时同步测试与抗多径优化

连续做Gardner环性能测试,第二轮我直接把信号扔进带多径的信道里。上篇内容是不同信噪比下定时收敛的表现,测完之后有两个疑问没有解决:高斯噪声是随机干扰,Gardner环可以通过环路滤波平均掉一部分;但多径是确定性干扰,它把符号波形直接“扯歪”了,定时误差检测器看到的过零点不再干净。我在FPGA平台上跑完这轮测试后,最大的感想是——多径对Gardner环的影响和噪声完全不同,它动的不是误差方差,而是误差检测的“基准”。这篇文章把多径拆成两个维度,一个是多径时延(以符号周期T的倍数衡量),另一个是多径幅度(相对主信号的衰减分贝数),逐组合测了一遍,并且把结果量化下来。

我采用的平台和上篇保持同一条流水线:Vivado里搭System Generator做信道激励和采集,核心Gardner环用可综合RTL重写,最后用ModelSim和Vivado Simulator交替做回归仿真。信号制式是QPSK,符号速率定在1 Msps,过采样率4倍,符号定时的捕获由环内的NCO和Farrow插值器完成。写完这个平台之后,我对着手里的旧代码发现一个问题:多数FPGA工程示例里把Gardner环放在理想信道下验证,一旦引入多径,环路参数是否还合适、插值器的精度是否够,根本没人给现成答案。所以这篇更准确地说不是“又做了个波形仿真”,而是把工程里最容易忽略的信道敏感性拿到台面上量化。无论你是刚开始搭定时同步链路,还是已经在FPGA项目里跑过Gardner环,下面的实现细节和故障排查都值得对照一遍。

1. 为什么第二轮测试要拿多径开刀

1.1 多径的延迟和幅度如何扭曲Gardner环的S曲线

Gardner定时误差检测器的本质是利用相邻符号的中间点与两端符号值之间的相关关系估计定时偏移。无多径时,匹配滤波后的眼图过零点对称,误差检测输出和定时偏差之间呈一条平滑的S形曲线,环路沿着S曲线把采样点拉回眼图中心。多径信道不一样,它相当于在原信号上叠加一个经过衰减和延迟的副本。副本与主路径叠加后,符号脉冲的上升沿和下降沿不再对称,眼图的过零点位置发生平移。我在测试里用两径模型控制时延τ和幅度α:时延从0.1T逐步加到0.8T,幅度从-20dB加到-3dB。当τ等于0.5T附近时,过零点平移最明显,定时误差检测器的S曲线零点整体偏移了接近0.13个符号周期。这个偏移不是噪声抖动,它是固定偏置,环路滤波器压不掉,看起来像是把采样点锁在一个偏移的位置上,实际就是在多径环境下“锁错了地方”。

这里还得强调一个机理:Gardner环本身不感知绝对时钟相位,它只能跟随S曲线的零点。多径引入零点偏移后,环路认为的“正确采样点”已经偏离真实最佳均衡点,最终剩余误差不再是零,而是这个偏置。工程上最容易踩的坑是,把这种固定偏置误判成环路没收敛,去调大环路带宽;实际上增大带宽只会增加稳态抖动,并不会把偏置消掉。这个机理理解透,后面看测试数据就顺了。

1.2 测试想回答的三个问题和信号参数快照

这次测试我给自己的目标非常具体,不指望把所有多径场景全测全。第一个问题是多径时延大小会如何影响收敛速度——Gardner环从上电到锁定需要多少个符号周期;第二个问题是多径幅度如何影响稳态定时抖动以及最终误码率;第三个问题是多径强到什么程度会直接导致环失锁。围绕这三个问题,我固定了一组基线参数:QPSK、符号速率1 Msps、4倍过采样、成形滤波采用滚降系数0.25的根升余弦滤波器,定时环的归一化环路带宽BL·T设为0.02。所有测试都在相同信噪比20dB下进行,隔离其他因素,单独观察多径维度。这么做的好处是结果之间可以直接横向对比,上一轮测不同SNR的数据也还能复用。

参数上还有一个细节需要交代:多径时延的分档。我选了0.1T、0.25T、0.5T、0.8T四档,0.5T是最恶劣的挡位,因为正交信号在符号中点的相干叠加最容易造成符号间干扰。幅度分档是-20dB、-10dB、-6dB、-3dB,-3dB基本对应接收端副径与主径幅度相当的极限场景。在这个参数快照下,每一组都跑满2^16个符号,重复30次,统计锁定时间和失锁比例。整轮测试大约四十多组仿真,跑起来并不慢,但能把问题的边界画清楚。

2. 先把手头的Gardner环拆开看

为了让多径测试结论可靠,我不可能拿黑盒去做分析,必须把FPGA里跑的定时环每一个模块都过一遍。Gardner环在FPGA中可以拆成四个部分:定时误差检测器(TED)、环路滤波器、NCO、插值器。很多工程问题不是算法不对,而是定点实现和模块间的延迟把环路带宽或误差增益悄悄改变了。尤其是在多径存在的场景,TED输出幅度随信道变化很大,如果不做归一化,环路实际带宽会随信道状态漂移,后面看数据就会“找不到原因”。

2.1 TED、Farrow插值器与定点的三层坑

TED实现上需要当前符号采样值y(k)、前一符号采样值y(k-1)以及两者中间的半符号采样值y(k-1/2)。QPSK的I/Q两路都要参与,实际误差值取复平面组合要按接收机结构决定。我这边采用复数形式:e(k) = Re{y(k-1/2)·(y*(k) - y*(k-1))}。中间点采样并不是ADC直接给出的,是靠插值器在过采样序列里计算出来的小数延迟点。FPGA里我用了四阶Farrow结构,用当前点前后四个采样值做三次多项式插值。定点位宽上,输入样值用了16bit,Farrow系数用16bit有符号数,插值结果保留到20bit。这个结构在无多径场景表现很好,误差精度能到0.001符号周期以内;但在多径测试中我发现,如果插值器系数位宽不足,多径造成的高频分量会直接变成插值噪声,结果比信道本身的损伤还明显。这个教训后面专门说。

误差算法本身不复杂,我贴一段Verilog摘要展示实现思路:

// Gardner TED核心,QPSK I/Q两路 wire signed [19:0] mI = interp_I; // 半符号点I wire signed [19:0] s0I = cur_I; // 当前符号I wire signed [19:0] s1I = prev_I; // 前一个符号I wire signed [19:0] errI = mI * (s0I - s1I); // I路误差 wire signed [19:0] mQ = interp_Q; wire signed [19:0] s0Q = cur_Q; wire signed [19:0] s1Q = prev_Q; wire signed [19:0] errQ = mQ * (s0Q - s1Q); // Q路误差 reg signed [19:0] e_ted; always @(posedge clk) begin e_ted <= (errI + errQ) >>> TED_SHIFT; // 归一化右移 end

真正定点实现时乘法器要配DSP48,并且根据仿真结果确定TED_SHIFT的值。我在无多径信道下先做一遍浮点模型与定点模型的对比,把量化误差控制在2%以内,才放心进入多径测试。

2.2 环路滤波器、NCO与带宽选择的折中

环路滤波器和NCO决定了环的动态特性。我用的是二阶环路,比例支路Kp负责直接对当前误差做出响应,积分支路Ki负责消除静态误差。由于Gardner环工作在符号率上,NCO实际上是一个相位累加器,每次迭代输出的小数相位控制Farrow插值器;累加器位宽我用了24bit,这决定了可调频率分辨率。归一化带宽BL·T是设计时输入量,我给出常用对应关系:

BL·TKpKi特点
0.010.0280.0004捕获慢,抗噪声强,适合高SNR但需稳定
0.020.0560.0015折中,本文测试默认
0.050.1410.01捕获快,稳态抖动大

这张表是PI参数换算后的经验值,实际还需要根据环路延迟微调。多径场景下我认为最关键的取舍在“带宽能不能跟着多径强度变”:多径产生的定时自噪声主要落在低频区,把BL·T收窄能压住自噪声,但会使环对时变信道失去跟踪能力。没有自适应环路的前提下,我把默认带宽定在0.02,是在上一轮SNR测试基础上找的平衡点。后面跑多径用例时,凡是抖动异常增大的用例,我都额外补跑BL·T等于0.01和0.05的对照,用来判断是信道损伤还是环路带宽不匹配。

3. 多径注入与性能测试工程实现

测试工程搭建时最重要的决定是“多径信道在哪里注入”。我之前见过有人直接用MATLAB把多径信号算好写成文件,再在Testbench里读文件灌给RTL;也有人用System Generator的FIR抽头模型在线生成。两种都可以,但我为了保证后续板级验证能直接复用,选择了在RTL侧用抽头延迟线加乘法器做成一个参数可配的信道模型。

3.1 两径信道模型:从解耦参数到FPGA建模

两径模型就一句话:输出 = 当前样值 + 副径系数 × 延迟后的样值。困难在延迟不一定是整数个采样点。比如符号周期T对应4个采样点,时延0.25T对应的就是1个采样周期,可以用寄存器链直接取;而0.1T对应0.4个采样点,寄存器链没法直接给分数延迟,必须再做一次插值。我的做法是先用一个独立Farrow插值器把当前序列做分数延迟,再把输出乘以幅度系数后叠加到主路径上。这里有个容易被忽略的问题:多径叠加后信号总功率会上升,如果不做归一化,进入TED的信号幅度变化会被误读成定时误差变化。我按主径幅度1、副径幅度β归一化总能量,代码里乘上一个固定因子1/sqrt(1+β²),确保不同用例之间S曲线增益可比。

信道模型参数表如下,我用寄存器字控制:

用例组多径时延多径幅度系数β数字化(16bit)
T10.1T-10dB0.316
T20.25T-10dB0.316
T30.5T-10dB0.316
T40.8T-10dB0.316
A10.25T-20dB0.100
A20.25T-6dB0.501
A30.25T-3dB0.708

T1-T4观察时延维度的变化,A1-A3观察幅度维度的变化;中间用0.25T、-10dB这组交叉用例保证两组可以直接对比。这组参数听起来很直观,但第一次跑的时候我踩了坑:副径时延在Tx信号发生端和信道模型是两套时钟域,如果省掉异步处理,在仿真里会出现随机毛刺。后来统一把整个信道模型放在ADC采样时钟域,激励从ROM里按同一时钟读,问题才消失。

3.2 Testbench与统计模块:用寄存器输出性能指标

性能测试不能靠眼睛盯着ModelSim波形数刻度,那不叫测试。我往RTL里嵌了一个统计模块,用AXI-Lite寄存器把实时指标读出来。每个符号周期,统计模块做四件事:记录TED输出的瞬时值、累计定时误差平方和、统计锁定标志的跳变次数、记录从启动到锁定的符号计数。为了把锁定定义具体化,我在统计模块里设置“误差滑动平均值小于0.05符号周期并连续保持2^10个符号周期”作为锁定条件。同时为了测试公平,每次仿真开始时NCO初始相位不是一个固定值,而是用线性反馈移位寄存器产生随机符号内偏移,避免初始相位恰好落在S曲线零点附近而“假锁定”。

激励侧的安排也值得提一下:QPSK基带信号用MATLAB生成,经过根升余弦成形、量化成16bit样值后写到COE文件,Testbench用$readmemh读入ROM。每个用例更换信道参数,实际上只需要重新生成信道仿真文件,或者通过寄存器实时配置抽头系数和延迟。跑完所有用例,再用MATLAB脚本解析仿真导出的寄存器数据,画收敛曲线和抖动分布。这套流程并不复杂,但统计口径统一,横向对比才有意义。

3.3 数据采集与指标定义

最终我采了六个指标:平均收敛符号数、失锁概率、稳态定时抖动σ_e、眼图张开度、误码率、TED输出均值。其中σ_e的定义是锁定后定时误差序列的标准差,单位是符号周期;眼图张开度我用过零点附近采样点的同相幅度比值来近似,反映可解码裕量。误码率在仿真里直接做符号级硬判,每用例统计2^16符号。这里有一个细节,单独仿真定时环时看不出误码,需要把定时环输出的插值样值送到后续匹配滤波和判决器里,才能反映出定时质量对链路最终性能的影响。我这轮把判决器一起跑通了,因此后面的误码数据是端到端结果,不是孤立的定时误差换算值。

4. 不同多径大小下的实测结果

数据就跑完了,开始看结论。整体来说,多径对Gardner环的影响是“温和时延先拖慢收敛,幅度再决定抖动上限”。我先把两个维度的数据分开讲,再合起来解释S曲线变化的机理。

4.1 时延维度:收敛速度先降、锁定点再偏移

固定多径幅度-10dB、SNR 20dB,改变时延,收敛时间和锁定点偏移的数据统计如下:

多径时延平均收敛符号数锁定点偏移(符号)失锁概率
无多径4520.002<1%
0.1T473-0.008<1%
0.25T7120.0522%
0.5T13310.1178%
0.8T18020.12425%

可以看到:0.1T时几乎没影响;从0.25T开始,收敛时间和锁定点偏移明显上升;到0.5T时最典型的问题已经不只是慢,而是锁定点被拉到约0.117个符号周期——这个偏移换算成采样相位就是约42度,对QPSK解调器来说已经非常可观。0.8T那组失锁概率上升到25%,说明环路在不同初始相位下经常找不到正确的S曲线零点,偶尔会锁定到相邻的伪零点上去。还有一个细节值得注意,0.5T和0.8T的锁定点偏移都在0.12符号附近,与单符号信道记忆理论的预期基本一致:过零点偏移在半个符号时延附近趋于饱和。

时延变化改变的是符号间干扰的“作用位置”。小于0.1T的时延等效为信道群延迟,Gardner环完全可以吸收掉,看起来只是把采样点整体移动了一下;当延迟接近并超过半个符号,副径会直接落在相邻符号的判决点附近,码间干扰的能量进入TED计算窗口,S曲线的过零点不再单调,锁相过程开始出现多个准平衡点。这就是为什么收敛符号数从400多跳到1800,不是单纯变慢,而是环路搜索机制在多准平衡点环境里总在反复试探。

4.2 幅度维度:抖动与误码呈非线性增长

固定多径时延0.25T、SNR 20dB,改变多径幅度,结果如下:

多径幅度稳态σ_e(符号)眼图张开度误码率BER
无多径0.01699%<1e-5
-20dB0.02295%<1e-5
-10dB0.03586%4e-4
-6dB0.05873%6e-3
-3dB0.12742%1.4e-2

第一眼看,σ_e从0.035跳到0.127,增幅明显大于线性,这说明多径造成的定时自噪声与副径幅度不是简单的比例关系。原因在于多径不仅增加了误差检测的自噪声,还改变了误差检测增益:副径幅度越大,TED输出中的确定性偏置越强,环路试图把偏置积分掉的同时,又把大量ISI相关的波动放大成抖动。眼图张开度在-3dB时掉到42%,这已经是基带解调基本不可用的水平。另一个值得一提的现象是:多径幅度相同但时延不同时,抖动差异非常大;在-6dB、时延0.25T的条件下,σ_e约0.058,而同样的幅度在时延0.5T时,σ_e会上升到接近0.09。所以多径的影响应该看“时延+幅度”的组合,单独给一个“有多少dB多径”并不能说明问题。

误码与抖动的折算也值得深入看:0.127个符号的定时抖动,对QPSK在20dB信噪比下造成的误码率下降远超预期。因为定时偏移直接造成采样点偏离符号中心,等价于降低了有效信噪比。估算下来,-3dB多径带来的等效SNR损失大约在5到6dB。这个数字并不新奇,但FPGA实测能稳定复现,就有参考价值了。

4.3 用S曲线解释为什么多径这么难缠

为了把数据背后的东西讲清楚,我把TED的输出在每个固定的定时偏移下扫一遍,得到S曲线。无多径情况下,S曲线是一条过零点附近基本线性的平滑曲线。加入0.5T时延、-10dB幅度后,曲线形态发生两个变化:过零点向右平移约0.12符号;过零点附近的斜率从约0.5下降到约0.34。斜率下降意味着环路增益变小,同样的误差电压对NCO的拉动力下降,所以收敛变慢;零点平移意味着即使在稳态,误差均值也不为零,固定偏置始终存在。

这两个变化放在一起就解释了前面所有数据:收敛慢是斜率下降的结果,锁定点偏移是零点平移的结果,失锁概率上升则是S曲线在远离零点区域出现非单调甚至局部极小值的直接后果。对FPGA开发人员来说,S曲线不是算法课上的抽象概念,它是可以用硬件扫描出来的关键曲线。我在工程里用寄存器把TED输出按偏移量分桶统计,300毫秒左右就能把S曲线扫出来,调试多径问题比看一堆抖动波形直观得多。如果你也在处理类似问题,强烈建议在测试模块里加一个“S曲线扫描”模式,短时间内能省下大量排查时间。

5. 踩坑清单、抗多径思路与后续方向

把最值钱的故障排除经验放在最后。多径测试不是灌一个信号看波形就行,这轮跑下来我在工程细节上抓出几个典型问题,都值得记录。

5.1 踩过的三个坑:分数延迟、归一化与带宽误判

第一个坑就是多径分数延迟。最初图省事,时延直接从采样点抽整数拍,0.25T、0.5T能整数对应没关系,但0.1T和0.8T两档就出问题了——用整数延迟替代分数延迟后,0.1T的测试结果与理论完全不匹配,S曲线零点偏移几乎为零,但抖动异常增大。后来查清是整数延迟在相邻采样点之间“跳变”,产生了额外的相位噪声。解决方法是把分数延迟统一用独立Farrow插值器生成,确保任意时延都能连续变化。

第二个坑是信道增益没有归一化。多径叠加让信号平均功率变大,TED输出的幅度整体上抬,统计模块算出来的“均值”不再能反映真实定时偏移。我在信道模型里加了固定能量归一化系数1/sqrt(1+β²),把主径加副径的总功率归一化回单位功率,所有用例的TED均值才具有可比性。

第三个坑最隐蔽:把环路带宽太宽导致的自噪声误判为多径失锁。刚开始用BL·T=0.05跑-3dB用例,看到σ_e冲到0.17以上,差点结论写成“系统失锁”;后来补跑BL·T=0.01的对照,σ_e立刻降到0.11,发现10dB多径并没有让环完全失锁,只是宽带宽放大了多径自噪声。这个错误在无多径测试中发现不了,因为高斯噪声被环路滤掉后,自噪声的贡献很小;多径的时序相关噪声会让宽带宽付出明显代价。

5.2 工程上实用的抗多径优化措施

从这轮测试看,多径环境下的Gardner环设计不能指望换算法一劳永逸,但有几个工程手段能把环境影响压下来。第一是环路带宽自适应:用状态机简单检测TED输出的滑动方差,方差小于阈值时把BL·T从0.05降到0.01,可以同时兼顾捕获速度和稳态抖动;FPGA实现时就是多组Kp/Ki系数表,切换时对NCO相位做连续性处理,防止跳变。第二是滚降系数的选择:根升余弦的滚降系数从0.25提高到0.5后,多径引起的过零点偏移会减小,因为频谱滚降区域占更大比例,信号对抗ISI的余量更足;代价是占用带宽变大,适合带宽充裕的场合。第三是级联均衡:在Gardner环后面挂一个自适应均衡器,多径的固定ISI由均衡器消掉,让定时环只负责相位对齐;这种“先定时后均衡”的结构在实测中能比单环方案提高3dB以上的等效SNR。最后还有一个细节,所有抗多径手段的验证都要跑完整链路,不能只看定时抖动一项指标;我这轮把误码率放进来后,发现有些“抖动改善了”的配置,误码率反而没变化,因为真正限制性能的已经变成固定ISI了。

以上措施是在我的两径模型下验证的,真实信道多径条数更多、衰落随时间变化,结论会有偏差,但工程手段的方向一致。

5.3 后续计划与个人验证心得

下一轮测试我已经排上日程了:一是把滚降系数从0.25换到0.5,看定时环的耐受度能提高多少;二是把两径扩张到三径、四径,模拟更接近实际场景的频率选择性衰落;三是考虑在多径模型基础上同时叠加残余载波频偏,看看Gardner环在载波恢复之前的性能边界。每次测试我都会先把浮点模型跑一遍,确定理论参考曲线,再上FPGA定点,否则很难判断结果是算法问题还是定点量化问题。

个人体会很深的一点是,FPGA里的时序同步模块,最怕的不是算法复杂,而是定点和环路参数没有量化的边界概念。多径测试能逼着人把所有边界都暴露出来,这比单纯调好一个无多径场景的环路参数有价值得多。如果你也准备做类似测试,我建议一开始就把多径时延、幅度、环路带宽、滚降系数四个参数做成交叉矩阵,全部跑完再下结论;单独一两个用例的波形说明不了任何设计优劣。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进