控制正弦波的频率(频率控制字的使用)
1 DDS原理
1.1 书上的解释
DDS(Direct Digital Synthesizer)技术是一种全新的频率合成方法,是从相位概念出发直接合成所需波形的一种频率合成技术,通过控制相位的变化速度,直接产生各种不同频率、不同波形信号的一种频率合成方法。
系统的核心是相位累加器,其内容会在每个时钟周期(system clock)更新。相位累加器每次更新时,存储在Δ相位寄存器中的数字字M就会累加至相位寄存器中的数字。假设Δ相位寄存器中的数字为00…01(即M=1),相位累加器中的初始内容为00…00。相位累加器每个时钟周期都会按00…01(M=1)更新。如果累加器为32位宽,则在相位累加器返回至00…00前需要2^32(超过40亿)个时钟周期,周期会不断重复。
相位累加器的截断输出用作正弦(或余弦)查找表的地址。查找表中的每个地址均对应正弦
波的从0°到360°的一个相位点。查找表包括一个完整正弦波周期的相应数字幅度信息。
(实际上,只需要90°的数据,因为两个MSB中包含了正交数据)。因此,查找表可将相位
累加器的相位信息映射至数字幅度字,进而驱动DAC。图3用图形化的“相位轮”显示了这
一情况。
考虑n = 32,M = 1的情况。相位累加器会逐步执行2^ 32 (2^n/M)个可能的输出中的每一个,直至溢出并重新开始。相应的输出正弦波频率等于输入时钟频率 2 ^ 32分频。若M=2,相位累加器寄存器就会以两倍的速度“滚动”计算,输出频率也会增加一倍。以上内容可总结如下:
1.2 自己的理解
DDS系统主要由相位累加器、波形存储器、数模(D/A)转换器和低通滤波器等四个大的结构组成,其结构框图如下图所示。
参考时钟:
图中,参考频率f_clk为固定值,一般我们选择系统时钟(system clock),这里设置的是100MHz。
频率控制字:
用来调整输出信号的频率。如何根据参考频率得到输出频率,DDS IP的官方文档给出了相应公式。
相位控制字:
相位累加器:
由N位加法器与N位累加寄存器构成,它根据频率控制字k,完成相位值的累加,并将此累加值输入到波形存储器中。
波形存储器:
将相位累积器的值作为当地址,查找与相位值对应的信号数据,输出到D/A转换器。
D/A转换器:
将波形存储器输出的数字量转换为与之对应的模拟量。
低通滤波器:
由于D/A转换器存在量化误差,输出波形中存在混叠,需要在输出端使用低通滤波器进行滤波,提高信号的输出性能。
2 DDS IP例化
2.1 parameter selection 选择system parameters
2.1.1 参数设置
summary:
2.1.2 源码
程序结构
2.1.2.1 顶层文件
`timescale 1ns / 1ps
module top(
input sys_clk ,//系统时钟
input rst_n ,//系统复位
input [1:0] key_PINC // 按键控制频率选择
);
//频率设置模块
wire [23:0] Fword ; //频率字
Fword_set Fword_set_inst(
//input
.clk (sys_clk ),
.rst_n (rst_n ),
.key_PINC (key_PINC ),
//output
.Fword (Fword )
);
//input
wire [0:0] fre_ctrl_word_en ;
//output
wire [0:0] m_axis_data_tvalid ;
wire [47:0] m_axis_data_tdata ;
wire [0:0] m_axis_phase_tvalid ;
wire [23:0] m_axis_phase_tdata ;
assign fre_ctrl_word_en=1'b1;
//DDS
dds_sin dds_sin_inst (
.aclk (sys_clk ), // input wire aclk
.s_axis_config_tvalid (fre_ctrl_word_en ), // input wire s_axis_config_tvalid
.s_axis_config_tdata (Fword ), // input wire [23: 0] s_axis_config_tdata
.m_axis_data_tvalid (m_axis_data_tvalid ), // output wire m_axis_data_tvalid
.m_axis_data_tdata (m_axis_data_tdata ), // output wire [47 : 0] m_axis_data_tdata
.m_axis_phase_tvalid (m_axis_phase_tvalid ), // output wire m_axis_phase_tvalid
.m_axis_phase_tdata (m_axis_phase_tdata ) // output wire [23 : 0] m_axis_phase_tdata
);
endmodule
2.1.2.2 频率控制模块
`timescale 1ns / 1ps
//
// 通过按键来选择对应的频率控制字,进而选择对应的信号频率
//
module Fword_set(
input clk ,
input rst_n ,
input [1:0] key_PINC ,
output reg [23:0] Fword
);
//always@(posedge clk or negedge rst_n)
//begin
// if(!rst_n)
// key_sel <= 4'd0;
// else
// key_sel <= key_sel;
//end
// The output frequency(f_out ) , of the DDS waveform is a function of the system clock frequency(f_clk ) .
// the phase width, that is, number of bits (B ) in the phase accumulator
// and the phase increment value (deta_theta) .
// The output frequency in Hertz is defined by:f_out=f_clk*deta_theta/(2^B)
// fre_ctrl_word是如何确定的?
// 根据IP核的summery, phase width=20bits Frequency per channel=100MHz
// 输出频率的计算公式f_out=f_clk*deta_theta/(2^B)=100M* 104857/(2^20 )= 10M
always@(*)
begin
case(key_PINC)
0: Fword <= 'h28f5; //1Mhz 10485 每次相位增加的值 deta_theta
1: Fword <= 'h51eb; //2Mhz 20971
2: Fword <= 'ha3d7; //4Mhz 41943
3: Fword <= 'h19999; //10Mhz 104857
endcase
end
endmodule
2.1.2.3 testbench文件
`timescale 1ns / 1ps
module sim_top;
reg sys_clk;
reg rst_n;
reg [1:0] key_PINC;
//例化源文件
top top_inst(
.sys_clk (sys_clk ),
.rst_n (rst_n ),
.key_PINC (key_PINC )
);
initial
begin
//初始化输入
sys_clk=0;
rst_n=0;
key_PINC=2'd0;
#100
rst_n=1;
key_PINC=0; //1Mhz 10485 每次相位增加的值 deta_theta
#4000
key_PINC=1; //2Mhz 20971
#4000
key_PINC=2; //4Mhz 41943
#4000
key_PINC=3; //10Mhz 104857
end
// create clock;
always #5 sys_clk=~sys_clk;//每次间隔5ns,取一次反,也就是周期为10ns,所以频率为100MHz
endmodule
2.1.3 仿真结果
可以看出,不同频率的波形的相位是连续的
2.2 parameter selection 选择hardware parameters
parameter selection 选择hardware parameters后,相位位宽phase width和输出位宽output width是可控的。
2.2.1 参数设置
2.2.2 源代码
2.2.2.1 结构图
2.2.2.2 顶层文件
`timescale 1ns / 1ps
// 频率控制字fre_ctrl_word是如何确定的?
// 根据IP核的summery, phase width=32bits Frequency per channel=125MHz
// 输出频率的计算公式:f_out(3M)=f_clk*deta_theta/(2^B)
// 输出频率字的计算公式:deta_theta=f_out*(2^B)/f_clk
module top(
input sys_clk ,//系统时钟
input rst_n //系统复位
);
//output
wire [31:0] m_axis_data_tdata ;
//DDS
dds_sin dds_sin_inst (
.aclk(sys_clk), // input wire aclk
.s_axis_config_tvalid(1'b1 ), // input wire s_axis_config_tvalid
.s_axis_config_tdata( 32'h06594AF5), // input wire [31 : 0] s_axis_config_tdata 3M
.m_axis_data_tvalid(), // output wire m_axis_data_tvalid
.m_axis_data_tdata(m_axis_data_tdata), // output wire [31 : 0] m_axis_data_tdata
.m_axis_phase_tvalid(), // output wire m_axis_phase_tvalid
.m_axis_phase_tdata() // output wire [31 : 0] m_axis_phase_tdata
);
endmodule
2.2.2.3 仿真文件
`timescale 1ns / 1ps
module sim_top;
reg sys_clk;
reg rst_n;
//例化源文件
top top_inst(
.sys_clk (sys_clk ),
.rst_n (rst_n )
);
initial
begin
//初始化输入
sys_clk=0;
rst_n=0;
#20
rst_n=1;
end
// create clock;
always #5 sys_clk=~sys_clk;//每次间隔5ns,取一次反,也就是周期为10ns,所以频率为100MHz
endmodule
2.2.3 结果
1)信号频率为3M
2)高16位为实部,低16位为虚部