《基于FPGA实现频率和可调相位的DDS.doc》由会员分享,可在线阅读,更多相关《基于FPGA实现频率和可调相位的DDS.doc(14页珍藏版)》请在三一文库上搜索。
1、基于FPGA实现频率和可调相位的DDSDDS直接数字式频率合成器(Direct Digital Synthesizer)。本文实现一个具有可以频率可调、相位可调的正余弦、方波、三角波的DDS。DDS的原理如下图,累加器每次累加一个频率控制字,调节频率控制字的数值,可以改变累加器的累加速度,进而可以调节从ROM查找表中读取波形数据的速度。即频率控制字越大,频率越高。相位控制字可以用来调节初始相位,即ROM地址自加的初始值。从查找表读取出来的数据,经DA转换芯片可以直接输出进行滤波或其他操作,最后可使用示波器进行观察波形变化。DDS 模块的输出频率是系统工作频率、相位累加器比特数N以及频率控制字K
2、三者的一个函数,其数学关系由式如下。DDS的频率分辨率,即频率变化间隔。本设计是调用Xilinx Vivado提供的ROM IP Core来存储波形数据,首先要生成波形数据并添加至IP Core中,Xilinx的文件类型为coe格式。MATLAB代码此MATLAB代码提供正余弦、方波、三角波四种波形的coe文件输出,MATLAB脚本语言并不是很难,有编程基础很快就能看懂,MATLAB提供的函数众多,哪里不会Google哪里。x=linspace(0,2*pi,4096);%6.28为2pi,一个周期采样点取4096个y1=cos(x)+1; %将函数平移到纵轴的正半轴。y2=sin(x)+1;
3、y3=ceil(y1*511);y4=ceil(y2*511);%生成cos函数coe文件fid = fopen(cos_coe.coe,wt);fprintf(fid,MEMORY_INITIALIZATION_RADIX=10;n);fprintf(fid,MEMORY_INITIALIZATION_VECTOR=n);%fprintf(fid,%16.0fn,y3);for i = 1:1:2fprintf(fid,%16.0f,y3(i);if i=2fprintf(fid,;);elsefprintf(fid,);endif i%15=0fprintf(fid,n);endendfc
4、lose(fid);%生成sin函数coe文件fid = fopen(sin_coe.coe,wt);fprintf(fid,MEMORY_INITIALIZATION_RADIX=10;n);fprintf(fid,MEMORY_INITIALIZATION_VECTOR=n);for i = 1:1:2fprintf(fid,%16.0f,y4(i);if i=2fprintf(fid,;);elsefprintf(fid,);endif i%15=0fprintf(fid,n);endendfclose(fid);%生成方波t=1:1:2;y=(t r=ceil(y*(2-1);fid
5、= fopen(square.coe,w); %写到square.coe,用来初始化rom_squarefprintf(fid,MEMORY_INITIALIZATION_RADIX=10;n);fprintf(fid,MEMORY_INITIALIZATION_VECTOR=n);for i = 1:1:2fprintf(fid,%d,r(i);if i=2fprintf(fid,;);elsefprintf(fid,);endif i%15=0fprintf(fid,n);endendfclose(fid);%生成三角波t=1:1:2;y=0.5:0.5/1024:1-0.5/1024,
6、1-0.5/1024:-0.5/1024:0, 0.5/1024:0.5/1024:0.5;r=ceil(y*(2-1);fid = fopen(triangular.coe,w); %写到triangular.coe,初始化三角波romfprintf(fid,MEMORY_INITIALIZATION_RADIX=10;n);fprintf(fid,MEMORY_INITIALIZATION_VECTOR=n);for i = 1:1:2fprintf(fid,%d,r(i);if i=2fprintf(fid,;);elsefprintf(fid,);endif i%15=0fprintf
7、(fid,n);endendfclose(fid);linspace函数生成一个等差数列y = linspace(x1,x2)y = linspace(x1,x2,n)y = linspace(x1,x2) 返回包含 x1 和 x2 之间的 100 个等间距点的行向量。示例y = linspace(x1,x2,n) 生成 n 个点。这些点的间距为 (x2-x1)/(n-1)。y1 = linspace(-5,5,7)y1 = 17-5.0000 -3.3333 -1.6667 0 1.6667 3.3333 5.0000 https:/ww2.mathworks/help/matlab/ref
8、/linspacel?requestedDomain=zhVerilog实现生成coe文件后调用ROM IP Core,需要生成个ROM的读取地址,主要代码如下。/freq_data为频率控制字,phase_data为相位控制字。always (posedge clk_50MHz or negedge rst)beginif(!rst)fcnt elsefcnt endassign addra = fcnt31:20 + phase_data;blk_mem_sin blk_mem_sin_inst (.clka(clk_50MHz), / input wire clka.addra(addr
9、a), / input wire 11 : 0 addra.douta(sin) / output wire 11 : 0 douta);本设计调用了四个IP,将四种波形同时出处,然后用一个四选一的选择器输出给DA模块至示波器显示,仿真截图如下。DA转换D/A转换器采用的是ADI公司的双通道12位21.3MSPS高速DAC转换器AD5447,FPGA 输出的12位数字信号进入AD5447后,经过两个锁存器,转换为差分信号输出芯片内部结构图如图所示。时序图如图所示。可以看到数据写入芯片的的过程也是十分简单,只要CS拉低就可以进行读操作或写操作。芯片的输入数据是并行的,我这里输入的数据就是MATLAB的直接生成的12bit的数据,输出电压的幅值手册给出了计算公式,清晰明了。Sin和Cos的波形是一样的,将三种波形输出用示波器查看。波形很漂亮。这个工程,我放在GitHub上了。订阅号后台回复“DDS”即可获得这个工程。GitHub 正式宣布了 GitHub Free 以及 GitHub Enterprise。GitHub Free:包含不限量的私有仓库,每个私有仓库里的项目最多可以与 3 人分享协作。
链接地址:https://www.31doc.com/p-3410225.html