通过查阅几篇CSDN找到使用方法,在此记录一下。
FPGA数字信号处理基础----Xilinx DDS IP使用_dds ip 脉冲信号-CSDN博客
Vivado的前仿真数据导入到matlab中进行分析 - 知乎 (zhihu.com)
1.configuration
①Configuration option:一共三个模式
Phase Generator and SIN/COS LUT (DDS):
在IP核内部集成好相位累加器与sin/cos模块,只需要在GUI中配置好需要生成的频率即可,可选择单独输出sin,或cos,也可以两个曲线正交输出。
Phase Generator only:
例化的 IP 核只有一个相位累加器,IP核不断输出相位累加的结果
SIN/COS LUT only模式:
例化的IP核只有一个sin/cos模块,需要外部不断的输入累加的相位
②System clock 系统时钟(同时也是采样频率),直接影响DDS输出波形的频率
③Number of channels 通道数,一般默认为1
④Mode of operation 分为两种模式,详情可翻阅Xilinx的官方手册,一般选择标准operation模式
标准operation模式下。
rasterized模式下,把分母换成可直接调控的M,方便输出一些整数频率波形。
⑤Parameter selection分为两种模式,Hardware Parameter 和 System Parameter
Hardware Parameter模式下需要选择是否需要整形噪声Noise Shaping以及输出的相位位宽核数据位宽
System Parameter模式包含Spurious Free Dynamic Range(SFDR)、Frequency Resolution(频率分辨率)、Noise Shaping三种需要配置的参数,SFDR与输出的数据位宽有关,Frequency Resolution与相位位宽有关,通过下面表格可以通过输出位宽算出SFDR
Dither为抖动法,以增加底噪为代价减小SFDR
Taylor是泰勒级数法,201405 (ceaj.org)
Auto为自动选择
system parameter可以选择输出频率,不过需要的参数多,为了方便并且使用泰勒级数法就选择了Hardware Paramete,在Hardware Paramete中输出频率需要通过公式计算:
2.implementation
可以设置为编程模式或者固定模式,编程模式可以在运行过程中改变输出频率。
3.写入相角增量
4.计算过程
本次生成10M信号,激发时钟为100M时钟。使用16位相位宽度
得到角度增量为6554 换成二进制写入3的相角增量即可
5.可以看到生成的频率,
生成数据为12位宽,其中第11位是符号位。
运行代码:
`timescale 1ns / 1ps
module dds_top(
input i_clk ,
input i_rst_n ,
output m_axis_data_tvalid ,
output [11:0] dout_sin
);
//wire [11:0] dout_sin ;
wire ro_dout_vaild ;
wire [15:0] m_axis_data_tdata ;
wire m_axis_data_tvalid ;
wire [15:0] m_axis_phase_tdata ;
wire m_axis_phase_tvalid ;
assign dout_sin = m_axis_data_tdata[11:0];
dds_compiler_0 dds_u0(
.aclk(i_clk), // input wire aclk
.s_axis_config_tvalid(1'd0), // input wire s_axis_config_tvalid
.s_axis_config_tdata(16'd0), // 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 [15 : 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
测试代码:把数据保存在txt里方便观察
module tb_dds(
);
reg clk;
initial begin
clk = 0;
forever #(5) clk = ~clk; // 100M system clokc
end
integer real_out_file;
// integer imag_out_file;
wire[11:0]real_data;
initial
begin
real_out_file = $fopen("./dds_out_real.txt","w");//定义需要保存的路径和文件名
// imag_out_file = $fopen("./fft_out_imag.txt","w");//定义需要保存的路径和文件名
#4500 $fclose(real_out_file) ;//在数据有效结束后关闭文件句柄
// $fclose(imag_out_file) ;//在数据有效结束后关闭文件句柄
end
always @(posedge clk ) begin
if(real_data_tvalid)begin
$fdisplay(real_out_file,"%b",real_data);//将数据保存为二进制
// $fdisplay(imag_out_file,"%b",imag_data);//将数据保存为二进制
end
end
dds_top dds_top_u (
.i_clk(clk), // input wire aclk
.i_rst_n(1'd1),
.m_axis_data_tvalid(real_data_tvalid),
.dout_sin(real_data)
);
endmodule
matlab代码:
clear
clc
close all
data_out = txtread_fi('dds_out_real2.txt',12,0);%12为有符号定点数的总长度,0为小数位的长度 只影响幅度
fs = 100000000; %采样率
N = length(data_out); %采样点数
n = 0:N-1;
t = n/fs; %时间序列
f = n*fs/N; %频率序列
Y = fft(data_out); %对M进行FFT变换
fshift = (-N/2:N/2-1)*fs/N;
y = fftshift(Y); %以0为中心循环平移
y_abs = 10*log10(abs(y));
figure;
subplot(2,1,1);
plot(t,data_out); %时域波形
title('时域波形');xlabel('时间/s');ylabel('幅值');
subplot(2,1,2);
plot(fshift,y_abs); %频域波形
title('频域波形');xlabel('频率/s');ylabel('幅值');
function data_out = txtread_fi(txt_file_path,total_bits_num,fraction_bits_num)
% 打开文件
fileID = fopen(txt_file_path, 'r');
% 使用 textscan 函数读取文件
data_cell = textscan(fileID, '%s', 'delimiter', '\n');
% 获取行数
line_count = numel(data_cell{1});
% 关闭文件
fclose(fileID);
text = fileread(txt_file_path);
data = [];
for i = 1:line_count
data = [data;text((total_bits_num+2)*(i-1)+1:(total_bits_num+2)*(i-1)+total_bits_num)];
end
data_out = data2fix(data,fraction_bits_num);
end
function [data_out] = data2fix(data_in,fraction_bits_num)
[m,~] = size(data_in);
data_out = zeros(m,1);
for data_index = 1:m
% x = dec2bin(data_in(data_index),total_bits_num);
x = data_in(data_index,:);
x_init = zeros(size(x));
y = 0;
if(str2num(x(1))==0)
for i = 1:length(x)
x_init(i) = str2num(x(i));
end
for i = 1:length(x)
y = y+2^(length(x)-i)*x_init(i);
end
else
for i = 1:length(x)
if(str2num(x(i))==1)
x_init(i) = 0;
else
x_init(i) = 1;
end
end
add_bit_last = 1;
for i = 1:length(x)
if((x_init(length(x)+1-i))&&(add_bit_last==1))
x_init(length(x)+1-i) = 0;
add_bit_last = 1;
else
x_init(length(x)+1-i) = x_init(length(x)+1-i)+add_bit_last;
add_bit_last = 0;
end
end
for i = 1:length(x)
y = y+2^(length(x)-i)*x_init(i);
end
y = -y;
end
data_out(data_index) = y/(2^(fraction_bits_num));
end
end
运行结果: