第四章 数字信号处理基础:ADC/DAC选型、DDC、DUC与FPGA信号处理流程
各位同学,咱们今天聊点实在的。数字信号处理这块,说白了就是干扰机的“心脏”。ADC/DAC选不好,后面算法再牛也白搭。DDC和DUC搞不明白,信号搬移就会出乱子。我当年刚入行时,就在ADC选型上栽过跟头,今天把这些经验掰开了讲给你们听。
4.1 ADC/DAC选型:别光看位数
很多人选ADC,第一反应就是“位数越高越好”。嗯,这话对了一半。但干扰机这种场景,你得多想几步。
采样率是第一道坎。根据奈奎斯特定理,采样率至少是信号最高频率的两倍。但实际工程中,我建议留出20%~30%的余量。为什么?因为抗混叠滤波器不是理想砖墙,过渡带会吃掉一部分带宽。
有效位数(ENOB)比标称位数更重要。标称12位的ADC,实际有效位数可能只有9~10位。我在项目中遇到过一款标称14位的ADC,实测ENOB只有10.5位,差点把动态范围搞崩了。所以选型时一定要看数据手册里的ENOB曲线,别只看标题。
无杂散动态范围(SFDR)是干扰机的命门。你想想看,干扰机要发射大功率信号,如果ADC自身的杂散太大,会把弱小目标信号淹没掉。我一般要求SFDR比系统需求高10dB以上。
ADC选型核心参数速查表
| 参数 | 干扰机场景要求 | 我的经验值 |
|---|---|---|
| 采样率 | ≥2.5倍信号带宽 | 留30%余量 |
| ENOB | ≥10位 | 实测为准 |
| SFDR | ≥70dBc | 越高越好 |
| 输入带宽 | 覆盖工作频段 | 注意滚降点 |
DAC选型思路类似,但要多关注更新率和无杂散动态范围。我曾经用过一款DAC,标称更新率1GSPS,但实际在800MHz以上输出时,SFDR掉了15dB。后来查原因,是输出匹配没做好。嗯,这里要注意:DAC的输出匹配网络直接影响高频性能。
4.2 数字下变频(DDC):把高频信号拉下来
DDC的作用,说白了就是把ADC采到的高中频信号,搬移到基带或者低中频。这样FPGA处理起来就轻松多了。
标准DDC流程分三步:
- 数字混频:用NCO产生的本振信号与输入信号相乘,得到I/Q两路
- 低通滤波:滤除混频产生的高频分量和带外噪声
- 抽取:降低数据率,减轻后续处理压力
我习惯用多级抽取的方式。比如总抽取因子是16,我会拆成2级:先4倍抽取,再4倍抽取。为什么?因为单级抽取的滤波器阶数太高,资源消耗大。分两级做,每级滤波器阶数能降一半左右。
小技巧:NCO的相位累加器位数要足够。我一般用32位累加器,频率分辨率能做到0.01Hz级别。别为了省几个LUT用16位,频率精度不够时,干扰信号会跑偏。
这里贴一段DDC的核心代码片段,用的是Xilinx的DDS和FIR IP核:
// DDC顶层模块示意
module ddc_top (
input clk_adc, // ADC采样时钟
input signed [15:0] adc_data, // ADC数据
output signed [15:0] i_out, // I路输出
output signed [15:0] q_out // Q路输出
);
// 实例化NCO
dds_compiler_0 u_nco (
.aclk(clk_adc),
.s_axis_phase_tvalid(1'b1),
.s_axis_phase_tdata(phase_inc), // 频率控制字
.m_axis_data_tvalid(),
.m_axis_data_tdata({cos, sin}) // 余弦和正弦
);
// 混频器
assign i_mix = adc_data * cos;
assign q_mix = adc_data * sin;
// 低通滤波+抽取
fir_compiler_0 u_fir_i (
.aclk(clk_adc),
.s_axis_data_tvalid(1'b1),
.s_axis_data_tdata(i_mix),
.m_axis_data_tvalid(),
.m_axis_data_tdata(i_out)
);
endmodule
4.3 数字上变频(DUC):把信号搬回高频
DUC是DDC的逆过程。基带信号先内插提高数据率,再滤波消除镜像,最后混频到目标频率。
内插有个坑:内插因子越大,镜像频率离得越近,滤波器设计越难。我建议内插因子不超过8。如果总内插因子是32,就分3~4级做。每级内插2~4倍,滤波器阶数控制在100阶以内。
混频后的信号,如果是正交调制,I/Q两路直接相加就得到实信号。但要注意:I/Q两路的增益必须一致,相位差要严格90度。我曾经遇到过I/Q不平衡的问题,导致输出信号有镜像分量,干扰效果大打折扣。后来加了数字校正模块才解决。
警告:DUC的输出数据率很高,DAC接口时序很容易出问题。我建议用OSERDES或DDR输出,确保数据与时钟对齐。另外,DAC的模拟输出要加抗镜像滤波器,别指望数字滤波能搞定一切。
4.4 FPGA信号处理流程:从天线到天线
整个干扰机的信号处理,在FPGA里走这么一圈:
- ADC接口:接收高速数据,做位同步和串并转换
- DDC:下变频到基带,降低数据率
- 干扰产生:根据策略生成干扰波形(噪声、欺骗、转发等)
- DUC:上变频到发射频率
- DAC接口:并串转换,输出到DAC
这里面,干扰产生是核心。我做过几种常见的干扰波形:
- 噪声干扰:用LFSR或高斯噪声发生器,带宽可调
- 欺骗干扰:存储并转发接收信号,加延时和多普勒调制
- 灵巧干扰:分析信号特征,针对性生成干扰
FPGA的流水线设计要特别注意时序收敛。我一般这样安排:
- ADC接口和DDC用高频率时钟域(比如250MHz)
- 干扰产生用中频率时钟域(比如125MHz)
- DUC和DAC接口用高频率时钟域(与ADC同频)
跨时钟域处理要用异步FIFO或握手信号。我习惯用Xilinx的FIFO IP核,简单可靠。千万别自己写异步FIFO,容易出亚稳态问题。
我的FPGA设计检查清单
- ✅ 所有跨时钟域信号都经过同步处理
- ✅ DDC/DUC的滤波器系数量化后性能达标
- ✅ NCO的频率控制字计算正确
- ✅ 流水线各级的位宽匹配,没有截位误差累积
- ✅ 时序约束完整,setup/hold满足要求
最后说一句:仿真验证一定要做。我每次改完代码,都会跑定点仿真,对比浮点模型的结果。差3dB以内算正常,超过5dB就要查问题了。别等到板子上才发现,那时候定位问题成本高得多。
好了,这一章就到这里。数字信号处理这块,理论不难,但工程细节很多。你们回去把ADC选型参数表背熟,把DDC/DUC的流程画一遍,下次课我们讲干扰波形生成的具体实现。