如何使用xilinx的DDS生成多项数据

目的

本文章的目的在于怎么使用dds生成单项数据和多项数据,单项数据和多项数据在实际的工程应用中做DDC和DUC时的本振信号。
什么是单项数据:
单项数据就是在每个采样时钟下只有一个样本,如250M采样率即250M的时钟下你每个时钟一个样本,则只需要要求FPGA内部时钟在250MHz下处理每个时钟下的单项数据样本即可。
什么是多项数据:
多项数据就是在每个时钟下产生多个样本,这种主要在高采样率下出现,如1GHz的采样率,即1GHz的时钟下每个时钟一个采样点,但是1GHz的频率在FPGA内部是实现不了的,所以我们需要降时钟,提高样本数量,从而达到1GHz采样率的数据量。比如让FPGA内部时钟工作在250M,则需要每个时钟下产生4个样本才能满足1GHz的采样率。这就是多项数据的由来。

matlab理论实现

Matlab仿真代码

clc;
clear all;
close all;

ploy_phase=16;  %数据的项数
fs=250*ploy_phase;%实际的数据采样率
len=1024;       %生成数据长度
fo=10;

t=0:1/(fs/ploy_phase):(len-1)/1/(fs/ploy_phase);%多项数据每一项时间间隔

pha=0;
for i=1:ploy_phase
    dat(i,:)=cos(2*pi*fo*t+pha);
    pha=pha+2*pi*fo*(1/fs);     %每一项的相位偏移不一样
end
%对信号的时域和频域画图
dac_dat=reshape(dat,1,len*ploy_phase);
subplot(211);
plot(dac_dat);
dat=awgn(dac_dat,40);
subplot(212);
[f,fft_data] = data_fft(dat', fs);
plot(f,fft_data);

matlab仿真结果

16路多项数据合成的结果

FPGA的实现

DDS IP的生成

DDS IP设置
DDS IP设置
DDS IP设置

Verilog代码

module	dac_dat_gen	#(
	parameter			PLOYPHASE	=	16
)(
	input							i_clk				,
	input							i_rst				,

	output							o_dat_vld			,
	output	reg	[15:0]				o_dat_i				,
	output	reg	[15:0]				o_dat_q				,

	output							o_ploy_dat_vld		,
	output		[PLOYPHASE*16-1:0]	o_ploy_dat_q		,
	output		[PLOYPHASE*16-1:0]	o_ploy_dat_i		
);

//生成单项数据

wire								data_tvalid			;
wire	[31:0]						data_tdata			;
wire	[63:0]						phase_tdata			;

reg		[31:0]						phase_pinc			;
reg		[31:0]						phase_poff			;

always@(posedge i_clk)
begin
	if(i_rst)	begin
		phase_pinc<=0;
		phase_poff<=0;
	end
	else	begin
		phase_pinc<=32'h73333333;
		phase_poff<=0;
		if(data_tvalid)	begin
			o_dat_i<=data_tdata[15:0];
			o_dat_q<=data_tdata[31:16];
		end
	end
end

assign	phase_tdata	=	{phase_poff,phase_pinc};

