简介
DDS(Direct Digital Synthesizer)即数字合成器,是一种新型的频率合成技术,具有低成本、低功耗、高分辨率、频率转换时间短、相位连续性好等优点,对数字信号处理及其硬件实现有着很重要的作用。DDS 的基本结构主要由相位累加器、相位调制器、波形数据表 ROM、D/A 转换器等四大结构组成。本章节主要介绍的是XILINX IP DDS的使用。
DDS的原理
相位累加器
相位累加器是一种模 N 计数器,具有 2N 个数字状态,这些状态会在每个系统时钟输入脉冲发生时逐渐递增。增量的大小取决于应用于累加器相加级的调谐字 M 的值。该调谐字确定了计数器增量的步长。这将决定输出波形的频率。
相位累加器的长度通常为 24 - 48 位;24 位累加器共有 224(即 16,777,216)个状态。这一数字表示 0 到 2p 弧度之间的相位值数量,或者说是可实现的相位增量。对于 24 位相位累加器,相位分辨率为 3.74 E-7 弧度。如果使用更大的相位累加器,相位增量会变得更加精细。如下图所示:
关于DDS的设置如下:
IP介绍
如上图所示调用FPGA DDS IP
翻译如下:
1、模式选择--(1)相位和波形数据 (2)相位数据 (3)波形数据
2、系统时钟设置,这里选用系统时钟100MHz,
3、设置通道数;
4、模式选择,两种模式,一般选择standard模式;
5、选择在System Parameters下进行参数设置
6、输出数据宽度和频率精度
偏移宽度计算公式如下:
数据位宽公式如下:
其中SFDR就是上图中的dB参数;
运行设置如下:
1、相位的增量(PINC)和偏移(POFF)
Fixed(固定模式):运行前确定,运行中不可更改,占用资源最少;
Programmable(编程模式): 运行时可修改,DDS频率在不同模式下进行切换;
Streaming(流模式):参数取决于输入的相位值,适用于DDS频率频繁变动的模式;
2、数据输出格式
sine通道输出;
cosine通道输出;
sine和cosine同时输出;
5、相位输出,本次设计对相位无要求,去掉。
其他的默认模式不做处理。
接口格式设置:
例如复位,数据流等控制,如有需求可以修改。
默认输出频率配置:
根据设置的信号,400Hz信号默认输入值为0x20c;
这个值怎么来的呢?
本设计使用的时钟是102.4MHz,根据phase width公式计算出phase width的宽度为27位;
再根据以下公式设置参数:
其中f_clk=102.4MHz,B=27。简单的理解就是2的27次方将102.4MHz做等分处理,计算出来的刻度是102400000/134217728=0.7629Hz。需要输出400Hz,那么设置的值为524,转换成16进制为20c。
啁啾信号是什么
啁啾信号是一种信号,其频率随时间变化,这种变化在时域上表现为脉冲性质的表征。啁啾信号分为正啁啾和负啁啾,其中正啁啾是频率随时间增加,而负啁啾则是频率随时间减少。信号如下图所示:
FPGA代码
`timescale 1ns / 1ps
//
// Company:
// Engineer:
//
// Create Date: 2024/01/10 11:11:34
// Design Name:
// Module Name: DDS_CTRL_TOP
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//
module DDS_CTRL_TOP(
input sys_clk,
input sys_rst_n,
input s_axis_dds_config_tvalid,
input[15:0] s_axis_dds_config_tdata,
//chirp
input[15:0] chirp_fre_start,
input[15:0] chirp_fre_stop,
input[15:0] chirp_fre_step,
input[15:0] chirp_fre_step_time,
input chirp_en,
output reg s_axis_config_tvalid,
output reg[31:0] s_axis_config_tdata
);
parameter us_time_num = 'd1024; //10us
reg s_axis_config_chirp_tvalid;
reg[23:0] s_axis_dds_chirp_config_tdata;
reg chirp_mode;0 递增 1 递减
reg[15:0] us_time_cnt;
reg[15:0] clk_cnt;
reg step_en;
reg us_time_cnt_en;
reg us_time_cnt_en_r1;
always @(posedge sys_clk)begin
us_time_cnt_en_r1 <= us_time_cnt_en;
end
always @(posedge sys_clk or negedge sys_rst_n)begin
if(sys_rst_n == 'd0)begin
chirp_mode <= 'd0;
end
else if(chirp_fre_start <= chirp_fre_stop)begin
chirp_mode <= 'd0;
end
else begin
chirp_mode <= 'd1;
end
end
always @(posedge sys_clk or negedge sys_rst_n)begin
if(sys_rst_n == 'd0)begin
us_time_cnt_en <= 'd0;
end
else if(chirp_en == 'd1)begin
us_time_cnt_en <= 'd1;
end
else if(chirp_mode == 'd0 && s_axis_dds_chirp_config_tdata >= chirp_fre_stop && us_time_cnt == chirp_fre_step_time - 'd1 && clk_cnt >= us_time_num - 'd2)begin
us_time_cnt_en <= 'd0;
end
else if(chirp_mode == 'd1 && s_axis_dds_chirp_config_tdata <= chirp_fre_stop && us_time_cnt == chirp_fre_step_time - 'd1 && clk_cnt >= us_time_num - 'd2)begin
us_time_cnt_en <= 'd0;
end
end
always @(posedge sys_clk or negedge sys_rst_n)begin
if(sys_rst_n == 'd0)begin
us_time_cnt <= 'd0;
clk_cnt <= 'd0;
step_en <= 'd0;
end
else if(us_time_cnt_en == 'd1 && us_time_cnt == chirp_fre_step_time - 'd1 && clk_cnt >= us_time_num - 'd1)begin
us_time_cnt <= 'd0;
step_en <= 'd1;
clk_cnt <= 'd0;
end
else if(us_time_cnt_en == 'd1 && clk_cnt >= us_time_num - 'd1)begin
us_time_cnt <= us_time_cnt + 'd1;
clk_cnt <= 'd0;
step_en <= 'd0;
end
else if(us_time_cnt_en == 'd1)begin
clk_cnt <= clk_cnt + 'd1;
step_en <= 'd0;
end
else begin
us_time_cnt <= 'd0;
clk_cnt <= 'd0;
step_en <= 'd0;
end
end
always @(posedge sys_clk or negedge sys_rst_n)begin
if(sys_rst_n == 'd0)begin
s_axis_config_chirp_tvalid <= 'd0;
s_axis_dds_chirp_config_tdata <= 'd0;
end
else if(chirp_en == 'd1)begin
s_axis_config_chirp_tvalid <= 'd1;
s_axis_dds_chirp_config_tdata <= chirp_fre_start;
end
else if(step_en == 'd1 && chirp_mode == 'd0)begin
s_axis_config_chirp_tvalid <= 'd1;
s_axis_dds_chirp_config_tdata <= s_axis_dds_chirp_config_tdata + chirp_fre_step;
end
else if(step_en == 'd1 && chirp_mode == 'd1)begin
s_axis_config_chirp_tvalid <= 'd1;
s_axis_dds_chirp_config_tdata <= s_axis_dds_chirp_config_tdata - chirp_fre_step;
end
else if(us_time_cnt_en == 'd0 && us_time_cnt_en_r1 == 'd1)beginover
s_axis_config_chirp_tvalid <= 'd1;
s_axis_dds_chirp_config_tdata <= 'd0;
end
else begin
s_axis_config_chirp_tvalid <= 'd0;
end
end
always @(posedge sys_clk or negedge sys_rst_n)begin
if(sys_rst_n == 'd0)begin
s_axis_config_tvalid <= 'd0;
s_axis_config_tdata <= 'd0;
end
else if(s_axis_dds_config_tvalid == 'd1)begin
s_axis_config_tvalid <= 'd1;
s_axis_config_tdata <= s_axis_dds_config_tdata;
end
else begin
s_axis_config_tvalid <= s_axis_config_chirp_tvalid;
s_axis_config_tdata <= s_axis_dds_chirp_config_tdata;
end
end
endmodule
本代码可以实现啁啾信号的起始频率,终止频率,频率步进,频率步进所持续的时间。
FPGA仿真代码如下:
`timescale 1ns / 1ps
//
// Company:
// Engineer:
//
// Create Date: 2024/08/23 14:44:30
// Design Name:
// Module Name: DDS_tb
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//
module DDS_tb(
);
reg sys_clk;
reg sys_rst_n;
wire s_axis_config_l_tvalid;
wire[31:0] s_axis_config_l_tdata;
wire s_axis_config_r_tvalid;
wire[31:0] s_axis_config_r_tdata;
wire[15:0] dds_data_l;
wire[15:0] dds_data_r;
reg chirp_en;
always #5 sys_clk = ~sys_clk;
initial begin
sys_clk = 'd0;
sys_rst_n = 'd0;
chirp_en = 'd0;
#30_000
sys_rst_n = 'd1;
#30_000
repeat(1)@(posedge sys_clk);
chirp_en = 'd1;
repeat(1)@(posedge sys_clk);
chirp_en = 'd0;
end
DDS_CTRL_TOP DDS_CTRL_TOP_L_inst(
.sys_clk(sys_clk),
.sys_rst_n(sys_rst_n),
dds fixed voice
.s_axis_dds_config_tvalid('d0),
.s_axis_dds_config_tdata('d0),
//chirp
.chirp_fre_start(16'h147a),
.chirp_fre_stop(16'h051e),
.chirp_fre_step(16'h0030),
.chirp_fre_step_time(16'h0004),
.chirp_en(chirp_en),
/ out
.s_axis_config_tvalid(s_axis_config_l_tvalid),
.s_axis_config_tdata(s_axis_config_l_tdata)
);
DAC_DDS DAC_DDS_L_INST(
.aclk(sys_clk),
.s_axis_config_tvalid(s_axis_config_l_tvalid),
.s_axis_config_tdata(s_axis_config_l_tdata),
.m_axis_data_tvalid(),
.m_axis_data_tdata(dds_data_l)
);
endmodule
仿真波形如下:ru
如上图所示,DDS输出波形逐渐递减的啁啾信号。
如有疑问,欢迎提问。