当前位置: 首页 > news >正文

FPGA数字信号处理(一)数字混频实现详解|NCO/DDS原理、有符号数避坑、直流滤除工程实战

前言

数字混频是软件无线电、调制解调、DDC数字下变频、DUC数字上变频的最基础核心操作。相比于模拟混频,FPGA数字混频精度高、无温漂、配置灵活,是入门FPGA DSP必学案例。

本文基于经典工程:5MHz系统时钟、625kHz输入信号 + 625kHz本振信号混频,完整讲解:

  • 数字混频数学原理

  • Quartus NCO / Vivado DDS 两大IP核区别与配置

  • FPGA有符号/无符号数、补码工程致命坑点

  • 两种混频乘法实现方式(纯Verilog / 乘法器IP)

  • 简易均值法直流滤除原理与代码解析

  • Testbench文件读写仿真方案

一、数字混频核心原理

1.1 混频本质:时域相乘、频域搬移

模拟混频依靠三极管/二极管非线性实现频率变换;数字混频最简单、最标准的方式就是:两个正弦信号直接相乘

根据三角积化和差公式:

$$\sin\omega_1 t \cdot \sin\omega_2 t = \frac{1}{2}[\cos(\omega_1-\omega_2)t-\cos(\omega_1+\omega_2)t]$$

相乘后会同时产生:

  • 差频分量(低频)

  • 和频分量(高频)

1.2 本文工程参数设计

  • 系统时钟:5MHz

  • 输入信号频率:625kHz

  • NCO/DDS本振频率:625kHz

混频结果:

  • 差频:625k − 625k =0Hz(直流分量)

  • 和频:625k + 625k =1.25MHz(目标有效信号)

工程最终目的:滤除直流,保留1.25MHz高频和频信号

二、NCO与DDS本质区别(工程必懂)

很多初学者困惑:Quartus叫NCO,Vivado叫DDS,到底有什么区别?

2.1 概念层级区别

DDS(直接数字频率合成器):是一套完整技术体系,包含相位累加器、LUT波形表、DAC、后置滤波,输出模拟波形

NCO(数控振荡器):是DDS的纯数字核心部分,只负责:相位累加 + 波形映射,只输出数字波形,无DAC。

简单总结:NCO = 纯数字本振;DDS = NCO + DAC + 模拟输出

2.2 FPGA厂商IP命名差异(重点)

  • Altera/Quartus:NCO IP

    • 轻量、简洁,专门用于数字本振、混频

    • 参数少、上手快

  • Xilinx/Vivado:DDS Compiler IP

    • 功能更强、可配置项极多

    • 支持SFDR、频率分辨率、相位可调、正交sin/cos输出、AXI流式配置

工程等价结论:做数字混频时,Quartus NCO ≈ Vivado DDS

2.3 DDS/NCO通用频率公式

$$f_{out} = \frac{FTW \times f_{clk}}{2^N}$$

  • FTW:相位增量字(phi_inc)

  • f_clk:系统时钟

  • N:相位累加器位宽

本文16位相位累加、FTW=8192、5MHz时钟,精准输出625kHz。

三、整体工程模块架构

整个数字混频工程分为三级流水线:

  1. NCO/DDS生成本振正弦波(625kHz)

  2. 有符号数乘法混频(产生和频+差频)

  3. 均值滤波去除直流分量(提纯1.25MHz信号)

3.1 顶层端口定义

