第四章 数字信号处理基础: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流程分三步:

  1. 数字混频:用NCO产生的本振信号与输入信号相乘,得到I/Q两路
  2. 低通滤波:滤除混频产生的高频分量和带外噪声
  3. 抽取:降低数据率,减轻后续处理压力

我习惯用多级抽取的方式。比如总抽取因子是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里走这么一圈:

  1. ADC接口:接收高速数据,做位同步和串并转换
  2. DDC:下变频到基带,降低数据率
  3. 干扰产生:根据策略生成干扰波形(噪声、欺骗、转发等)
  4. DUC:上变频到发射频率
  5. 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的流程画一遍,下次课我们讲干扰波形生成的具体实现。