这是数字信号处理系列的第一篇,以简单的数字混频为例,介绍在FPGA程序设计中很重要的二进制原码、补码;有符号数、无符号数的问题。本文不是像课本那样介绍这些基础概念,而是介绍很实际的设计方法。

借助于数字混频这个设计,本文还会介绍用途非常广泛的Altera公司Quartus中的NCO IP核、Xilinx公司Vivado中的DDS Compiler IP核的具体使用方法。

混频原理
混频就是把两个不同的频率信号混合,得到第三个频率。在模拟电路中经常见到的就是把接收机接收到的高频信号,经过混频变成中频信号,再进行中频放大,以提高接收机的灵敏度。

数字电路中最简单的混频便是两个信号做乘法,可以得到它们的和频信号与差频信号。数字混频在通信的调制、解调、DUC(数字上变频)、DDC(数字下变频)等系统中应用广泛。通常把其中一个信号称为本振信号(local oscillator),另一个信号称为混频器的输入信号。

程序设计
本文的程序设计参考自杜勇老师的书《数字滤波器的MATLAB与FPGA实现-Altera/Verilog版》,对其中部分设计细节做了修改。杜勇老师的这个系列共有三本书,很推荐大家购买学习。不过可能由于篇幅有限,杜勇老师在书中对设计的一些细节和思想没有做详细介绍,博主在本文中和大家讨论讨论。

程序设计系统时钟5MHz,625kHz的输入信号与625kHz的本振信号做混频,根据混频原理会得到1.25MHz的和频信号与0Hz(直流),将直流滤除掉得到1.25MHz的有效信号。
设计的顶层模块接口如下所示:

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

程序中首先生成本振信号。Quartus和Vivado中都提供了类似功能的IP核:Vivado中叫DDS(Direct Digital Synthesizers)Compiler;Quartus中叫NCO(Numerically controlled oscillators)。下面以实例化NCO为例,具体的设计方法在下文讲解。

wire [9:0] oc_sin;oc oc
(.phi_inc_i  (16'd8192),   //相位增量,对应625kHz.clk        (clk),        .reset_n    (rst_n),      .clken      (1'b1),       //时钟允许信号.fsin_o     (oc_sin),     //本振正弦信号.out_valid  (out_valid)   //输出有效标志
);

接下来用乘法进行混频。我们都知道计算机中有带符号数signed和无符号数unsigned,还知道计算机经常以二进制补码的形式的表示带符号数。

在FPGA设计中,不管是Altera还是Xilinx,它们的IP核几乎都是采用二进制补码带符号数,也有很多的ADC、DAC芯片的数据接口也采用的是二进制补码。因此,在设计中,我们要清楚什么时候用什么数值表示法。

比如NCO的输出为带符号数二进制补码,假设混频的输入信号也是带符号数二进制补码,则在整个混频程序设计中都要保持这个数值表示方法,否则就会出错。

在下面的方法1中,再定义一个带符号的寄存器将输入信号转换为带符号数是很有必要的:“wire signed [9:0] din_s = din;”。如果不这样做,直接使用乘法运算符“*”,会被综合为无符号数乘法,得到的就是错误的结果。

当然也可以用方法2,乘法器IP核可以选择计算方式是“signed”还是“unsigned”,将乘法器设置为signed也可以完成正确的计算。

//----------------------------------------------------
//     乘法实现混频,方法1,转换为带符号数后再相乘
//----------------------------------------------------
//reg signed [19:0] mult;
//wire signed [9:0] din_s = din;
//wire signed [9:0] oc_sin_s = oc_sin;
//
//always @(posedge clk or negedge rst_n)
//  if (!rst_n) mult <= 20'd0;
//  else mult <= din_s * oc_sin_s;//----------------------------------------------------
//     乘法实现混频,方法2,调用乘法器IP核,设置为signed
//----------------------------------------------------wire signed [19:0] mult; mult1   mult1_inst (.clock ( clk ),.dataa ( din ),.datab ( oc_sin ),.result ( mult ));

接下来滤除混频后的直流信号。由于乘法的运算结果为带符号数,接下来的计算使用到的寄存器都应申明为signed。

需要强调的是,signed和unsigned的申明只是告诉设计的运算如何看待这个寄存器中的数,并不能改变寄存器的值。比如“11”这个值,如果申明为signed,运算将其视作-1,如果申明为unsigned,运算将其视作3。因为有符号数和无符号数的运算法则是不一样的,所以错误的申明会导致结果计算错误。

