1.实验目的
1.1掌握直接数字频率合成(DDS)的基本原理及其实现方法。
1.2在DE2-115 FPGA开发板上设计一个可调频率的正弦波和方波发生器,频率范围10Hz~5MHz,最小分辨率小于1kHz。
1.3使用Quartus II进行仿真,并通过SignalTap II实时观测输出波形。
2.实验原理
2.1 DDS(Direct Digital Frequency Synthesis)是一种通过数字方式生成高精度、高稳定度频率信号的技术。其核心由三部分组成:
相位累加器 :在时钟驱动下累加频率控制字(K),输出相位值。
波形查找表(LUT) :存储波形采样数据(如正弦波、方波)。
DAC转换 (可选):将数字波形转换为模拟信号(本实验仅观测数字输出)。
2.2输出频率计算公式:

K :频率控制字(Tuning Word)
fclkf clk:系统时钟(50MHz)
NN :相位累加器位数(32位)
3.关键参数设计
3.1频率分辨率 :

3.2频率范围 :
最小值:K=1K =1,fout=0.0116Hzf out=0.0116Hz
最大值(Nyquist限制):fout≤25MHzf out≤25MHz,实际设计目标5MHz。
4.实验设计
4 .1 硬件设计
(1)相位累加器
32位累加器,每个时钟周期增加频率控制字 KK 。
输出相位值的高10位作为LUT地址(1024点正弦表)。
(2)波形查找表(LUT)
正弦波 :c生成1024点8位有符号数据(.mif文件),存储于ROM。
方波 :直接取相位累加器最高位(占空比50%)。
(3)顶层模块
输入:系统时钟(50MHz)、复位信号、频率控制字 KK 、波形选择信号。
输出:8位数字波形数据。
4 .2 关键代码
4.2.1 相位累加器
cs
module addr_cnt(CPi,K,ROMaddr,Address);
input CPi;
input [12:0] K;
output reg [9:0] ROMaddr;
output reg [16:0] Address;
always @(posedge CPi) begin
Address=Address+K;
ROMaddr=Address[16:7];
end
Endmodule
选择Create Symbol Files for Current File


4.2.2 波形存储器ROM
方波模块
cs
module squwave(CPi,RSTn,Address,Qsquare);
input CPi;
input RSTn;
input [16:0] Address;
output reg [11:0] Qsquare;
always @(posedge CPi)
if (!RSTn)Qsquare=12'h000;
else begin
if(Address<=17'h0FFFF)
Qsquare=12'hFFF;
else Qsquare=12'h000;
end
endmodule

4.2.3 正弦波形存储器
其中Sine1024.mif的代码如下:
cs
/*myMIF.c*/
#include <stdio.h>
#include <math.h>
#define PI 3.141592
#define DEPTH 1024
#define WIDTH 12
int main(void)
{
int n,temp;
float v;
FILE *fp;
fp=fopen("Sine1024.mif","w+");
if(NULL==fp)printf("Can not creat file!\r\n");
else
{
printf("File created successfully!\n");
fprintf(fp,"DEPTH=%d;\n",DEPTH);
fprintf(fp,"WIDTH=%d;\n",WIDTH);
fprintf(fp,"ADDRESS_RADIX=HEX;\n");
fprintf(fp,"DATA_RADIX=HEX;\n");
fprintf(fp,"CONTENT\n");
fprintf(fp,"BEGIN\n");
for(n=0;n<DEPTH;n++)
{
v=sin(2*PI*n/DEPTH);
temp=(int)((v+1)*4095/2);
fprintf(fp,"%04x : %03x;\n",n,temp);
}
fprintf(fp,"END;\n");
fclose(fp);
}
}
运行.exe文件生成.mif文件





LPM_ROM定制正弦波形存储器:


以下进行修改:


4.2.4 顶层电路设计
cs
module DDS_top (CLOCK_50,RSTn,WaveSel,K,
WaveValue,LEDG,CLOCK_100);
input CLOCK_50;
input RSTn;
input [1:0] WaveSel;
input [12:0] K;
output reg [11:0] WaveValue;
wire [9:0] ROMaddr/* synthesis keep */;
wire [16:0] Address;
wire [11:0] Qsine,Qsquare;
output [0:0] LEDG;
output CLOCK_100;
wire CPi=CLOCK_100;
PLL100M_CP PLL100M_CP_inst(
.inclk0(CLOCK_50),
.c0(CLOCK_100),
.locked(LEDG[0])
);
addr_cnt U0_instance(CPi,K,ROMaddr,Address);
SineROM ROM_inst(
.address(ROMaddr),
.clock(CPi),
.q(Qsine)
);
squwave U1(CPi,RSTn,Address,Qsquare);
always @(posedge CPi)
begin
case(WaveSel)
2'b01:WaveValue=Qsine;
2'b10:WaveValue=Qsquare;
default:WaveValue=Qsine;
endcase
end
endmodule
4.2.5配置文件
cs
module DE2_115_DDS_top(CLOCK_50,KEY,SW,GPIO_0,LEDG);
input CLOCK_50;
input [3:3] KEY;
input [17:0] SW;
output [12:0] GPIO_0;
output [0:0] LEDG;
wire CLOCK_100;
assign GPIO_0[12]=CLOCK_100;
wire RSTn=KEY[3];
wire [1:0] WaveSel=SW[17:16];
wire [12:0] K=SW[12:0];
wire [11:0] WaveValue;
assign GPIO_0[11:0]=WaveValue;
DDS_top DE2(CLOCK_50,RSTn,WaveSel,K,WaveValue,LEDG,CLOCK_100);
endmodule
4.2.5仿真

进入界面配置


