资讯动态

LMS自适应算法驱动DFE判决反馈均衡器:从原理推导到Python仿真与工程调试实战

发布时间:2026/9/21 16:18:52 来源:尧图企业网站定制
1. 从一条被噪声淹没的链路说起DFE到底在解决什么问题做数字通信或者信号处理的人迟早会撞上同一个场景信号在信道里跑了一趟回来眼图已经闭合得差不多了。尤其在有线传输场景里比如千兆以太网、背板互连、长距离同轴电缆信道的带宽限制和阻抗不匹配会带来严重的码间干扰ISI。你发一个理想的脉冲出去收到的却是一个拖尾很长的波形前一个符号的能量拖到了当前符号的判决时刻上当前符号又拖到了下一个符号上。速率越高这个问题越致命。传统的线性均衡器比如FIR结构的迫零均衡或者MMSE均衡能解决一部分ISI。但线性均衡有个硬伤它在补偿信道高频衰减的同时会把高频段的噪声也一并放大。当信道衰减很严重的时候线性均衡器为了把高频抬起来付出的代价是噪声被放大到无法忍受的程度。这时候就需要换一个思路——判决反馈均衡器也就是DFEDecision Feedback Equalizer。DFE的核心思想其实很朴素既然ISI主要来自已经判决过的历史符号那我把这些历史符号重新通过一个滤波器模拟出它们对当前符号造成的干扰然后从接收信号里减掉不就行了这个“重新通过滤波器”的结构叫反馈滤波器它的输入不是接收信号而是已经判决输出的符号。因为判决输出是“干净”的数字值不携带噪声所以反馈路径不会像前馈路径那样引入噪声放大。这就是DFE相对于线性均衡器的根本优势。而LMS算法全称Least Mean Squares最小均方算法是自适应滤波里最经典、最实用的一种系数更新方法。它的计算量小、实现简单、数值稳定性好非常适合用在DFE这种需要实时更新系数的场景里。用LMS来驱动DFE的前馈和反馈滤波器系数更新就是这套方案的核心。这篇文章面向的是有一定信号处理基础、想动手实现一个完整DFE系统的读者。不管你是通信工程的学生要做课程设计还是嵌入式工程师要在FPGA或DSP上落地均衡器或者只是对自适应滤波感兴趣想跑通一个仿真下面的内容都会覆盖到。我会从DFE的结构拆解讲起把LMS的更新公式推导清楚然后给出完整的Python仿真代码最后重点讲我在实际调试中踩过的坑和总结出来的参数调节经验。这些东西在教科书里往往一笔带过但真正动手的时候它们才是决定你能不能跑通的关键。2. DFE的结构拆解前馈、反馈与判决器如何协同工作2.1 前馈滤波器处理当前符号受到的“前瞻性”干扰DFE的前馈部分本质上就是一个线性均衡器通常用FIR滤波器实现。它的输入是接收到的采样序列输出经过加权求和后送给判决器。前馈滤波器主要处理的是当前符号受到的来自“未来”符号的干扰也就是那些在时间上还没被判决的符号造成的ISI。听起来有点绕但你可以这样理解在判决当前符号的时刻未来符号的干扰已经体现在接收波形里了前馈滤波器通过它的抽头系数去补偿这部分影响。前馈滤波器的抽头数通常用Nf表示抽头间隔可以是符号周期T也可以是T/2分数间隔。分数间隔的前馈滤波器有个好处它能同时处理采样相位偏差和ISI对定时误差不那么敏感。我在实际项目中一般优先考虑T/2间隔虽然计算量翻倍但鲁棒性提升很明显。前馈滤波器的输出可以写成y_ff(n) Σ w_f(i) * r(n-i)i从0到Nf-1其中r(n)是接收采样序列w_f(i)是前馈抽头系数。这个输出y_ff(n)还不是最终的判决输入它还要减去反馈滤波器的输出。2.2 反馈滤波器用已判决符号重建干扰并抵消反馈滤波器是DFE区别于线性均衡器的关键。它的输入是判决器输出的历史符号序列记作d(n-1), d(n-2), ..., d(n-Nb)其中Nb是反馈滤波器的抽头数。反馈滤波器的输出是y_fb(n) Σ w_b(j) * d(n-j)j从1到Nb注意这里的求和从j1开始因为当前符号d(n)还没判决出来不能用。反馈滤波器的输出代表了已判决符号对当前符号造成的ISI估计值。把这个估计值从前馈输出里减掉就得到了判决器的输入z(n) y_ff(n) - y_fb(n)然后判决器对z(n)进行判决得到d(n)。判决规则取决于调制方式比如BPSK就是取符号QPSK就是找最近的星座点。这里有一个非常重要的前提假设历史判决必须是正确的。如果某个历史符号判错了这个错误会通过反馈滤波器传播下去导致后续一连串的判决都出错。这就是DFE的“误差传播”问题也是它最大的弱点。在实际系统里通常会配合信道编码和交织来缓解误差传播的影响但在均衡器层面我们能做的就是尽量降低单次判决的错误概率。2.3 判决器DFE里最容易被低估的环节很多人把注意力都放在滤波器的系数更新上觉得判决器就是一个简单的取符号操作没什么好讲的。但实际上判决器的设计直接影响DFE的性能上限。判决器的输入z(n)是一个带噪声和残余ISI的模拟量判决门限的设置、星座点的映射方式、甚至判决的时序都会影响误码率。以BPSK为例判决规则是如果z(n) 0则d(n) 1否则d(n) -1。看起来很简单但如果z(n)的分布不是以0为中心对称的比如存在直流偏置那判决门限就需要调整。我在一次实际调试中就遇到过这个问题接收链路里有一个微小的直流偏置导致判决门限偏移误码率一直降不下来。后来在判决前加了一个直流消除模块问题才解决。另外判决器的输出不仅要送给反馈滤波器还要作为LMS算法的参考信号来计算误差。所以判决器的延迟必须严格控制否则误差计算的时间对齐就会出问题。2.4 三个模块的协同一个完整的符号周期内发生了什么把前馈、反馈、判决器串起来在一个符号周期内DFE的工作流程是这样的接收采样r(n)进入前馈滤波器计算y_ff(n)反馈滤波器根据历史判决d(n-1)...d(n-Nb)计算y_fb(n)判决器输入z(n) y_ff(n) - y_fb(n)判决器输出d(n)计算误差e(n) d(n) - z(n)用LMS算法更新前馈和反馈滤波器的系数将d(n)移入历史判决缓冲区准备下一个符号周期这个流程看起来清晰但实际实现的时候步骤5到步骤7的顺序、缓冲区的大小、系数的初始化方式都会影响收敛速度和稳态性能。后面讲实现的时候我会详细展开。3. LMS算法的更新逻辑为什么它适合驱动DFE3.1 从最陡下降到LMS一次近似带来的巨大简化LMS算法的根源是最陡下降法。最陡下降法的思路是沿着均方误差MSE性能曲面的负梯度方向一步步调整滤波器系数最终到达MSE最小的那个点。理想情况下每次迭代需要知道真实的梯度而真实梯度需要用到输入信号的自相关矩阵和互相关向量计算量很大。LMS算法做了一个大胆的近似用瞬时误差的平方来代替均方误差用瞬时梯度来代替真实梯度。这个近似带来的结果是系数更新公式变得极其简单w(n1) w(n) μ * e(n) * x(n)其中w(n)是滤波器系数向量x(n)是输入信号向量e(n)是误差信号μ是步长因子。就这一个公式没有矩阵求逆没有自相关估计每次迭代只需要几次乘加运算。这就是LMS算法在工程上如此流行的原因。对于DFE来说前馈滤波器和反馈滤波器的系数更新都遵循这个公式只是输入向量不同。前馈滤波器的输入是接收采样序列反馈滤波器的输入是历史判决序列。误差信号是同一个e(n) d(n) - z(n)其中d(n)是判决输出z(n)是判决器输入。3.2 步长μ的选择收敛速度与稳态误差的博弈步长μ是LMS算法里最重要的参数没有之一。它直接决定了两个关键指标收敛速度和稳态误差。μ越大收敛越快但稳态误差也越大因为系数在最优值附近来回抖动的幅度更大。μ越小稳态误差越小但收敛速度慢可能需要几千甚至几万个符号才能收敛到可接受的水平。极端情况下μ超过某个上限算法直接发散系数飞到无穷大。这个上限和输入信号的自相关矩阵的最大特征值有关。理论上μ必须满足0 μ 2 / λ_max其中λ_max是输入自相关矩阵的最大特征值。在实际工程中我们通常不知道λ_max的精确值所以会用输入信号的功率来近似。一个常用的经验法则是μ α / (N * P)其中N是滤波器抽头数P是输入信号的平均功率α是一个小于1的常数通常取0.01到0.1之间。这个公式的直觉是抽头越多输入功率越大步长就应该越小否则更新量会过大导致不稳定。我在实际项目中一般会先按这个公式算一个初始值然后在仿真里扫描不同的α观察收敛曲线和稳态MSE选一个折中。对于DFE这种有反馈路径的结构步长还要更保守一些因为反馈路径的误差传播会放大不稳定性。3.3 归一化LMS让步长对输入功率变化免疫基本LMS算法有一个问题如果输入信号的功率随时间变化固定的步长就不合适了。功率大的时候等效步长变大可能不稳定功率小的时候等效步长变小收敛变慢。解决方法是使用归一化LMSNLMS更新公式变成w(n1) w(n) (μ / (ε ||x(n)||^2)) * e(n) * x(n)其中||x(n)||^2是输入向量的能量ε是一个很小的正数防止分母为零。NLMS的等效步长会根据输入能量自动调整对输入功率变化更鲁棒。在DFE里前馈滤波器的输入功率可能因为信道衰减而变化用NLMS会更稳。不过NLMS的计算量比基本LMS大一些因为每次迭代都要算输入向量的能量。在FPGA上实现的时候这个除法操作也比较费资源。所以到底用LMS还是NLMS要看具体的资源预算和性能要求。我在DSP上实现的时候一般用NLMS因为DSP有硬件除法器开销可以接受在FPGA上如果资源紧张就用基本LMS配合自动增益控制AGC来稳定输入功率。3.4 误差信号的来源判决输出还是训练序列LMS算法需要误差信号e(n)来更新系数。误差信号怎么来有两种模式第一种是训练模式。在通信开始时发送端发送一段已知的训练序列接收端用这个已知序列作为参考计算误差e(n) d_ref(n) - z(n)。训练序列的长度通常几百到几千个符号足够让系数收敛到接近最优值。第二种是判决引导模式。训练结束后接收端切换到用判决输出作为参考误差e(n) d_hat(n) - z(n)。这时候如果判决正确误差信号就是准确的如果判决错误误差信号就被污染了可能导致系数往错误的方向调整。实际系统里通常是先训练后判决引导。训练序列的设计也有讲究要保证它的自相关特性好频谱足够丰富能激励信道的所有模式。常用的训练序列有PN序列、Zadoff-Chu序列等。我在项目里用过的最简单的训练序列就是交替的1/-1对于大多数信道来说已经够用了。4. 用Python从零搭建一个完整的DFE仿真链路4.1 仿真框架设计先想清楚要验证什么动手写代码之前先想清楚这个仿真要验证什么。我的目标有三个第一验证DFE能有效消除ISI误码率明显低于无均衡的情况第二观察LMS算法的收敛过程看系数是否收敛到合理值第三对比不同步长和抽头数对性能的影响。基于这三个目标仿真框架需要包含以下模块信道模型产生ISI我选一个典型的频率选择性信道比如三径信道主径加两个延迟径调制解调用BPSK简单直观判决规则清晰DFE主体前馈滤波器、反馈滤波器、判决器LMS更新系数自适应更新性能评估误码率统计、MSE收敛曲线、星座图代码用Python写依赖numpy和matplotlib。numpy负责矩阵运算matplotlib负责画图。整个仿真大概两百行左右不算长但每个模块都要写清楚。4.2 信道与信号生成构造一个能体现DFE价值的场景先定义信道。我选一个三径信道冲激响应为h [0.8, 0.5, 0.3]延迟分别为0、1、2个符号周期。这个信道的主径能量占比不算特别高ISI比较明显正好能体现DFE的作用。import numpy as np import matplotlib.pyplot as plt # 信道参数 h np.array([0.8, 0.5, 0.3]) channel_delay len(h) - 1 # 仿真参数 N_symbols 5000 SNR_dB 20 Nf 7 # 前馈抽头数 Nb 3 # 反馈抽头数 mu_ff 0.01 mu_fb 0.005 train_len 500 # 生成BPSK符号 np.random.seed(42) tx_symbols np.random.choice([-1, 1], sizeN_symbols) # 通过信道 rx_signal np.convolve(tx_symbols, h, modefull) rx_signal rx_signal[:N_symbols channel_delay] # 加高斯白噪声 signal_power np.mean(rx_signal**2) noise_power signal_power / (10**(SNR_dB/10)) noise np.sqrt(noise_power) * np.random.randn(len(rx_signal)) rx_noisy rx_signal noise这里有一个细节卷积之后信号长度变成了N_symbols channel_delay我截断到N_symbols channel_delay保证每个符号周期都有对应的采样。实际系统里还要考虑定时同步但仿真里我假设定时是理想的直接按符号周期采样。4.3 DFE核心循环逐符号处理与系数更新接下来是DFE的主循环。每个符号周期前馈滤波器处理接收采样反馈滤波器处理历史判决判决器输出当前符号然后LMS更新系数。# 初始化 w_ff np.zeros(Nf) w_fb np.zeros(Nb) d_hist np.zeros(Nb) # 历史判决缓冲区 mse_history [] ber_errors 0 # 训练序列前train_len个符号用已知序列 train_seq tx_symbols[:train_len] for n in range(Nf - 1, N_symbols): # 前馈滤波 r_vec rx_noisy[n - Nf 1 : n 1][::-1] y_ff np.dot(w_ff, r_vec) # 反馈滤波 y_fb np.dot(w_fb, d_hist) # 判决器输入 z y_ff - y_fb # 判决 d_hat 1.0 if z 0 else -1.0 # 选择参考信号 if n train_len: d_ref train_seq[n] else: d_ref d_hat # 计算误差 e d_ref - z # LMS更新 w_ff w_ff mu_ff * e * r_vec w_fb w_fb mu_fb * e * d_hist # 更新历史判决缓冲区 d_hist np.roll(d_hist, 1) d_hist[0] d_hat # 记录MSE mse_history.append(e**2) # 统计误码只统计训练后的 if n train_len: if d_hat ! tx_symbols[n]: ber_errors 1 # 计算误码率 ber ber_errors / (N_symbols - train_len) print(f误码率: {ber:.6f})这段代码是整个仿真的核心。有几个地方需要特别注意第一r_vec的构造。我用rx_noisy[n - Nf 1 : n 1][::-1]来获取当前时刻往前Nf个采样然后反转顺序使得r_vec[0]对应最新采样r_vec[Nf-1]对应最旧采样。这个顺序要和w_ff的系数顺序一致否则滤波器的时延关系就乱了。第二d_hist的更新。我用np.roll把缓冲区右移一位然后把最新判决放在d_hist[0]。这样d_hist[0]对应d(n-1)d_hist[1]对应d(n-2)以此类推。反馈滤波器的系数w_fb也是按这个顺序排列的。第三训练模式和判决引导模式的切换。前train_len个符号用已知的训练序列作为参考之后切换到判决输出。这个切换点很关键如果训练不够充分就切换系数还没收敛判决错误率高误差传播会导致系统崩溃。4.4 收敛曲线与误码率怎么判断系统跑对了跑完仿真第一件事是看MSE收敛曲线。如果曲线从大逐渐减小最后稳定在一个较小的值附近说明LMS在收敛。如果曲线震荡剧烈或者发散说明步长太大或者有bug。# 平滑MSE曲线 window 50 mse_smooth np.convolve(mse_history, np.ones(window)/window, modevalid) plt.figure(figsize(10, 4)) plt.plot(mse_smooth) plt.xlabel(Symbol Index) plt.ylabel(MSE (smoothed)) plt.title(LMS Convergence Curve) plt.grid(True) plt.show()然后看误码率。在SNR20dB、信道ISI明显的情况下无均衡的误码率可能在10^-2量级DFE应该能把它降到10^-4以下。如果误码率没有明显改善就要检查系数是否收敛、判决门限是否正确、训练序列是否足够长。我还习惯画一下均衡后的星座图或者眼图直观感受残余ISI的大小。对于BPSK可以画z(n)的直方图看两个簇是否分得开。4.5 参数扫描抽头数和步长怎么选仿真跑通之后下一步是扫描参数找到最优配置。我一般会做两个扫描第一个是前馈抽头数Nf的扫描。Nf从3到15观察误码率的变化。通常Nf增加到一定程度后误码率改善就不明显了这时候再增加抽头只会增加计算量。第二个是步长μ的扫描。μ从0.001到0.05观察收敛速度和稳态MSE。太小的μ收敛太慢太大的μ稳态MSE高甚至发散。# 参数扫描示例 Nf_list [3, 5, 7, 9, 11, 15] ber_list [] for Nf in Nf_list: # 重新初始化并运行仿真 # ...省略重复代码 ber_list.append(ber) plt.figure(figsize(8, 4)) plt.plot(Nf_list, ber_list, o-) plt.xlabel(Number of Feedforward Taps) plt.ylabel(BER) plt.yscale(log) plt.grid(True) plt.show()这个扫描过程在仿真里很快但在实际硬件上可能要花不少时间。所以我的习惯是先在仿真里把参数范围缩小再到硬件上做精细调整。5. 实际调试中那些教科书不会告诉你的坑5.1 反馈滤波器的误差传播一次误判如何毁掉一整段数据误差传播是DFE的固有缺陷但它的严重程度和很多因素有关。我在一次调试中遇到的情况是信道在某个时间段出现了深度衰落导致连续几个符号判决错误。这几个错误符号进入反馈滤波器后产生的干扰估计完全错误导致后续符号的判决输入偏离又产生新的错误。这个连锁反应持续了十几个符号才恢复。缓解误差传播有几个实用手段。第一个是限制反馈滤波器的抽头数Nb不要太大。Nb越大单个错误符号影响的持续时间越长。对于大多数信道Nb取2到4就够了。第二个是在反馈路径上加一个非线性限幅把反馈滤波器的输出限制在一个合理范围内防止错误估计造成过大的干扰抵消量。第三个是配合信道编码用纠错码来纠正残余的错误。还有一个技巧是“部分反馈”就是反馈滤波器只使用置信度高的历史判决。如果某个符号的判决输入z(n)非常接近0说明判决置信度低可以把这个符号从反馈路径里排除或者给它一个较小的权重。这个做法在实现上稍微复杂一些但在误差传播严重的场景下效果不错。5.2 训练序列长度与切换时机太早切换等于白训练训练序列的长度直接决定了系数收敛的程度。训练太短系数还没收敛就切换到判决引导模式误码率高误差传播会让系统永远收敛不了。训练太长浪费带宽和时延。我的经验是训练序列的长度至少是前馈抽头数的10倍最好是20倍以上。比如Nf7训练序列至少70个符号最好150个以上。如果信道条件差还要更长。切换时机也有讲究。不要一到训练序列结束就立刻切换可以设置一个过渡期在过渡期里逐渐降低训练序列的权重增加判决输出的权重。或者监控MSE当MSE连续一段时间低于某个阈值时再切换。我在项目里用过的一个简单策略是训练序列结束后先保持系数不更新用判决引导模式跑100个符号统计误码率如果误码率低于阈值再开启系数更新否则继续训练。5.3 系数的初始化全零初始化不一定是最好的选择大多数教科书和代码示例都用全零初始化系数。这没问题LMS会从零开始慢慢收敛。但如果你对信道有先验知识可以用一个更好的初始值来加速收敛。比如如果你知道信道的主径增益和延迟可以把前馈滤波器的中心抽头初始化为主径增益的倒数其他抽头为零。这相当于给LMS一个接近最优的起点收敛时间可以缩短一半以上。反馈滤波器的系数初始化也有讲究。如果信道的主要ISI来自第一个延迟径可以把w_fb[0]初始化为该延迟径的增益除以主径增益。这个值就是最优反馈系数的近似值。当然如果你对信道一无所知全零初始化是最安全的。但如果你在做的是一个已知信道的固定场景花点时间算一个初始值收益很明显。5.4 定点化实现的精度陷阱仿真跑通不代表硬件能跑仿真里用的是浮点数精度足够。但到了FPGA或DSP上通常要用定点数实现这时候就会遇到精度问题。第一个问题是系数的位宽。前馈和反馈系数需要足够的位宽来表示小数部分否则系数的更新量会被量化误差淹没。我的经验是系数至少用16位其中小数部分至少10位。如果步长很小比如μ0.001更新量可能只有10^-4量级需要更多的小数位才能表示。第二个问题是累加器的位宽。前馈滤波器的输出是Nf个乘积的和每个乘积是系数和采样的乘积。如果系数和采样都是16位乘积是32位Nf个乘积相加需要额外的log2(Nf)位。所以累加器至少需要32log2(Nf)位比如Nf7累加器至少35位实际实现时取40位比较安全。第三个问题是误差信号的量化。误差e(n) d(n) - z(n)其中d(n)是±1z(n)是判决器输入。如果z(n)的定点表示精度不够误差信号就会有较大的量化噪声影响系数更新的准确性。我一般会给z(n)留至少12位小数。5.5 采样相位偏移分数间隔前馈滤波器的必要性如果前馈滤波器是符号间隔T间隔那么采样相位必须非常准确否则性能会严重下降。在实际系统里采样时钟不可能完全理想总会有相位偏移。这时候分数间隔的前馈滤波器比如T/2间隔就很有必要。T/2间隔的前馈滤波器每个符号周期有两个采样抽头数翻倍但好处是它对采样相位不敏感。即使采样相位偏移了半个符号周期性能下降也很有限。代价是计算量翻倍系数更新也需要调整。实现T/2间隔的时候输入向量的构造要改。每个符号周期取两个采样点组成一个长度为2Nf的向量。系数向量也是2Nf长。更新公式不变只是向量的维度变了。我在一个实际项目里对比过T间隔和T/2间隔的性能。在采样相位理想的情况下两者误码率差不多但当采样相位偏移0.3个符号周期时T间隔的误码率恶化了两个数量级T/2间隔只恶化了不到一个数量级。这个差距在工程上是决定性的。6. 从仿真到落地DFE在真实系统里的工程化考量6.1 资源与功耗的平衡抽头数不是越多越好在FPGA上实现DFE每个抽头需要一个乘法器、一个加法器和一个寄存器。前馈抽头Nf和反馈抽头Nb加起来就是乘法器的数量。对于高速应用比如10Gbps以上乘法器的数量和时钟频率直接决定了资源占用和功耗。我的经验是在满足误码率要求的前提下尽量少用抽头。前馈抽头Nf通常取5到9反馈抽头Nb取2到4。如果信道特别恶劣可以考虑用判决反馈加最大似然序列估计MLSE的混合结构但那是另一个话题了。另外LMS的系数更新不需要每个符号周期都做。可以每2个或4个符号更新一次这样系数更新模块的时钟频率可以降低功耗也降下来。代价是收敛速度慢一些但稳态性能几乎不受影响。6.2 流水线设计让DFE跑在更高的时钟频率上DFE的前馈滤波器和反馈滤波器都有反馈路径特别是反馈滤波器它的输出依赖上一个符号的判决这形成了一个闭环。这个闭环的延迟限制了最高时钟频率。解决方法是流水线化。把前馈滤波器的乘加运算拆成多级流水线每级之间加寄存器。反馈滤波器的闭环延迟也可以通过预测技术来缩短比如用 speculation 的方法提前计算两种可能的判决结果对应的反馈输出等判决出来后再选择。这个技术叫“预测DFE”或“ speculation DFE”在高速SerDes里很常用。不过流水线化会引入额外的延迟需要在系统层面做延迟补偿。而且 speculation 会成倍增加硬件资源因为要同时计算多个假设分支。所以到底用不用要看具体的速率要求和资源预算。6.3 与AGC和定时同步的配合DFE不是孤立的模块DFE在实际系统里不是孤立工作的它的前面通常有AGC和定时同步模块。AGC负责把接收信号的功率稳定在一个合适的范围内这样LMS的步长可以固定不用频繁调整。定时同步负责找到最佳的采样时刻如果定时不准DFE的性能会大打折扣。我在调试的时候通常会先调好AGC和定时同步确保进入DFE的信号功率稳定、采样相位准确然后再调DFE的参数。如果DFE的性能不理想我会先检查AGC和定时同步是否工作正常而不是一味地调DFE的步长和抽头数。还有一个细节AGC的增益变化会影响LMS的等效步长。如果AGC的调整速度比较快LMS的步长就要设得保守一些否则AGC和LMS会互相干扰导致系统不稳定。我的做法是让AGC的环路带宽远低于LMS的收敛速度这样两者可以解耦。6.4 测试与验证怎么确认DFE真的在工作在硬件上验证DFE是否工作最直接的方法是看误码率。但误码率测试需要很长时间特别是误码率很低的时候。所以我会用一些辅助手段来快速判断。第一个是看系数是否收敛。在FPGA里加一个调试接口把前馈和反馈系数读出来观察它们是否稳定在某个值附近。如果系数一直在大幅震荡说明步长太大或者有bug。第二个是看误差信号的统计特性。如果DFE工作正常误差信号应该接近高斯分布均值接近零。如果误差信号有偏置或者分布异常说明判决门限或者系数更新有问题。第三个是看眼图。在DFE输出端接一个眼图仪观察眼图的张开程度。如果眼图张开度明显改善说明DFE在起作用。我还会做一个“旁路测试”把DFE旁路掉直接看无均衡的误码率然后打开DFE对比误码率的改善。如果改善不明显就要检查DFE的配置是否正确。6.5 从BPSK到高阶QAMDFE的扩展思路BPSK是最简单的调制方式DFE的判决器只需要一个门限。但实际系统里常用高阶QAM比如16QAM、64QAM判决器需要在二维星座图上找最近的星座点复杂度高很多。对于高阶QAMDFE的前馈和反馈滤波器结构不变但判决器的实现要改。而且高阶QAM对ISI更敏感因为星座点之间的距离更近。所以DFE的抽头数可能需要增加步长需要减小训练序列需要加长。另外高阶QAM的LMS误差信号是复数系数更新也是复数运算。实现的时候要注意复数的乘加运算量是实数的四倍左右资源规划要留足余量。我在一个16QAM的项目里前馈抽头用了11个反馈抽头用了5个训练序列用了1000个符号才把误码率降到可接受的水平。相比BPSK资源开销大了不少但这是高阶调制必须付出的代价。7. 一些参数调节的实战心得步长μ的调节我习惯从一个小值开始比如0.001然后逐步增大观察MSE收敛曲线。当曲线开始出现明显震荡时往回退一半这个值通常就是比较合适的。不要一上来就用大步长虽然收敛快但稳态性能差而且容易发散。前馈抽头数Nf的选择我一般从信道冲激响应的长度出发。如果信道有L个显著径Nf至少取2L到3L。比如三径信道Nf取7到9比较合适。反馈抽头数Nb取L-1就够了因为反馈滤波器只需要覆盖已判决符号造成的ISI。训练序列的长度我的经验公式是train_len 10 * (Nf Nb)。对于Nf7、Nb3训练序列至少100个符号。如果信道条件差加倍。还有一个容易被忽略的参数是误差信号的限幅。在LMS更新的时候如果误差信号突然变得很大比如因为一次严重的判决错误系数会被大幅调整可能导致不稳定。我通常会给误差信号加一个限幅把它的绝对值限制在一个合理范围内比如±2。这个简单的措施能显著提高系统的鲁棒性。最后别忘了在仿真里加噪声。有些人在仿真的时候只加信道ISI不加噪声结果DFE跑得很好到了硬件上就完全不行。噪声是真实系统里不可避免的仿真必须包含它而且要在不同的SNR下都测试一遍确保DFE在各种条件下都能稳定工作。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价