首页 > 技术 > 内容

基于FPGA实现频率和可调相位的DDS

时间:2026-02-01  作者:Diven  阅读:0

DDS直接数字式频率合成器(Direct Digital Synthesizer)。本文实现一个具有可以频率可调、相位可调的正余弦、方波、三角波的DDS。

DDS的原理如下图,累加器每次累加一个频率控制字,调节频率控制字的数值,可以改变累加器的累加速度,进而可以调节从ROM查找表中读取波形数据的速度。即频率控制字越大,频率越高。相位控制字可以用来调节初始相位,即ROM地址自加的初始值。

从查找表读取出来的数据,经DA转换芯片可以直接输出进行滤波或其操作,最后可使用示波器进行观察波形变化。

DDS 模块的输出频率是系统工作频率、相位累加器比特数N以及频率控制字K三者的一个函数,其数学关系由式如下。

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;

y3=ceil(y1*511);

y4=ceil(y2*511);

%生成cos函数coe文件

fid = fopen(‘cos_coe.coe’,‘wt’);

fprintf(fid,‘MEMORY_INITIALIZATION_RADIX=10;’);

fprintf(fid,‘MEMORY_INITIALIZATION_VECTOR=’);

%fprintf(fid,‘%16.0f’,y3);

for i = 1:1:2^12

fprintf(fid,‘%16.0f’,y3(i));

if i==2^12

fprintf(fid,‘;’);

else

fprintf(fid,‘,’);

end

if i%15==0

fprintf(fid,‘’);

end

end

fclose(fid);

%生成sin函数coe文件

fid = fopen(‘sin_coe.coe’,‘wt’);

fprintf(fid,‘MEMORY_INITIALIZATION_RADIX=10;’);

fprintf(fid,‘MEMORY_INITIALIZATION_VECTOR=’);

for i = 1:1:2^12

fprintf(fid,‘%16.0f’,y4(i));

if i==2^12

fprintf(fid,‘;’);

else

fprintf(fid,‘,’);

end

if i%15==0

fprintf(fid,‘’);

end

end

fclose(fid);

%生成方波

t=1:1:2^12;

y=(t r=ceil(y*(2^9-1));

fid = fopen(‘square.coe’,‘w’); %写到square.coe,用来初始化rom_square

fprintf(fid,‘MEMORY_INITIALIZATION_RADIX=10;’);

fprintf(fid,‘MEMORY_INITIALIZATION_VECTOR=’);

for i = 1:1:2^12

fprintf(fid,‘%d’,r(i));

if i==2^12

fprintf(fid,‘;’);

else

fprintf(fid,‘,’);

end

if i%15==0

fprintf(fid,‘’);

end

end

fclose(fid);

%生成三角波

t=1:1:2^12;

y=[0.5:0.5/1024:1-0.5/1024, 1-0.5/1024:-0.5/1024:0, 0.5/1024:0.5/1024:0.5];

r=ceil(y*(2^9-1));

fid = fopen(‘triangular.coe’,‘w’); %写到triangular.coe,初始化三角波rom

fprintf(fid,‘MEMORY_INITIALIZATION_RADIX=10;’);

fprintf(fid,‘MEMORY_INITIALIZATION_VECTOR=’);

for i = 1:1:2^12

fprintf(fid,‘%d’,r(i));

if i==2^12

fprintf(fid,‘;’);

else

fprintf(fid,‘,’);

end

if i%15==0

fprintf(fid,‘’);

end

end

fclose(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 = 1×7

-5.0000 -3.3333 -1.6667 0 1.6667 3.3333 5.0000 ⋯

https://ww2.mathworks.cn/help/matlab/ref/linspace.html?requestedDomain=zh

Verilog实现

生成coe文件后调用ROM IP Core,需要生成个ROM的读取地址,主要代码如下。

//freq_data为频率控制字,phase_data为相位控制字。

always @(posedge clk_50MHz or negedge rst)begin

if(!rst)

fcnt else

fcnt end

assign addra = fcnt[31:20] + phase_data;

blk_mem_sin blk_mem_sin_inst (

.clka(clk_50MHz), // input wire clka

.addra(addra), // 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 人分享协作。

猜您喜欢


电子工程和电气设计中,电阻器的热功率计算是一个重要的基础环节。合理计算电阻产生的热功率不仅有助于选择合适的电阻器,还能保证电路的安全和稳定运行。本文将详细介绍电...
2025-11-07 22:00:38
贴片电阻R050表示阻值为0.5欧姆。在电子元件中,贴片电阻的阻值通常用数字编码表示,R050就是其中一种常见的表示方法。字母「R」代表小数点,后面的数字则表示...
2024-11-26 11:29:29
肖特基二极管是特殊类型的二极管,低正向压降和快速开关特性而闻名。由于这些优点,肖特基二极管在现代电子设备中得到了应用。本文将深入探讨肖特基二极管的多种用途,帮助...
2025-03-29 13:30:34
快速掌握贴片电阻规格型号对照表,只需抓住几个关键参数:尺寸代码: 表示电阻的封装尺寸,例如「0402」、「0603」等,数字越大,尺寸越大。 0402代表长宽为...
2025-04-14 15:02:23
劳保手套是保护工人双手的重要装备,不同类型的劳保手套适用于不同的工作环境和需求。材质上,劳保手套可以分为橡胶手套、 PVC 手套、尼龙手套和皮革手套等。橡胶手套...
2024-05-07 00:00:00
贴片电阻01B是一种广泛应用于电子电路中的小型化电阻器。其01B的封装尺寸仅为0.063英寸长和0.032英寸宽,非常适合空间受限的应用场合。贴片电阻01B采用...
2024-11-26 11:29:27
现代电子技术中,二极管作为重要的半导体器件,应用于整流、开关和信号调制等领域。随着科技的进步,碳化硅(SiC)二极管逐渐崭露头角,与传统的肖特基二极管相比,展现...
2025-04-05 04:31:40
选购电脑电源,对于很多小白用户来说,就像走进了一片迷宫,各种参数和指标让人眼花缭乱。别担心,这篇指南将带你一步步了解 DDR4 电脑电源的选择要点,助你找到最适...
2024-12-09 11:19:22
贴片电阻虽然体积小巧,但在电路中扮演着重要的角色。它能够限制电流,稳定电压,但如果电压过高,就可能导致电阻击穿,造成电路故障。那么,贴片电阻多少电压能击穿呢?实...
2024-11-26 11:29:57
手工锯是传统而有效的工具,在 woodworking 和 DIY 项目中有着着重要作用。其主要优势有以下几点。手工锯操作简单,适合各种水平的用户。无论是新手还是...
2014-11-08 00:00:00