Xilinx DDS IP核生成任意频率的正弦波、余弦波
本文详细介绍了在Vivado开发工具中使用DDS IP核生成任意频率正弦、余弦波形的方法,并进行仿真查看生成的波形。
·
关于DDS IP核的使用说明和参数配置可参考这篇文章:Xilinx DDS IP核 配置及使用方法
1、创建好Vivado工程后,打开IP Catalog,搜索DDS,选择DDS Compiler IP核。双击打开进入配置界面:
2、进入Configuration配置界面
- Configuration Options配置为phase generator and sin cos LUT
- 系统时钟配置为100MHz
- 操作模式配置为标准模式
- 参数配置为使用系统参数
- SFDR配置为48(6*N,N为正余弦波形数据输出位宽,如果只输出正弦波或余弦波,则输出数据位宽为8;如果同时输出正弦波和余弦波,则输出数据位宽为16,高8位为正弦波形数据,低8位为余弦波形数据)
- 频率分辨率计算方法:Frequency resolution = f_clk / (2^N) ,其中N为相位位宽,相位位宽越大,频率分辨率越高,分辨率越精确,可调输出频率越精确,相位位宽越大,相位累加器和相位-幅度转换表(ROM)的资源消耗也会增加。尤其是ROM的大小会随着相位位宽(用于寻址的位数)的增加而指数增长。通常,DDS的相位位宽设置为24位到48位之间,这里相位位宽使用32进行计算。设置频率分辨率Frequency resolution = 100M / (2^32) = 0.023283064365386962890625。
- 噪声整形配置为自动

3、Implementation 界面配置 - 要实现输出任意频率的正余弦波,Phase increment programmability(相位增量可编程性)配置为可编程
- Phase offset programmability(相位偏移可配置性)配置为None,无相位偏移
- 输出选择正余弦同时输出
- 其余保持默认即可

4、Detials Implementation 界面配置
在AXI Channel options下可以选择 output tready(输出正余弦数据有效信号)输出引脚,其余设置保持默认即可。
5、Output Frequencies输出频率设置
根据之前选择为单通道输出,为了输出任意频率之前选择相位增量可编程模式,输出频率由相位增量决定,这里不设置输出频率。
6、查看配置总结,确认无误后点击OK生成IP核

7、在工程目录下找到例化模板进行例化
8、添加仿真文件查看IP核输出的正余弦波形
相位增量计算方法:相位增量 = 输出波形频率 * 2^N / 系统时钟频率,N为相位位宽
dds_wave.v
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 2025/09/30 14:36:09
// Design Name:
// Module Name: dds_wave
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module dds_wave(
input sysclk ,
input sysrstn ,
input [31:0] phase_crement , // 相位增量
input phase_crement_valid // 相位增量有效
);
reg s_axis_config_tvalid ;
wire s_axis_config_tready ;
reg [31:0] s_axis_config_tdata ;
wire m_axis_data_tvalid ;
wire [15:0] m_axis_data_tdata ;
wire m_axis_phase_tvalid ;
wire [31:0] m_axis_phase_tdata ;
wire signed [7:0] sin ;
wire signed [7:0] cos ;
dds_sin_cos u_dds_sin_cos (
.aclk ( sysclk ), // input wire aclk
.s_axis_config_tvalid ( s_axis_config_tvalid ), // input wire s_axis_config_tvalid
.s_axis_config_tready ( s_axis_config_tready ), // output wire s_axis_config_tready
.s_axis_config_tdata ( s_axis_config_tdata ), // input wire [31 : 0] s_axis_config_tdata
.m_axis_data_tvalid ( m_axis_data_tvalid ), // output wire m_axis_data_tvalid
.m_axis_data_tready ( 1'b1 ), // input wire m_axis_data_tready
.m_axis_data_tdata ( m_axis_data_tdata ), // output wire [15 : 0] m_axis_data_tdata
.m_axis_phase_tvalid ( m_axis_phase_tvalid ), // output wire m_axis_phase_tvalid
.m_axis_phase_tready ( 1'b1 ), // input wire m_axis_phase_tready
.m_axis_phase_tdata ( m_axis_phase_tdata ) // output wire [31 : 0] m_axis_phase_tdata
);
always @(posedge sysclk or posedge sysrstn ) begin
if(!sysrstn)begin
s_axis_config_tvalid <= 1'b0 ;
s_axis_config_tdata <= 32'd0 ;
end
else if(s_axis_config_tready && phase_crement_valid)begin
s_axis_config_tvalid <= phase_crement_valid ;
s_axis_config_tdata <= phase_crement ;
end
end
assign sin = m_axis_data_tvalid ? {~m_axis_data_tdata[7],m_axis_data_tdata[6:0]} : 8'd0; // DDS输出的数据是二进制补码形式,所以需要最高位取反
assign cos = m_axis_data_tvalid ? {~m_axis_data_tdata[15],m_axis_data_tdata[14:8]} : 8'd0;
endmodule
仿真测试文件dds_tb.v
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 2025/09/30 14:47:15
// 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 sysclk ;
reg sysrstn ;
reg [31:0] phase_crement ;
reg phase_crement_valid ;
dds_wave u_dds_wave(
/*input */.sysclk ( sysclk ),
/*input */.sysrstn ( sysrstn ),
/*input */.phase_crement ( phase_crement ), // 相位增量
/*input */.phase_crement_valid ( phase_crement_valid ) // 相位增量有效
);
parameter T_CLK = 10 ;
always # (T_CLK / 2) sysclk = ~sysclk ;
initial begin
sysclk = 1'b1 ;
sysrstn = 1'b1 ;
#(T_CLK * 10);
sysrstn = 1'b0 ;
#(T_CLK * 15);
sysrstn = 1'b1 ;
end
initial begin
phase_crement = 32'd0 ;
phase_crement_valid = 1'b0 ;
#(T_CLK * 30);
phase_crement = 32'h028F_5C29 ; // 1M
phase_crement_valid = 1'b1 ;
#(T_CLK * 2000);
phase_crement = 32'h0CCC_CCCD ; // 5M
#(T_CLK * 2000);
phase_crement = 32'h1999_999A ; // 1M
#(T_CLK * 2000);
phase_crement_valid = 32'd0 ;
$finish ;
end
endmodule

注意:由于DDS输出数据是二进制补码形式,所以需要在数据最高位取反,否则显示不是正常的正余弦波形。
火山引擎开发者社区是火山引擎打造的AI技术生态平台,聚焦Agent与大模型开发,提供豆包系列模型(图像/视频/视觉)、智能分析与会话工具,并配套评测集、动手实验室及行业案例库。社区通过技术沙龙、挑战赛等活动促进开发者成长,新用户可领50万Tokens权益,助力构建智能应用。
更多推荐
所有评论(0)