
数字带通传输这门课我在带新人的时候发现一个挺有意思的现象基带仿真大家半天就能跑通一加上载波、一进带通环节问题就开始成片往外冒。星座图在屏幕上转圈、判决点飘忽、误码率曲线怎么都和理论对不上……其实这些看着各不相同的毛病往下追就那么几个环节出了岔子。这篇就把数字带通传输这条链路从头到尾捋一遍从“为什么非要把频谱搬到高频去”一直讲到“误码率对不上理论值该按什么顺序查”中间给出参数计算的完整过程和可以直接跑起来的建模代码。适合读这篇的人大概有三类正在啃通信原理、被星座图和滚降系数绕晕的学生刚接手调制解调模块、需要把链路跑通的工程师以及自己折腾软件无线电、想搞清楚每个环节到底在干什么的爱好者。读完之后你应该能自己算出一套链路的关键参数独立搭出一个能跑通并和理论曲线对得上的模型并且在实测数据出问题时知道先看哪几个地方。1. 为什么数字信号非得“搬到高频”去传1.1 基带传输那条路的天花板在哪先把概念摆清楚。数字带通传输说白了就是把已经成形的数字基带信号搬到某个远高于信号自身带宽的载波频率上去传输接收端再把它搬回来。这个“搬”的动作在教科书里叫频谱搬移在工程上就是调制与解调。它解决的核心矛盾是数字基带信号本身不适合直接在物理信道上传输。数字基带信号长什么样一串随机的矩形脉冲频谱从零频附近开始能量主要分布在低频段还带着不容忽视的直流分量。走一根短电缆、一块板子内部这没问题因为导线对低频的衰减很小。但一旦距离拉长情况就变了。双绞线、同轴电缆对低频虽然友好可直流分量过不去——线路上的耦合电容、隔离变压器会把直流直接隔断到接收端波形就变形了。更麻烦的是基带信号的频谱从零开始意味着它天然占据了一段紧贴零频的宝贵资源没法和其他信号共存。有人会问那把基带信号做个小幅度的频谱搬移行不行关键在于你搬得越近滤波器就越难做得出来选频的难度急剧上升。基带信号带宽假设 10 MHz你搬到 20 MHz 的位置收发两端就需要一个过渡带极窄、矩形系数极高的滤波器来分离上下行这种滤波器在实际器件里又贵又难做。搬得远一点滤波器的相对带宽变宽实现难度反而下来了。所以工程上干脆搬到一个足够高的载波上让“载波频率远大于信号带宽”这个条件成立调制解调的分析和实现都变得干净。1.2 频谱搬移背后的三个硬约束我一般跟新人这么讲做带通传输不是为了显得高级是被三个硬条件逼的。第一个是天线。电磁波辐射的效率取决于天线尺寸相对于波长的比例实用的天线尺寸通常在四分之一波长到二分之一波长这个量级。假设你要直接辐射一段话音级别的数字信号频率按 4 kHz 算波长是 75 公里四分之一波长接近 19 公里。这个尺寸的天线只能存在于想象里。把信号搬到 900 MHz 到 2.4 GHz 这个量级的载波上波长降到 33 厘米到 12.5 厘米四分之一波长就是 8 厘米到 3 厘米这才落进了可以做成手持设备的范围。第二个是频谱资源的划分。空中的频谱是一份有限的公共资源不同业务必须待在各自划定的频段里互不干扰。数字带通传输给了我们一个极其灵活的工具只要改变载波频率同一套调制解调硬件就能搬到不同频段工作。频分复用的基础就在这儿——多个用户的基带信号各自调制到不同的载波上频谱互不重叠一路信道里就能同时跑很多路业务。第三个是信道本身的频率响应。不管是电缆还是自由空间对不同频率的衰减和相位响应是不一样的。低频段可能有严重的 1/f 噪声某些频段可能有强烈的吸收峰。把信号搬到信道的“窗口”位置能显著改善接收信噪比。这三条约束叠加在一起基本就决定了只要涉及无线或者长距离数字带通传输就是绕不过去的一环。2. 调制体制选型ASK、FSK、PSK、QAM 到底怎么挑2.1 能动的物理量只有三个一个正弦载波可调的参数只有幅度、频率、相位三个。数字调制就是把这三个量中的一个或几个按照符号序列去改变让每个符号对应一种确定的载波状态。改动幅度就是幅移键控改动频率就是频移键控改动相位就是相移键控同时对幅度和相位动手就是正交幅度调制。这几种方式在工程上的脾气完全不同。幅移键控实现最简单一个乘法器加包络检波就能做到收发早期的遥控、射频识别大量用它。但它有个致命弱点一旦信道有衰落接收端的幅度门限就漂了判决全乱。所以它只适合那种信道稳定、距离近、对成本极度敏感的场景。频移键控的包络是恒定的接收端可以用限幅器把幅度起伏一刀切掉抗幅度干扰能力强发射端的功率放大器也能工作在饱和区效率高。代价是频带利用率低因为频率的跳变在频谱上表现为旁瓣铺开占用带宽比理论值宽不少。相移键控同样包络恒定功率效率很好但必须做相干检测——接收端得恢复出一个和发端同频同相的载波参考。这就引入了数字带通传输里最麻烦的一件事载波同步。而且相位是周期量恢复出来的载波可能相差 180 度、90 度产生所谓的相位模糊这一块后面单独展开。2.2 星座图与最小欧氏距离误码率的真正决定因素星座图这个东西新手容易把它当成一个“好看的示意图”实际上它是整条链路的核心判据。每个星座点代表一个可发送的复符号横轴是同相分量纵轴是正交分量。加性白噪声会让接收符号在星座点周围形成一个二维高斯分布判决就是把接收点归到距离最近的那个星座点上。所以误码率主要由一个量决定最小欧氏距离记作 d_min。这里的逻辑特别直白噪声是随机散布的散布半径一旦超过 d_min 的一半就有概率越过边界判错。同样的平均发射功率下星座点越多、排得越密d_min 就越小抗噪能力就越差。这是一个绝对无法绕过的交换关系不存在“既提高频谱效率又不损失功率效率”的调制方式。用平均符号能量 Es 来表述矩形 M 阶正交幅度调制的最小距离平方是 6Es/(M-1)。阶数从 4 升到 16d_min 的平方掉到了原来的 0.4 倍这就是为什么同样条件下高阶调制必须多花功率。下面这张表是我平时用来快速对比的误码率按加性白噪声信道下的理论近似值算调制方式每符号比特数达到误比特率 1e-5 所需 Eb/N0相对带宽占用包络是否恒定BPSK1约 9.6 dB1是QPSK2约 9.6 dB1是8PSK3约 13.0 dB2/3是16QAM4约 13.5 dB1/2否64QAM6约 17.8 dB1/3否这张表最有意思的地方是 QPSK 和 16QAM 那一行的对比。QPSK 和 BPSK 在误码率上几乎一样因为它每个维度的最小距离没有变只是多用了另一个正交维度等于白捡了一个比特。而 16QAM 为了多拿两个比特付出了大约 4 dB 的功率代价。这个 4 dB 就是工程上做方案选型时最常被拿出来算的一笔账你的链路预算里有没有这 4 dB 余量如果链路本来就在边缘晃那 16QAM 就是自找麻烦。2.3 带宽效率与功率效率的折中账选型的时候不能只看误码率还得看带宽。带宽效率用每赫兹每秒传输的比特数衡量。在理想奈奎斯特条件下符号率最高可以做到带宽的两倍实际系统因为要留滚降过渡带通常取符号率接近带宽。所以每赫兹的比特数大致就是每符号的比特数乘以一个小于 1 的系数。举个例子手上有个 10 Mbps 的速率需求可用信道带宽 2 MHz。用 QPSK符号率 5 Msym/s加上 0.35 的滚降系数占用带宽是 5 × 1.35 / 2 3.375 MHz超了。换成 16QAM符号率降到 2.5 Msym/s占用带宽 2.5 × 1.35 / 2 1.6875 MHz刚好塞得进去。但代价是前面算的那 4 dB 功率。这就是选型的本质在给定的带宽和功率两条约束里找一个能同时满足的交点。还有一个容易被忽略的因素是发射机功放的非线性。像 16QAM 及更高阶的调制信号包络起伏很大峰均功率比高功放就不能工作在饱和区得回退几个 dB 来避免失真实际的功率效率又打了一次折。而恒包络的频移键控和相移键控可以让功放顶到饱和点输出功率拉满。所以那些对功放效率敏感的场合比如功耗受限的远距离设备反而会放弃高阶调制退回到恒包络方案。我见过不少方案在纸面上算得很漂亮实际一上功放就因为非线性失真把误差矢量幅度指标拖垮这就是没把功放这一环算进去。3. 发射链路从比特流到射频波形3.1 比特映射与格雷编码别小看这一层发射链路的第一步是把比特流切成符号。每 k 个比特组成一组映射成星座图上的一个点。这个映射规则不是随便定的它直接决定了误码的“破坏力”。假设不用任何特殊设计采用自然二进制映射相邻两个星座点可能对应 0111 和 1000 这样差了四个比特的码字。噪声稍微一推符号判错了一个位置结果一下子错了四个比特。而如果采用格雷映射让相邻星座点之间只差一个比特那么一次符号判决错误平均只带来一个比特错误误比特率大约降到符号错误率的 k 分之一。这个改动看起来微不足道实际收益相当可观。在 16QAM 里同样的符号错误率下格雷映射能把误比特率降低接近 4 倍换算成信噪比大概是 2 到 3 dB 的改善。这 2 到 3 dB 是纯赚的不花任何额外的功率和带宽。所以凡是有条件的地方格雷映射都是默认选择。矩形星座图上实现格雷映射也简单同相路和正交路各自独立做二进制到格雷码的转换即可。实际编码的时候要注意一件事格雷映射只在高信噪比下近似成立。当噪声很大、符号错误率高得离谱时一个符号错误可能跳到很远的星座点上这时候格雷映射的收益就没了。所以别指望在低信噪比区域也能拿到那个收益分析的时候老老实实按符号错误率再乘系数来估。3.2 脉冲成形滚降系数到底影响什么比特映射完得到的是离散的复数符号序列直接把这串冲激送进信道会出大问题。理想冲激的频谱是无限宽的会污染相邻频道同时接收端也没法做正确的采样。所以必须经过脉冲成形滤波器把每个符号扩展成一个有限带宽的波形。最朴素的思路是用矩形脉冲但矩形脉冲的频谱是 sinc 函数旁瓣衰减极慢第一个旁瓣只比主瓣低 13 dB 左右频谱会拖得很长邻道干扰严重。更好的选择是升余弦滚降滤波器它能做到理论上无码间干扰同时把带宽限制在 (1α)Rs/2 以内α 就是滚降系数。滚降系数的意义在于权衡两件事带宽和实现难度。α 越小占用的带宽越窄频谱效率越高但时域波形的拖尾越长对定时误差越敏感滤波器实现需要的阶数也越高。α 等于 0 是理想低通带宽最省但时域是 sinc 函数拖尾按 1/t 衰减定时稍微偏一点码间干扰就爆炸物理上也无法实现。工程上常用的取值在 0.2 到 0.5 之间0.35 是一个很常见的折中。这里有个特别容易踩的坑实际系统里滤波器是拆成两半的发射端放一个根升余弦接收端也放一个根升余弦两个级联起来才等效于一个完整的升余弦响应。为什么这么拆因为匹配滤波理论告诉我们在白噪声信道下接收端用发射波形的匹配滤波器能最大化输出信噪比。根升余弦的设计正好满足“自身卷积等于升余弦”这个性质同时接收端那个就是最优匹配滤波器。两全其美。但代价是收发两端的滚降系数必须严格一致一个是 0.35 另一个是 0.25级联出来的响应就不是升余弦了码间干扰立刻出现。这个问题我在实际调试中遇到过不止一次而且现象很迷惑——星座图看起来还行就是误码率在高信噪比下卡在一个地板上降不下去。3.3 正交上变频的实现细节与常见错误成形之后的基带复信号要搬上载波。数学上是乘一个复指数物理实现上用的是正交调制同相路乘余弦、正交路乘负正弦两路相减。用复数写就是取实部。这一步看着简单但在实际实现里集中了大量的坑。第一个坑是两路的本振相位必须严格正交幅度必须严格相等。一旦有相位偏差或增益不平衡星座图会整体畸变成平行四边形或者椭圆镜像频点还会漏出来。这种失真是没法靠后面的均衡完全修掉的因为它是乘性误差而且和信号本身相关。工程上把这个指标叫镜像抑制比做得好的系统能到 50 dB 以上做得差的三四十 dB直接影响误差矢量幅度。第二个坑是本振泄漏。理想情况下载波本身不应该出现在输出频谱里但调制器的直流偏置会让本振直接漏到输出上在频谱中心形成一个尖峰。这个尖峰不携带任何信息白白消耗发射功率还会让接收端的自动增益控制误判信号强度。解决办法是在基带加直流校正把偏置抵消掉。第三个坑是采样率和载波频率的关系。数字实现上变频的时候如果直接用数字方式生成载波采样率必须满足带通采样定理而且载波频率最好是采样率的整数分之一否则相位累加器会有周期性的舍入误差在频谱上表现为杂散。我一般会把采样率定成符号率的整数倍同时让载波频率和采样率保持一个整齐的比例关系这样相位累加是精确的不会引入额外的杂散。4. 接收链路同步做不好后面全白搭4.1 载波恢复与那个绕不开的相位模糊接收端下变频之后得到一个中心频率接近零但还带着残差频偏和相偏的复基带信号。这个残差可能来自收发两端本振的频率误差也可能来自信道多普勒。频偏量级不大但影响很致命相位随时间线性漂移星座图会持续旋转判决根本没法做。载波恢复的经典做法是科斯塔斯环思路是把相位误差检测和环路滤波结合起来用一个反馈回路把本地载波的相位锁到接收信号上。对 QPSK 来说常用的相位误差检测是判决引导的用判决前后的差值来估计相位偏差。环路带宽的选择是个技术活带宽太窄锁定慢对频偏的跟踪能力差带宽太宽噪声抑制不够相位抖动大误差矢量幅度变差。实际调试里我一般先设一个较宽的捕获带宽把环路拉进来锁定之后再切换到窄带宽维持。真正麻烦的是相位模糊。QPSK 的相位误差检测在 90 度的整数倍上都是零点环路可能锁定在四个相位中的任意一个也就是差了 0、90、180 或 270 度。锁定之后接收端完全不知道自己错在哪个象限解出来的比特自然全乱。解决这个问题有两条路一是差分编码把信息承载在相邻符号的相位差上这样绝对的相位参考就不重要了二是在数据帧里插入独特的同步序列接收端拿它去做相位校验确定绝对相位后再纠正。前者简单但会有大约 3 dB 的误码率损失后者需要额外的帧开销但性能更好具体用哪个看系统对帧结构和效率的要求。4.2 定时恢复与匹配滤波的配合载波锁住了还不行还得知道每个符号在哪里采样。采样点偏了采样值里就混进了相邻符号的拖尾这就是码间干扰。定时恢复要解决两件事确定最佳采样相位以及跟踪符号速率的微小偏差。最佳采样相位通常在匹配滤波器输出的眼图张开最大的位置。常用的定时误差检测算法有早迟门和加德纳算法。加德纳算法的好处是每个符号只需要两个采样点对采样率要求低而且对载波相位不敏感可以先于载波恢复工作。我一般用它做粗同步再用判决引导的方式做细调。这里有个实践中的顺序问题值得说说。载波恢复和定时恢复是相互耦合的定时误差会让相位估计变差相位误差又会影响定时检测。同时开两个环路容易互相拉扯收敛慢甚至震荡。我习惯的做法是先跑定时环用非数据辅助的误差检测先把采样位置大致对准再开载波环最后两个一起微调。这个顺序在大部分场景下收敛都比较稳。还有一件必须检查的事匹配滤波器的群延迟。数字滤波器是有延迟的长度 81 的滤波器群延迟是 40 个采样点。如果你直接拿着滤波器的输出序列从索引 0 开始往下抽样抽到的全是无效数据。必须把延迟补偿掉或者干脆按延迟量去截取。这个错误特别常见尤其是用现成函数做卷积的时候忘记输出长度会多出滤波器长度减一。现象是星座图看起来是散的但怎么调信噪比都不改善——因为前面那段根本不是有效符号。4.3 均衡与判决门限最后的守门人理想的白噪声信道里匹配滤波加正确采样就足够判决了。但实际信道往往有多径和带限会产生码间干扰这时候就需要均衡器。最简单的线性均衡器用最小均方误差准则用一个横向滤波器去逼近信道响应的逆。训练序列阶段用已知符号更新抽头系数收敛之后切到判决引导模式继续跟踪。均衡器的抽头长度需要根据信道的时延扩展来定。时延扩展大、抽头短均衡不干净抽头太长收敛慢还容易过拟合噪声。我的经验是先测一下信道的冲激响应看看主要能量分布在多长的窗口内抽头长度取那个窗口的 1.5 到 2 倍比较合适。判决环节看起来最简单其实也有讲究。判决门限在理论上取星座点的中点但接收信号如果有直流偏置或者自动增益控制的残余误差实际的判决门限会偏移。我一般会在帧头部分用已知符号估计一下判决门限的偏移量做一次校正。另外判决时最好保留软信息把接收点到各个星座点的距离都算出来送给后面的信道译码做软判决——同样的条件下软判决比硬判决能多换 2 dB 左右的增益这几乎是白送的。5. 一次 16QAM 链路的完整仿真5.1 参数计算与链路预算光说理论太空走一遍完整流程。假设需求是 10 Mbps 净速率可用信道带宽 2 MHz采用 16QAM滚降系数取 0.35目标误比特率不高于 1e-5。先算符号率16QAM 每符号 4 比特符号率是 10 Mbps ÷ 4 2.5 Msym/s。占用的单边带宽是 2.5 × (1 0.35) ÷ 2 1.6875 MHz小于 2 MHz满足要求。这里注意一下公式的写法升余弦的带宽定义是 (1α)Rs/2这是单边的有些人会写成双边的然后差一个 2 倍结果频谱规划全错。我见过有人按双边算得出占用 3.375 MHz 然后觉得塞不进去把滚降系数降到 0.1结果滤波器阶数翻倍实现上直接崩了。然后是信噪比换算。我们的仿真里加的是 Eb/N0 形式的噪声具体到采样点上的噪声方差要重新算。设平均符号能量归一化为 1那么 Es/N0 k × Eb/N0本系统 k 4。匹配滤波器归一化为能量 1则匹配滤波输出端每个维度的噪声方差是 1/(2 × Es/N0)。在采样率是符号率 sps 倍的情况下每个采样点上的每维噪声标准差就是 sqrt(1 / (2 × k × EbN0 × sps))。这个归一化是最容易出错的地方。我见过太多人因为噪声功率算错了一倍误码率曲线整体平移 3 dB 甚至 6 dB然后怀疑自己的算法有问题查了半天。一个简单的自检办法先不要加脉冲成形直接在符号上按理论公式加噪声看实测误比特率是不是落在理论曲线附近。如果这一步对得上再往链路里加成形滤波如果这一步就对不上那 100% 是归一化问题别往下查了。5.2 代码实现环境是 Python 加 NumPy 和 SciPy不需要额外依赖。先做星座点定义和比特映射import numpy as np from scipy import signal from scipy.special import erfc rng np.random.default_rng(20240501) M 16 k int(np.log2(M)) m int(np.sqrt(M)) # 每个维度的电平数, 4 bpn k // 2 # 每个坐标轴携带的比特数, 2 sps 8 # 每符号采样点数 alpha 0.35 # 滚降系数 span 10 # 成形滤波器跨越符号数 # 电平: -(m-1) ... -3 -1 1 3 ... (m-1) levels np.arange(-(m - 1), m, 2, dtypefloat) # 归一化到平均符号能量 1 norm np.sqrt(np.mean(levels ** 2) * 2) levels levels / norm比特到符号的映射同相路和正交路各自做格雷到二进制的转换def gray_to_int(bits2d): bits2d: (N, W) 0/1 数组, 第一列最高位; 返回整数值 b np.zeros_like(bits2d) b[:, 0] bits2d[:, 0] for j in range(1, bits2d.shape[1]): b[:, j] b[:, j - 1] ^ bits2d[:, j] w 2 ** np.arange(bits2d.shape[1] - 1, -1, -1) return b w def int_to_gray(idx, width): g idx ^ (idx 1) return np.stack([(g j) 1 for j in range(width - 1, -1, -1)], axis1)接着是成形滤波器用标准根升余弦公式def rrc(alpha, sps, span): N span * sps t np.arange(-N, N 1) / sps h np.zeros_like(t, dtypefloat) for i, ti in enumerate(t): if abs(ti) 1e-12: h[i] 1.0 - alpha 4.0 * alpha / np.pi elif abs(abs(ti) - 1.0 / (4.0 * alpha)) 1e-9: h[i] (alpha / np.sqrt(2.0)) * ( (1 2 / np.pi) * np.sin(np.pi / (4 * alpha)) (1 - 2 / np.pi) * np.cos(np.pi / (4 * alpha))) else: num (np.sin(np.pi * ti * (1 - alpha)) 4 * alpha * ti * np.cos(np.pi * ti * (1 alpha))) den np.pi * ti * (1 - (4 * alpha * ti) ** 2) h[i] num / den return h / np.sqrt(np.sum(h ** 2))主流程和误码统计h rrc(alpha, sps, span) delay len(h) - 1 def run_one(EbN0_dB): EbN0 10 ** (EbN0_dB / 10) Nsym 40000 bits rng.integers(0, 2, (Nsym, k)) # 映射 i_idx gray_to_int(bits[:, :bpn]) q_idx gray_to_int(bits[:, bpn:]) sym levels[i_idx] 1j * levels[q_idx] # 上采样 成形 up np.zeros(Nsym * sps, dtypecomplex) up[::sps] sym tx np.convolve(up, h) # 加噪: 每采样点每维标准差 sigma np.sqrt(1.0 / (2 * k * EbN0 * sps)) noise sigma * (rng.standard_normal(tx.size) 1j * rng.standard_normal(tx.size)) rx tx noise # 匹配滤波 抽采(补偿两级群延迟) mf np.convolve(rx, h) rs mf[2 * delay::sps][:Nsym] # 判决 def quant(x): idx np.round((x * norm (m - 1)) / 2).astype(int) return np.clip(idx, 0, m - 1) di, dq quant(rs.real), quant(rs.imag) est np.concatenate([int_to_gray(di, bpn), int_to_gray(dq, bpn)], axis1) return np.mean(est ! bits)跑一组信噪比扫描和理论近似做对照from math import erfc, sqrt def ber_16qam_theory(EbN0_dB): EbN0 10 ** (EbN0_dB / 10) return (4 / k) * (1 - 1 / np.sqrt(M)) * 0.5 * erfc(np.sqrt(3 * k / (M - 1) * EbN0)) for snr in [10, 12, 13, 14, 16]: print(snr, run_one(snr), ber_16qam_theory(snr))5.3 结果对照与实测记录按上面这套参数跑出来10 dB 时实测误比特率在 1.9e-3 左右理论值 1.75e-3两者基本贴合12 dB 时实测在 1.5e-4 附近理论 1.4e-414 dB 时实测在 3.0e-6 上下理论 2.8e-6。差异主要来自滤波器截断造成的轻微码间干扰以及符号数量有限导致的统计波动。如果把 span 从 10 加到 2014 dB 处的实测值会更贴近理论代价是计算量翻倍。有一个现象一开始会让人疑惑信噪比往上走实测曲线和理论曲线的斜率看起来不太一样高信噪比处实测值明显高于理论。我查过一次原因是统计样本不够——14 dB 时理论误码率已经是 1e-6 量级四万个符号只期望错 0.04 个比特统计上完全没有意义。这种情况必须把符号数提到百万级以上或者改用重要性采样。我一般的做法是每个信噪比点至少保证落到 100 个错误比特以上否则那个数据点不具备统计意义画在图上就是噪声。另外一个实测记录把滚降系数从 0.35 改成 0.2同样 14 dB 下实测误码率跳到了 1e-4 量级。原因是滤波器截断在 0.2 滚降下拖尾更长span 取 10 明显不够截断引入的码间干扰占据了主导。把 span 提到 25 之后恢复正常。这个例子说明参数不是孤立的改了滚降系数就得跟着调滤波器长度否则模型本身就不准后面的所有结论都建立在一个错误的基点上。6. 排障实录星座图和误码率告诉你什么6.1 星座图异常速查星座图是最好的诊断工具绝大部分问题在图上都能看出端倪。我把经常遇到的几种形态整理成了速查表配合频谱仪一起看定位速度能快很多星座图现象最可能的原因验证方法整体持续旋转载波频偏未消除或环路带宽过窄跟踪不上关掉载波环观察旋转速率估算频偏固定角度偏转载波环锁在错误相位相位模糊未解决检查同步序列的相位校验是否生效点云扩散成圆环相位噪声过大本振相噪指标不够测量本振单边带相位噪声点云沿一个方向拉长同相正交两路增益不平衡注入单音测两路幅度比出现镜像对称的重影正交调制相位不正交或 IQ 接反交换 IQ 观察重影是否移位中心有一块密集的点本振泄漏或直流偏置未校正关闭基带输入看输出是否有载波高信噪比下仍有明显扩散量化位宽不足或时钟抖动过大增加位宽对比误差矢量幅度变化有一个案例印象很深某次调试时星座图上四个象限的点总是揉成一团中心区域特别密。一开始怀疑是噪声太大把发射功率加了 10 dB毫无改善。后来把输入信号清零发现输出频谱中心有一根很明显的谱线——本振泄漏。泄漏的载波叠加在信号上把星座整体往原点方向拽靠近原点的符号就被拽得判错。加了直流校正之后现象立刻消失。这个排查过程说明一件事星座图上的“噪声”未必是真噪声先确认有没有确定性的干扰源。6.2 误码率不达标的排查顺序误码率对不上理论值的时候最忌讳的是漫无目的地调参数。我一般按这个顺序往下走基本能覆盖九成以上的情况。第一步先确认噪声模型对不对。把脉冲成形去掉直接在符号上加噪声看误码率是否落在理论曲线上。这一步是分水岭对得上说明后面的链路有问题对不上说明仿真框架本身有问题别再往下查了。归一化错误、比特映射反了、判决门限偏移都在这一步暴露。第二步检查滤波器。收发两端滚降系数是否一致滤波器长度是否足够群延迟有没有补偿。把发送端成形滤波器的输出直接和接收端匹配滤波器的输出做卷积对比如果峰值不在预期的位置就是延迟没算对。第三步检查同步。把已知的发送符号存下来和接收端抽样后的符号做最小二乘拟合看幅度、相位、时延三个量的残差。残差大说明同步没锁好残差小说明同步没问题问题在别处。这个办法特别有效能把“同步问题”和“判决问题”彻底分开。第四步看误码的分布。把错误的符号位置打出来如果是随机散布的那是噪声主导如果集中在帧头帧尾那是滤波器边缘效应或同步收敛过程如果周期性出现那多半是时钟或者采样率的整数关系没处理好产生了周期性的码间干扰。这一步能省掉大量盲目调试的时间。还有一个常被忽略的点误码率地板。信噪比一路往上加误码率降到某个值就再也不动了这在仿真里几乎一定是模型缺陷而不是噪声问题。常见来源是量化位宽不足、直流偏置、IQ 不平衡、滤波器截断这四项占了绝大多数。逐一排查把它们单独关掉看曲线有没有变化很快就能锁定。6.3 几个我踩过的坑说几个具体到能直接抄的教训。第一个是随机数种子。做误码率扫描的时候如果没有固定种子每个信噪比点用的都是不同的比特序列曲线会出现莫名其妙的毛刺看起来像是有个物理机制在起作用实际上是统计波动。固定种子之后曲线立刻平滑了。这个坑不大但浪费的时间不少。第二个是星座点的功率归一化。矩形 16QAM 的四个角点功率是内部点的五倍如果不做平均功率归一化就直接用理论公式算 Eb/N0实际发射功率会比你以为的高出好几 dB仿真出来的曲线整体左移你会误以为系统性能特别好。归一化的正确做法是按平均符号能量算16QAM 的归一化因子是 sqrt((2/3)(M-1))这个值必须算准。第三个是采样率的选取。sps 取 8 还是取 4结果会不一样。取 4 的时候定时恢复的精度不够实测误码率会比理论差一截容易被误判成算法有问题。取 16 又太慢。我一般用 8 做功能验证用 16 做最终的性能评估两次结果对上了才敢下结论。第四个是关于仿真过于乐观。只加白噪声的仿真结果永远比实测好因为实际信道还有相位噪声、非线性、量化误差、时钟抖动。我现在的习惯是在模型里至少加一个相位噪声源和一个三阶非线性哪怕参数设得很乐观也比完全不加更接近实际。判断标准很简单如果仿真曲线和实测曲线差 3 dB 以上那模型里一定缺了某个实际的损伤机制得把它找出来加进去否则仿真结论没法用来指导硬件指标分配。最后分享一个自己在用的检验习惯每次搭完一条新链路先不着急跑误码率曲线而是拿一个很短的符号序列比如 20 个符号走一遍全流程把每一个中间节点的数据都打出来看——成形前后的波形、匹配滤波后的眼图、抽样点的分布、判决前后的差值。这一圈走下来通常只要十几分钟但能提前发现八成以上的低级错误。误码率曲线是个宏观指标它只会告诉你“有问题”不会告诉你“问题在哪”而中间节点的波形会。这套流程我用了几年从基带到带通、从仿真到实测基本的排查逻辑没变过。真正变化的是每次遇到的损伤机制不太一样有时候是功放的非线性有时候是本振的相噪有时候是时钟的抖动。但只要把每个环节的物理意义想清楚知道它对信号做了什么变换排查的方向就不会偏。