reg signed [19:0] m1,m2,m3,m4,m5,m6,m7;// 5MHz/625kHz=8; 缓存连续8个点的值
always @ (posedge clk or negedge rst_n)if (!rst_n) beginm1 <= 20'd0; m2 <= 20'd0; m3 <= 20'd0;m4 <= 20'd0; m5 <= 20'd0; m6 <= 20'd0; m7 <= 20'd0;endelse beginm1 <= mult; m2 <= m1; m3 <= m2; m4 <= m3; m5 <= m4; m6 <= m5; m7 <= m6;endwire signed [22:0] madd = mult+m1+m2+m3+m4+m5+m6+m7;     //一个周期
wire signed [19:0] mean = madd[22:3];   //舍掉低3bit,相当于除8,得到
wire signed [19:0] mt = mult - mean;    //滤除直流分量
assign dout = mt;
assign s_oc = oc_sin;   endmodule

上面滤除直流分量的方法并不通用,由于5Mhz的系统时钟是625kHz信号的8倍,所以连续8个点的平均值便是直流分量。不过程序设计思路还是可以学习,比如依次移位缓存数据、截高位做除法这些小技巧。
NCO IP核的使用
在Quartus中打开该IP核,配置界面如下。后面的Quartus版本中将IP核集成到了qsys中,配置界面略有不同,但设置的参数之类的基本一样。

设定好相位累加器精度、角度分辨率、幅度精度、系统时钟和输出信号频率,便可以得到一个相位增量值(phase increment value),在实例化NCO模块时传入的便是这个值。实际的输出频率和设定的频率会存在一定误差,下方便展示了输出信号的频域和时域图形。总体来说设置比较简单。

如果需要仿真,在生成IP核前一定要在“Set up simulation”中选中“Generate Simulation Model”和“Generate netlist”,如下图所示。否则在导入ModelSim时会失败,无法进行仿真。

DDS Compiler IP核的使用
基本配置
在Vivado中打开DDS Compiler IP核,配置界面如下:

这个IP核的配置选项更丰富,提供的功能也更强大。我这里只介绍下本设计用到的功能,其余具体信息可以参考Xilinx官方文档pg141。

同样设定系统时钟,Parameter Selection选择“System Parameters”,这种设计方式可以直接设置无杂散动态范围、频率分辨率、输出频率等系统级的参数,和Quartus的NCO IP核很像。另外一种“Hardware Parameters”设计方式需要自己设定输出数据和相移的位宽,输出频率、相位偏移等值需要自己计算对应的二进制数值。这两种设计方式向不同需求的设计者提供。

pg141中给出了总线位宽与系统参数之间的转换关系公式。


相位增量和相位偏移都可以设置为可编程的“Programmable”和“Streaming”方式,本设计只需要产生625kHz固定频率的本振信号,设置为“Fixed”即可(所需资源少)。在“Summary”中可以看到整个DDS系统的详细信息。

位宽问题
需要提醒的是系统最终的实际信号位宽和总线接口位宽并不一致。IP核的位宽只会是8的倍数,多余的位数会移符号为填充,如下图所示。

更直观的感受,看一个DDS Compiler IP核的仿真:

可以看到相移虽然有16bit的位宽,但是有效的只有低10bit,高位都是符号为。为了更好的观察相位值,新建一个“virtual bus“,将低10bit加到bus中,如下图所示:

可以清楚的看到相位和幅度之间的关系。

产生sin与cos信号
很多系统中需要sin和cos信号(如解调系统中的本振信号),在DDS中设置为“Sine and Cosine”输出时,sin和cos信号会共用数据总线,sin使用高字节,cos使用低字节,格式如下:

产生带有相位偏移的信号
如果需要生成带有可调初始相位(也叫相位偏移Phase Offset)的信号,在DDS中将“Phase Offset Programmability”设置为“Streaming”,IP核端口会增加一个PHASE输入通道,该通道数据总线的有效位宽与设置的频率分辨率(Frequency Resolution)有关,可以在Summary界面中看到位宽(Phase Width)。该数据总线与360°相位之间线性对应。比如Phase Width为16Bits,则0对应0°,FFFF对应360°,7FFF对应180°,以此类推。

NCO和DDS是经常用到的IP核,在后面的“FPGA数字信号处理“系列介绍的其它系统中,也会经常出现,因此需要熟悉掌握这两个IP核的使用。