module Mixer ( input clk, //5MHz系统时钟 input rst_n, //低电平有效复位 input [9:0] din, //10bit输入信号 output [9:0] s_oc, //NCO本振输出625kHz output out_valid, //本振有效标志 output [19:0] dout //混频最终输出 );

四、NCO本振信号生成(Quartus)

通过NCO IP核生成625kHz标准正弦本振,核心参数为相位增量 16'd8192。

wire [9:0] oc_sin; oc oc ( .phi_inc_i (16'd8192), .clk (clk), .reset_n (rst_n), .clken (1'b1), .fsin_o (oc_sin), .out_valid (out_valid) ); assign s_oc = oc_sin;

Tips:生成IP时必须勾选Generate Simulation Model,否则ModelSim仿真报错。

五、FPGA最关键坑点:有符号数与无符号数运算

这是90%初学者混频出错的根本原因。

5.1 核心规则

  • NCO/DDS/ADC/DAC输出一律是补码有符号数

  • Verilog默认变量为无符号数

  • 有符号数 × 无符号数 =错误无符号乘法结果

signed关键字不改变二进制值,只改变运算解析方式

例如二进制11

  • unsigned:当作 3

  • signed:当作 -1

5.2 两种正确混频乘法写法

方式1:纯代码强制有符号转换(无需IP)

wire signed [9:0] din_s = din; wire signed [9:0] oc_sin_s = oc_sin; reg signed [19:0] mult; always @(posedge clk or negedge rst_n) if(!rst_n) mult <= 20'd0; else mult <= din_s * oc_sin_s;

方式2:调用有符号乘法器IP(工程常用)

wire signed [19:0] mult; mult1 mult1_inst ( .clock (clk), .dataa (din), .datab (oc_sin), .result (mult) );

六、直流滤除原理与代码解析(工程小技巧)

本设计5MHz时钟采样625kHz信号,一个正弦周期恰好8个采样点

周期内平均值 = 信号直流分量,用“均值相减”即可去直流。

6.1 移位缓存8点数据

reg signed [19:0] m1,m2,m3,m4,m5,m6,m7;

always @ (posedge clk or negedge rst_n) if (!rst_n) begin m1 <= 20'd0;

m2 <= 20'd0; m3 <= 20'd0; m4 <= 20'd0; m5 <= 20'd0; m6 <= 20'd0; m7 <= 20'd0; end

else begin m1 <= mult; m2 <= m1; m3 <= m2; m4 <= m3; m5 <= m4; m6 <= m5; m7 <= m6;

end

6.2 累加求均值、去除直流

// 8点累加 wire signed [22:0] madd = mult+m1+m2+m3+m4+m5+m6+m7; // 右移3位 = 除以8 wire signed [19:0] mean = madd[22:3]; // 原始混频结果 - 直流均值 = 无直流交流信号 wire signed [19:0] mt = mult - mean; assign dout = mt;

⚠️该方法仅适用于采样倍数固定场景,通用性不强,但非常适合新手理解去直流思想。

七、Vivado DDS Compiler IP配置要点

DDS比NCO功能更强,适合复杂通信系统:

  • System Parameters模式:直接配置时钟、频率、SFDR、频率分辨率,适合新手

  • Hardware Parameters模式:手动配置位宽、手动计算频率字,适合底层优化

  • 固定频率选择Fixed模式,资源最小

  • 支持输出Sin+Cos正交双路信号,用于解调系统

  • 支持相位动态偏移,可实现相位调制

DDS输出位宽通常为8的整数倍,有效位在低位,高位为符号填充,仿真时建议使用虚拟总线观察有效位。

八、Testbench文件读写仿真方案

本工程配套仿真支持txt激励读取、结果保存,是FPGA DSP仿真通用方法。

8.1 读取txt激励

integer i; reg [9:0] stimulus[1:data_num]; initial begin $readmemb("SinIn.txt", stimulus); i = 0; repeat(data_num) begin i = i + 1; din = stimulus[i]; #clk_period; end end

$readmemb:读取二进制txt;$readmemh:读取十六进制txt。

8.2 仿真数据写入txt

integer file_out; initial begin file_out = $fopen("mixer_out.txt"); if(!file_out) begin $display("file open error"); $finish; end end wire signed [19:0] dout_s = dout; wire rst_write = clk & rst_n; always @(posedge rst_write) begin $fdisplay(file_out,"%d",dout_s); end

九、工程核心总结(面试/复盘必背)

  1. 数字混频 = 时域相乘、频域产生和频/差频

  2. NCO是Quartus叫法,DDS是Vivado叫法,工程功能等价

  3. 混频出错90%是因为有符号数未统一

  4. FPGA除法尽量用截位/移位,不直接使用除号

  5. 周期均值法可简单去除直流,适合定点采样倍数场景

  6. IP仿真必须开启仿真模型,否则仿真失败

十、拓展学习方向

  • 替换均值去直流为 FIR/IIR 低通滤波器,实现通用频谱提纯

  • 基于DDS实现 FSK/ASK/PSK 数字调制

  • 搭建完整 DDC/DUC 软件无线电架构

  • 深入理解DDS杂散、SFDR、频率分辨率指标


完整Quartus工程、Testbench、仿真文件可参考原文开源工程,适合零基础复刻学习。

http://www.jsqmd.com/news/1009793/

相关文章:

  • 思源宋体CN:7种粗细免费商用字体终极指南
  • 滚珠丝杆品牌哪家靠谱?启尖丝杠性价比高 - mypinpai
  • 武汉本地沙发翻新服务商评测:明鑫家具实力解析 - 优质品牌商家
  • 从开源openGauss到企业级GaussDB:一个数据库内核的‘商业化’演进之路
  • 机器学习决策框架:业务模式、数据质量与错误代价三重校验
  • HBM封装国内哪家强?JECT、通富微、长电、华天的技术路线与客户争夺战
  • 多维聚合中的数据操纵:维度裁剪、条件度量与流式再加工
  • 机器学习生产化实战:模型服务化与特征一致性架构
  • 列表与元组区别、常用方法及使用场景(生产选型指南)
  • YashanDB v22.1深度体验:除了‘国产替代’,它的HTAP和云原生特性到底香不香?
  • Notebook到生产环境的ML模型部署实战:7个致命细节与防御体系
  • 基于YOLOv5的智能象棋助手:Vin象棋完整使用指南
  • 抖音直播内容永久保存的终极解决方案:从单场录制到自动化采集系统
  • 【2027最新】基于SpringBoot+Vue的web机动车号牌管理系统管理系统源码+MyBatis+MySQL
  • 紧束缚链模型中的缺陷局域化与弛豫动力学研究
  • 告别Unity,用C#和OpenTK从零撸一个3D旋转立方体(.NET 8 + VS2022保姆级教程)
  • WASI 0.3 发布:异步成 WebAssembly 组件原生特性,多工具链即将支持
  • Cursor Free VIP:如何快速实现AI编程助手永久免费激活的完整指南
  • 从CATIA V6到网页浏览:3DXML格式如何成为设计评审的‘隐形桥梁’?
  • AI时代真正的硬功夫:高级用户五维胜任力与人机协作方法论
  • Matlab 2022a实战:手把手教你复现ZF、ML、MRC、MMSE四种信号检测算法(附完整代码)
  • 【无人机覆盖】基于分解和扫描线策略对多边形区域进行凹度感知覆盖路径规划附matlab代码
  • 别再手动改代码了!用Docker Compose一键部署kkfileview 4.1.0,附Nginx反向代理配置
  • 保姆级教程:用Intouch SMC搞定S7-200SMART的Modbus TCP/IP通讯(附避坑点)
  • MacBook Air M1 搞定ESP32烧录难题:CH9102X驱动安装保姆级教程(附避坑指南)
  • Vue3实战:用Class与Style绑定5分钟搞定一个动态导航栏(附完整代码)
  • 别再只用傅里叶了!用Python实战对比小波/小波包/软硬阈值去噪(附完整代码)
  • 机器学习项目五道硬门槛:问题可解性、数据可信度、目标对齐、基线确认与部署预演
  • 机器学习三大数学支柱:线性代数、微积分与概率论的工程化解读
  • APDTFlow、NSGM与MLFlow三层MLOps框架分工与协同实践