dds_compiler_0	u1_dds(
	.aclk							(i_clk				),// input wire aclk
	.aresetn						(~i_rst				),// input wire aresetn
	.s_axis_phase_tvalid			(1'b1				),// input wire s_axis_phase_tvalid
	.s_axis_phase_tdata				(phase_tdata		),// input wire [63 : 0] s_axis_phase_tdata
	.m_axis_data_tvalid				(data_tvalid		),// output wire m_axis_data_tvalid
	.m_axis_data_tdata				(data_tdata			)// output wire [31 : 0] m_axis_data_tdata
);
assign	o_dat_vld	=	data_tvalid;

//生成多项数据
localparam					DDS_FTW	=	32'h01111111		;

wire	[PLOYPHASE-1:0]		ploy_data_tvalid				;
wire	[31:0]				ploy_data_tdata[PLOYPHASE-1:0]	;
wire	[63:0]				ploy_phase_tdata[PLOYPHASE-1:0]	;

reg		[31:0]				ploy_phase_pinc[PLOYPHASE-1:0]	;
reg		[31:0]				ploy_phase_poff[PLOYPHASE-1:0]	;

genvar	i;
generate
for(i=0;i<PLOYPHASE;i=i+1)	begin
	always@(posedge i_clk)
	begin
		if(i_rst)	begin
			ploy_phase_pinc[i]<=0;
			ploy_phase_poff[i]<=0;
		end
		else	begin
			ploy_phase_pinc[i]<=DDS_FTW<<$clog2(PLOYPHASE);
//			ploy_phase_poff[i]<=i*(32'h73333333>>$clog2(PLOYPHASE));
			ploy_phase_poff[i]<=i*DDS_FTW;
		end
	end

	assign	o_ploy_dat_i[i*16+:16]	=	ploy_data_tdata[i][15:0];
	assign	o_ploy_dat_q[i*16+:16]	=	ploy_data_tdata[i][31:16];
	assign	ploy_phase_tdata[i]		=	{ploy_phase_poff[i],ploy_phase_pinc[i]};
	
	dds_compiler_0	u2_dds(
		.aclk							(i_clk				),// input wire aclk
		.aresetn						(~i_rst				),// input wire aresetn
		.s_axis_phase_tvalid			(1'b1				),// input wire s_axis_phase_tvalid
		.s_axis_phase_tdata				(ploy_phase_tdata[i]),// input wire [63 : 0] s_axis_phase_tdata
		.m_axis_data_tvalid				(ploy_data_tvalid[i]),// output wire m_axis_data_tvalid
		.m_axis_data_tdata				(ploy_data_tdata[i]	)// output wire [31 : 0] m_axis_data_tdata
	);
end
endgenerate

assign	o_ploy_dat_vld	=	ploy_data_tvalid[0];

endmodule

tesebench代码

`timescale 1ns/1ps

module testbench;

localparam							PLOYPHASE	=16		;

wire	[15:0]						dat_i				;
wire	[15:0]						dat_q				;
wire	[PLOYPHASE*16-1:0]			ploy_dat_i			;
wire	[PLOYPHASE*16-1:0]			ploy_dat_q			;
wire								dat_vld				;
wire								ploy_dat_vld		;

reg									clk					;
reg									rst					;
reg									ploy_dat_vld_d1		;
reg		[15:0]						wr_cnt				;

dac_dat_gen	#(
	.PLOYPHASE						(PLOYPHASE			)
)u_dac_dat_gen(
	.i_clk							(clk				),
	.i_rst							(rst				),

	.o_dat_vld						(dat_vld			),
	.o_dat_i						(dat_i				),
	.o_dat_q						(dat_q				),
	.o_ploy_dat_vld					(ploy_dat_vld		),
	.o_ploy_dat_q					(ploy_dat_q			),
	.o_ploy_dat_i					(ploy_dat_i			)
);

always	#2.0	clk	=	~clk		;

initial	begin
	clk=0;
	rst=1;
	#200;
	rst=0;
end

integer	fp;
initial	begin
	fp=$fopen("./matlab/dac_dat.bin","w");
end

always@(posedge clk)
begin
	if(rst)	begin
		wr_cnt			<=0;
		ploy_dat_vld_d1	<=0;
	end
	else	begin
		ploy_dat_vld_d1<=ploy_dat_vld;
		if(wr_cnt<1024 && ploy_dat_vld_d1)	begin
			wr_cnt<=wr_cnt+1;
			$fwrite(fp,"%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n",
										$signed(ploy_dat_q[15:0])	,$signed(ploy_dat_q[31:16]),
										$signed(ploy_dat_q[47:32])	,$signed(ploy_dat_q[63:48]),
										$signed(ploy_dat_q[79:64])	,$signed(ploy_dat_q[95:80]),
										$signed(ploy_dat_q[111:96])	,$signed(ploy_dat_q[127:112]),
										$signed(ploy_dat_q[143:128]),$signed(ploy_dat_q[159:144]),
										$signed(ploy_dat_q[175:160]),$signed(ploy_dat_q[191:176]),
										$signed(ploy_dat_q[207:192]),$signed(ploy_dat_q[223:208]),
										$signed(ploy_dat_q[239:224]),$signed(ploy_dat_q[255:240]));
		end
	end
end
endmodule

modelsim仿真结果

16项仿真数据

对modelsim仿真的数据进行fft分析

Modelsim仿真结果分析

实际编译完成上板调试

10M的16项数据

对Vivado保存数据csv文件进行分析

10M的CSV数据分析
生成1800M信号:
1800M的16项数据
1800M的CSV数据分析
本项目工程链接地址:工程下载

  • 1
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值