当前位置:网站首页>如何使用xilinx的DDS生成多项数据
如何使用xilinx的DDS生成多项数据
2022-08-06 14:12:00 【FPGA-信号处理】
目的
本文章的目的在于怎么使用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=1800;
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仿真结果

FPGA的实现
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 ;
[email protected](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
[email protected](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
[email protected](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仿真结果

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

实际编译完成上板调试

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

生成1800M信号:

本项目工程链接地址:工程下载
边栏推荐
- redis use
- IO的阻塞和非阻塞、同步和异步
- ERC4907 的到来 会给 NFT 带来哪些变革?
- 天梯赛真题——7-6 老板的作息表(25 分)
- 10 文件上传和下载
- R语言使用addmargins函数和prop.table函数为二维列联表计算列(column)比例值以及对应的边缘比率值、使用addmargins函数和prop.table函数计算二维列联表行边缘比率
- 多机分布式执行异步任务的实现姿势
- LeetCode Brushing Diary: Full Arrangement
- mosquitto使用的基本流程以及一些遇见的问题
- 【paper速读】NLNL: Negative Learning for Noisy Labels (ICCV2019)
猜你喜欢
随机推荐
天梯赛真题——7-6 老板的作息表(25 分)
爬虫之Scrapy框架
How to switch configuration files and deployment in microservices
The real question of the ladder game - 7-6 boss's schedule (25 points)
Go 大杀器之跟踪剖析 trace
【蓝桥杯集训100题】scratch售票找零 蓝桥杯scratch比赛专项预测编程题 集训模拟练习题第23题
浅谈树状数组
速览muduo组成结构
js array to remove the specified element [function encapsulation] (including object array to remove the specified element)
微服务数据库分库设计解决方案(跨库关联查询、分布式事务处理)
The R language uses the addmargins function and the prop.table function to calculate the column ratio value and the corresponding edge ratio value for the two-dimensional contingency table, and uses t
Analysis of Rocket MQ Crash-Safe Mechanism
SAP 特征 Classification
redis使用
Why are there so many security incidents in DeFi?
【paper速读】NLNL: Negative Learning for Noisy Labels (ICCV2019)
Golang sync.Once
winbox管理端口多少?
redis use
兆骑科创双创服务平台,创新创业高层次人才引进,投融资对接









