参考链接:
FPGA数字信号处理(一)数字混频(NCO与DDS的使用)
https://blog.csdn.net/fpgadesigner/article/details/80512067
一、混频原理
混频就是把两个不同的频率信号混合,得到第三个频率。在模拟电路中经常见到的就是把接收机接收到的高频信号,经过混频变成中频信号,再进行中频放大,以提高接收机的灵敏度。
数字电路中最简单的混频便是两个信号做乘法,可以得到它们的和频信号与差频信号。数字混频在通信的调制、解调、DUC(数字上变频)、DDC(数字下变频)等系统中应用广泛。通常把其中一个信号称为本振信号(local oscillator),另一个信号称为混频器的输入信号。
二、 程序设计
程序设计系统时钟50MHz,1MHz的输入信号与1MHz的本振信号做混频,根据混频原理会得到2MHz的和频信号与0Hz(直流)
设计的顶层模块接口如下所示:
module top(
input clk, //50MHz系统时钟
input rst_n, //低电平有效复位信号
output [19:0] dout //混频输出信号
);
理论上用来混频的输入信号应该来自本模块之外,考虑未安装matlab以及简化程序等原因,本工程输入信号和本振信号通过例化两个DDS IP核来产生。
dds_compiler_0 dds_compiler_0_inst1 (
.aclk(clk), // input wire aclk
.m_axis_data_tvalid(), // output wire m_axis_data_tvalid
.m_axis_data_tdata(din), // output wire [15 : 0] m_axis_data_tdata
.m_axis_phase_tvalid(), // output wire m_axis_phase_tvalid
.m_axis_phase_tdata(m_axis_phase_tdata1) // output wire [39 : 0] m_axis_phase_tdata
);
dds_compiler_1 dds_compiler_0_inst2 (
.aclk(clk), // input wire aclk
.m_axis_data_tvalid(), // output wire m_axis_data_tvalid
.m_axis_data_tdata(s_oc), // output wire [15 : 0] m_axis_data_tdata
.m_axis_phase_tvalid(), // output wire m_axis_phase_tvalid
.m_axis_phase_tdata(m_axis_phase_tdata2) // output wire [39 : 0] m_axis_phase_tdata
);
产生输入信号和本振信号后,接下来用乘法进行混频。我们都知道计算机中有带符号数signed和无符号数unsigned,还知道计算机经常以二进制补码的形式的表示带符号数。
在FPGA设计中,不管是Altera还是Xilinx,它们的IP核几乎都是采用二进制补码带符号数,也有很多的ADC、DAC芯片的数据接口也采用的是二进制补码。因此,在设计中,我们要清楚什么时候用什么数值表示法。
比如DDS的输出为带符号数二进制补码,假设混频的输入信号也是带符号数二进制补码,则在整个混频程序设计中都要保持这个数值表示方法,否则就会出错。
在下面的方法1中,一定要定义输入信号和本振信号为有符号型signed,如果不这样做,直接使用乘法运算符“*”,会被综合为无符号数乘法,得到的就是错误的结果。
/*采用直接相乘的方法*/
reg signed [19:0] dout;
wire signed [9:0] din;
wire signed [9:0] s_oc;
always @(posedge clk or negedge rst_n)
if (!rst_n)
dout <= 20'd0;
else
dout <= din * s_oc;
当然也可以用方法2,乘法器IP核可以选择计算方式是“signed”还是“unsigned”,将乘法器设置为signed也可以完成正确的计算。
/*采用直接ip核的方法*/
wire signed [19:0] dout;
wire [9:0] din;
wire [9:0] s_oc;
mult_gen_0 your_instance_name (
.CLK(clk), // input wire CLK
.A(din), // input wire [9 : 0] A
.B(s_oc), // input wire [9 : 0] B
.P(dout) // output wire [19 : 0] P
);
三、测试
工程下载见https://download.csdn.net/download/keilzc/12133386,
其中dds配置可参考https://blog.csdn.net/keilzc/article/details/104146629
1、最初采用同一个DDS产生的1MHz正弦信号进行混频
2、1MHz和3MHz混频得到2MHz和4MHz
3、5MHz和4MHz混频得到9MHz和1MHz
4、直接相乘时,其中本振信号未定义为unsigned
注意此时本振信号s_oc虽然为定义为signed,但查看波形时依然可以选择signed,由此也证明signed和unsigned的申明只是告诉设计的运算如何看待这个寄存器中的数,并不能改变寄存器的值。
5、用乘法器相乘时,参数B设置为unsigned
查看波形时dout设置为signed
查看波形时dout设置为unsigned
由此可见:一定要正确设置数据类型,因为有符号数和无符号数的运算法则是不一样的,所以错误的申明会导致结果计算错误。