第一章 FPGA数字信号处理_数字混频(NCO与DDS)相关推荐

  1. rbw数字信号处理_数字信号处理与模拟IC设计

    马上注册,结交更多好友,享用更多功能,让你轻松玩转社区. 您需要 登录 才可以下载或查看,没有帐号?注册 x 本帖最后由 血荐轩辕HIT 于 2019-12-15 23:38 编辑 信号与系统.数字信 ...

  2. 数字信号处理_第1个编程实例

    最近准备开一个关于<数字信号处理>的课程,课程的视频在b站分享(数字信号处理_引言_哔哩哔哩_bilibili),大概会保持每周一更的频率,希望对<数字信号处理>感兴趣的同学多 ...

  3. ldar是什么意思 计算机组成,第一章TEC-9计算机组成和数字逻辑实验系统介绍….PDF...

    第一章TEC-9计算机组成和数字逻辑实验系统介绍-.PDF 目 录 第一章 TEC-9 计算机组成和数字逻辑实验系统介绍----------------------.2 一.TEC-9 实验系统的特点 ...

  4. 数字信号处理_ 第2个编程实例

    配套的讲解视频详见数字信号处理_第2个Matlab编程实例_哔哩哔哩_bilibili 方波信号合成与分解的实例代码如下: %% //数字信号第2个Matlab程序:方波信号的分解 %% //作者:g ...

  5. 01_01 python机器学习_第一章学习内容整理_加载样本数据绘制散点图

    第一章学习内容整理_加载样本数据&绘制散点图 01 常用包说明 python可以解决很多问题,相应解决方案使用的包也很多,不太好记忆. 为了便于记忆,用大白话简单描述一下各个包的功能. # 科 ...

  6. 归一化数字角频率_数字信号处理中的各种频率

    在学习数字信号处理时,很多种频率很容易搞混淆,有模拟/数字/频率/角频率等等,也不是特别清楚不同频率之间的关系,希望这篇文件可以为各种频率来个了结. 4种频率及其数量关系 实际物理频率表示物理信号的真 ...

  7. MATLAB_数字信号处理_模拟滤波器_设计巴特沃斯滤波器

    简介 巴特沃斯滤波器-百度百科 巴特沃斯滤波器-维基百科 简介:巴特沃斯滤波器是一种模拟滤波器,它在频率响应方面具有特殊的属性.它被设计为具有均匀的幅度响应,即在通带内,它对所有频率的增益是相等的,而 ...

  8. rbw数字信号处理_【有奖】示波器,实时频谱仪?MXR让您鱼与熊掌兼得!

    本文4400字左右,有视频演示,主要内容包括: 示波器的传统FFT分析的一些基本介绍 MXR的RTSA功能的介绍和实测演示视频 (全文阅读需要15分钟左右) 前言 MXR云马拉松拉力赛终于进入到收官站 ...

  9. 数字身份_数字身份作为投资

    数字身份 Trustworthy digital identification remains one of the main challenges of the internet because n ...

  10. 计算机找单词嫌疑犯游戏纸境,纸境(Tengami)第一章怎么过_纸境(Tengami)第一章图文攻略_快吧单机游戏...

    来自IOS平台的<纸境(Tengami)>,如今已经登上PC平台,而且有很多的玩家都已经通关了,但是也有一部分玩家不会过,纸境(Tengami)第一章怎么过?下面是快吧为各位整理的第一章图 ...

最新文章

  1. 帮AI摆脱“智障”之名,NLP这条路还有多远?
  2. python做动态折线图_Python数据可视化 pyecharts实现各种统计图表过程详解
  3. 鸡肋工具-Oracle建表工具
  4. java 捕获特定异常_java – 使用特定消息捕获异常
  5. java宏定义_现代化的 Java (二十六)—— Akka Stream Graph
  6. c#小游戏_C#小游戏—钢铁侠VS太空侵略者
  7. 深度 | 带领国产数据库走向世界,POLARDB底层逻辑是什么?
  8. 默认选中_双击dwg图纸,怎么设置默认天正打开?
  9. 利用CSS实现悬停下拉菜单
  10. python库--Numpy and pandas
  11. fm -rf 删除 恢复
  12. 171021 逆向-Xp0intCTF(re300)
  13. vw、vh、vmin、vmax 的含义
  14. 如何用acme.sh申请证书
  15. 一行代码能实现什么丧心病狂的功能?
  16. 通用人工智能:我们还有多远?
  17. STM32系列(HAL库)——F103C8T6通过MFRC522、RFID射频卡、门禁卡模块读取卡片ID
  18. Cadence IC设计环境搭建( IC617+MMSIM151+Calibre2015)
  19. 【解决方案】A session ended very soon after starting. Check that the command in profile “XXX” is correct.
  20. 新手游戏创业如何推广游戏?

热门文章

  1. Linux驱动开发基础
  2. 瑞昱网卡linux通用驱动下载,Realtek瑞昱网卡万能驱动
  3. adb工具下载及安装
  4. Perl语言程序设计_输入与输出
  5. SQL Server如何备份数据库
  6. visio 2013安装教程
  7. 3S基础知识:用MapX快速开发
  8. 服务器ghost备份后无法进入系统还原,ghost系统备份后的恢复方法
  9. 13个不容错过的Java项目
  10. lg手机历史机型_lg手机大全【详细介绍】