VIVADO IP核之DDS直接数字频率合成器使用详解
目录
四、DDS IP核使用之Phase Generator and SIN COS LUT
五、DDS IP核之Phase Generator and SIN COS LUT仿真
前言
在数字调制解调,数字上下变频,软件无线电等应用中,均需要用到不同频率的正弦信号或者复正弦信号,VIVADO中的DDS IP核便可以产生不同频率的正弦信号,同时还可以用来计算三角函数值,本文将仔细介绍该IP核的使用,同时将该IP核计算的结果导入MATLAB中分析以验证该IP核被正确使用。
提示:以下是本篇文章正文内容,欢迎各位阅读,转载请附上链接。
一、DDS基本知识
DDS的核心原理是通过数字计算直接生成波形数据,然后将这些数据转换为模拟信号。其基本组成包括:
相位累加器(Phase Accumulator):
相位累加器负责生成波形的相位信息。它是一个寄存器,每个时钟周期都会根据相位增量(Phase Increment)进行累加,累加的结果表示当前波形的相位。相位增量决定了输出信号的频率。
波形查找表(Waveform Lookup Table, LUT):
查找表存储了一周期波形的离散采样点,如正弦波的采样值。相位累加器的输出被用作查找表的地址,从而得到当前相位对应的波形幅度值。
数模转换器(Digital-to-Analog Converter, DAC):
查找表输出的数字波形幅度值经过数模转换器转换成模拟信号。DAC的分辨率决定了输出波形的精度。
低通滤波器:
DAC输出的是离散的步进信号,通过低通滤波器可以去除高频成分,得到平滑的模拟波形。
在VIVADO DDS IP核中,只有前两个,产生的是数字信号。
假设为工作时钟频率(采样频率),N为相位增量控制字位数,K为相位增量控制字,则生成正弦波信号的频率为:
频率分辨率为。
不理解这个公式的可以从周期出发理解:
二、DDS IP核使用之SIN COS LUT only
IP核命名为DDS_test,配置选项选择SIN COS LUT only,这个是用来计算三角函数值的。Nosie shaping选择无,另外一种是泰勒技术纠正,可以提高精度。相位控制字位宽和输出位宽均设置16位。
输出选择sin和cos都选择输出,极性那项如果勾选negative就会将原本的三角函数值乘上-1,相当于与正确的三角函数值差了一个负号。幅度选择选全范围,若选择另外一个就会导致计算出来的三角函数值是正确三角函数值的一半,比如sin(30°)就会变成0.25。
根据手册提供的内容,当选择sin和cos都输出时,sin在高位,cos在低位。<<<<<<表示补的符号位。
以上设置完成后,剩下参数保持默认,生成IP核即可。
三、DDS IP核之SIN COS LUT only仿真
创建一个tb文件对其仿真。代码如下:
`timescale 1ns / 1ps
//
// Company:
// Engineer:
//
// Create Date: 2024/08/08 14:59:00
// Design Name:
// Module Name: tb_DDS_test
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//
module tb_DDS_test( );
parameter PERIOD=2;
reg clk = 1;
initial
begin
forever #(PERIOD/2) clk=~clk;
end
wire m_axis_data_tvalid;
wire [31 : 0] m_axis_data_tdata;
wire [15:0] m_axis_data_tdata_cos;
wire [15:0] m_axis_data_tdata_sin;
assign m_axis_data_tdata_cos=m_axis_data_tdata[15:0];
assign m_axis_data_tdata_sin=m_axis_data_tdata[31:16];
reg s_axis_phase_tvalid=0;
reg [15 : 0] s_axis_phase_tdata=0;
initial
begin
#(PERIOD*5)
forever
begin
@(posedge clk)
begin
s_axis_phase_tvalid<=1;
s_axis_phase_tdata<=16'd61455;
end
end
end
DDS_test u_DDS_test (
.aclk(clk), // input wire aclk
.s_axis_phase_tvalid(s_axis_phase_tvalid), // input wire s_axis_phase_tvalid
.s_axis_phase_tdata(s_axis_phase_tdata), // input wire [15 : 0] s_axis_phase_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 [31 : 0] m_axis_data_tdata
);
endmodule
仿真结果如下,更改格式s_axis_phase_tdata设置为无符号十进制数,m_axis_data_tdata_sin和m_axis_data_tdata_cos设置为小数位为15位的定点数。
相位控制字是61455,位控制字位宽是16位,那么此时对应的三角函数值在matlab由以下代码验证
a=61455;
b=a/(2^16-1)
b*360
bsin=sind(b*360)
bcos=cosd(b*360)
运行可得到,可见结果与VIVADO 仿真结果一致。
从以上仿真,我们可以知道,当相位控制字字长为N位时,输入的相位控制字范围为0~2^N-1,对应0-360°,输出就是正确的三角函数值,范围为-1~1。
另外,再说一点,用DDS IP核来计算三角函数值比用查ROM表得到三角函数值所耗的资源少的多。
四、DDS IP核使用之Phase Generator and SIN COS LUT
将相位增量设置为可编程,这样就由程序控制输出正弦波的频率,相位增量就是相位控制字,不需要相位偏置。S_AXIS_CONFIG里面就是编程控制的相位增量。
其他参数保持默认,直接生成IP核。
五、DDS IP核之Phase Generator and SIN COS LUT仿真
创建一个tb文件对其仿真。代码如下:
`timescale 1ns / 1ps
//
// Company:
// Engineer:
//
// Create Date: 2024/08/08 16:24:30
// Design Name:
// Module Name: tb_DDS_waveform_test
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//
module tb_DDS_waveform_test(
);
parameter PERIOD=2;
reg clk = 1;
initial
begin
forever #(PERIOD/2) clk=~clk;
end
reg s_axis_config_tvalid=0;
reg [15 : 0] s_axis_config_tdata=0;
wire m_axis_data_tvalid;
wire [31 : 0] m_axis_data_tdata;
wire m_axis_phase_tvalid;
wire [15 : 0] m_axis_phase_tdata;
wire [15:0] m_axis_data_tdata_cos;
wire [15:0] m_axis_data_tdata_sin;
assign m_axis_data_tdata_cos=m_axis_data_tdata[15:0];
assign m_axis_data_tdata_sin=m_axis_data_tdata[31:16];
initial
begin
#(PERIOD*5)
forever
begin
@(posedge clk)
begin
s_axis_config_tvalid<=1;
s_axis_config_tdata<=16'd6554;
end
end
end
integer dout_file;
initial begin
dout_file=$fopen("E:/play_vivado/DDS_test/Readme/datacos.txt"); //打开所创建的文件,修改为自己想存储的位置
if(dout_file == 0)
begin
$display ("can not open the file!"); //创建文件失败,显示can not open the file!
$stop;
end
end
always @(posedge clk)
begin
if(m_axis_phase_tvalid)
$fdisplay(dout_file,"%d",$signed(m_axis_data_tdata_cos)); //保存有符号数据
end
DDS_waveform_test u_DDS_waveform_test (
.aclk(clk), // input wire aclk
.s_axis_config_tvalid(s_axis_config_tvalid), // input wire s_axis_config_tvalid
.s_axis_config_tdata(s_axis_config_tdata), // input wire [15 : 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 [31 : 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 [15 : 0] m_axis_phase_tdata
);
endmodule
相位控制字为6554,根据公式可得输出正弦波的频率为
仿真所得波形如下:
在仿真文件里面自己设置的路径下找到datacos.txt(注意要运行仿真一小会儿才会有这个文件),用MATLAB去画它的频谱。
clc;
clear;
close all;
a=61455;
b=a/(2^16-1)
b*360
bsin=sind(b*360)
bcos=cosd(b*360)
vivado_datacos = importdata('datacos.txt'); %read files
vivado_datacos1=vivado_datacos(7:10240)/2^15;
Fs=100000000;
N=length(vivado_datacos1); %信号长度,采样点数
y_fft=fft(vivado_datacos1,N); %快速傅里叶变换
df=Fs/N; %计算谱线间隔
f1=0:df:Fs-df;
f1=f1-Fs/2;
% subplot(1,2,1);
v=abs(fftshift(y_fft))/N;
plot(f1,20*log10(v));
grid on;
xlabel("频率/Hz");ylabel("幅度/dB");
可得频谱图如下:
可见该正弦波频率为10MHz,IP核使用正确。
总结
以上就是本文的全部内容,详细介绍了DDS IP核的使用,它可以拿来计算三角函数值,也可以用来产生正弦波形。