第2章 数字信号处理基础:采样定理、量化编码与数字混频

各位同学,咱们今天聊聊数字信号处理里最基础、也最绕不开的几个概念。说实话,这些内容看起来像是教科书上的老古董,但我在做电子对抗项目时,几乎天天跟它们打交道。你想想看,一个信号从天线进来,到FPGA里变成数字流,再到你把它分析出来,每一步都离不开这些基础。

2.1 采样定理(Nyquist)——别让信号“说谎”

采样定理,说白了就是一句话:采样频率至少要是信号最高频率的两倍。为什么?因为低于这个频率,信号就会“混叠”,你看到的频率就不是真实的频率了。

我举个例子。假设你有一个10MHz的正弦波,你用15MHz去采样。结果呢?FPGA里恢复出来的信号看起来像5MHz。这就是混叠。我在做雷达信号侦察时,遇到过这种情况——明明敌方雷达是10GHz的,我这边采样率不够,结果在频谱上看到的是5GHz。嗯,那后果你懂的。

核心公式:

fs ≥ 2 × fmax

其中 fs 是采样频率,fmax 是信号最高频率。

实际工程中,我建议留出20%~30%的余量。比如信号最高频率100MHz,采样率至少做到250MHz。为什么?因为实际滤波器不是理想的,会有过渡带。我曾经因为只留了10%的余量,结果带外噪声混叠进来,整个系统信噪比掉了3dB。那叫一个惨。

个人经验:在FPGA里做采样率转换时,一定要先确认输入信号的带宽。我习惯在ADC后面加一个抗混叠滤波器,哪怕只是简单的RC低通,也能省去很多麻烦。

2.2 量化与编码——精度和资源的博弈

采样是把连续时间变成离散时间,量化则是把连续幅度变成离散幅度。说白了,就是用有限个数字去表示无限个可能的电压值。

量化位数(bit数)直接决定了你的动态范围和信噪比。公式很简单:

SNR ≈ 6.02 × N + 1.76 dB

其中N是量化位数。12位ADC的理论SNR大约是74dB,14位就是86dB。听起来不错对吧?但你要知道,实际ADC的有效位数(ENOB)往往比标称值低1~2位。我测过一款标称14位的ADC,实际有效位数只有11.5位。嗯,厂商的广告嘛,你懂的。

量化位数 理论SNR (dB) 实际ENOB (典型) 适用场景
8位 49.9 7.2 简单检测、通信
12位 74.0 10.5 雷达、电子对抗
14位 86.0 11.5 高精度测量
16位 98.1 13.0 音频、低频信号

编码方式上,最常见的是二进制补码。FPGA里处理有符号数,补码是标配。我建议你养成习惯:所有信号处理链路都用补码,别混用原码和反码,否则调试时你会疯掉。

注意:量化误差是不可避免的,但你可以通过过采样+噪声整形来改善。说白了就是用更高的采样率换取有效位数。我在做宽带电子对抗接收机时,就用过4倍过采样,把12位ADC用出了13位的效果。

2.3 数字混频(DDC/DUC)——搬移频率的利器

数字混频,就是让信号在频率上“搬家”。DDC(数字下变频)把高频信号搬到基带,DUC(数字上变频)把基带信号搬到高频。这在电子对抗里太常见了——你收到的信号可能是2GHz的,但FPGA处理不了那么快,得先下变频到几十MHz甚至基带。

DDC的基本结构:

输入信号 → 混频器(× cos + × sin) → 低通滤波 → 抽取 → 输出I/Q

这里有个关键点:混频后的信号包含和频和差频。低通滤波器的作用就是滤掉和频,保留差频。我刚开始做的时候,滤波器设计得不够好,结果和频分量泄漏进来,整个解调都乱了。后来我学乖了,滤波器阶数至少留到80阶,过渡带宽设成信号带宽的1.5倍。

DUC则是反过来:

输入I/Q → 内插 → 低通滤波 → 混频器(× cos + × sin) → 输出

我个人习惯在DDC/DUC里用多级级联的结构。比如先做2倍抽取,再做2倍抽取,而不是一次做4倍抽取。为什么?因为单级滤波器的阶数太高,资源消耗大,而且延迟也大。多级级联可以用更少的资源达到同样的滤波效果。

避坑指南:我曾经在DUC里忘了考虑内插后的镜像频率,结果发射出去的信号带了一堆杂散。记住:内插之后一定要加滤波器,否则镜像分量会把你害惨。

2.4 CORDIC算法原理——用移位和加法算三角函数

CORDIC(坐标旋转数字计算机)是个很有意思的算法。它不用乘法器,只用移位和加法就能算sin、cos、反正切这些函数。在FPGA里,乘法器是稀缺资源,但移位器和加法器管够。所以CORDIC特别适合硬件实现。

它的核心思想是:通过一系列固定的角度旋转,逼近目标角度。每次旋转的角度是预先算好的,比如45°、26.565°、14.036°……这些角度有个特点:tan(θ) = 2-i,所以旋转操作可以用移位实现。

伪代码大概是这样:

// 计算 sin(θ) 和 cos(θ)
x = 1 / 1.64676  // 初始值,补偿增益
y = 0
z = θ

for i = 0 to N-1:
    d = sign(z)  // 判断旋转方向
    x_new = x - d * y * 2^(-i)
    y_new = y + d * x * 2^(-i)
    z_new = z - d * atan(2^(-i))
    x = x_new
    y = y_new
    z = z_new

// 结果:cos(θ) ≈ x, sin(θ) ≈ y

迭代次数N决定了精度。一般来说,16次迭代就能达到16位精度。我在项目中用过12次迭代,精度也够用,但相位误差会大一些。如果你做的是相参处理,我建议至少迭代16次。

实际应用:CORDIC在DDC里可以直接生成NCO(数控振荡器)的正余弦值。比查表法省资源,比直接计算快。我在一个宽带接收机项目里,用CORDIC替代了ROM查表,LUT资源节省了40%。

不过CORDIC也有缺点:它只能算一个角度一个角度地逼近,不能并行算多个频率。如果你需要同时生成多个频率的载波,查表法可能更合适。嗯,具体选哪个,得看你的资源预算和性能要求。

注意:CORDIC的输入角度范围有限,一般是[-π/2, π/2]。如果角度超出这个范围,需要先做象限映射。我刚开始用的时候忘了这茬,结果算出来的sin值全是错的。调试了两天才发现是角度范围的问题。

好了,这一章的内容就这些。采样定理告诉你该用多快的速度采样,量化编码告诉你该用多少位来表示,DDC/DUC帮你搬移频率,CORDIC帮你算三角函数。这些都是数字信号处理的基石,也是你在FPGA里做电子对抗信号处理必须掌握的东西。

下一章咱们聊聊滤波器设计,那又是另一番天地了。