目录
一、设计原理与准备
1.1 DDS 原理
1.2 IP 核学习与准备:FPGA开发中常用IP核——ROM/RAM/FIFO
2、ROM文件的设置
1.3 开发环境搭建
二、DDS 信号发生器设计实现
2.1 系统架构设计
2.2 代码编写与模块实现
三、测试结果与总结
参考文献:
引言:
在电子技术领域,信号发生器是不可或缺的工具。直接数字频率合成(Direct Digital Frequency Synthesis,DDS)技术凭借其频率转换速度快、分辨率高、相位连续性好等优势,成为信号生成的热门选择。本文将详细介绍基于 DDS 技术的信号发生器设计过程,实现正弦波和方波的合成,并满足特定频率范围与分辨率要求,同时利用嵌入式逻辑分析仪进行实时测试。
一、设计原理与准备
1.1 DDS 原理
DDS 的核心思想是通过数字计算和数模转换来生成模拟信号。其基本结构包括相位累加器、波形存储器(ROM)、数字模拟转换器(DAC)等。相位累加器在时钟信号的驱动下,不断进行累加操作,其输出作为波形存储器的地址,从波形存储器中读取预先存储的波形数据,再经过 DAC 转换为模拟信号输出。通过改变相位累加器的累加步长,就可以实现输出信号频率的调整。
1.2 IP 核学习与准备:FPGA开发中常用IP核——ROM/RAM/FIFO
常见的 FPGA 存储器有 3 种:RAM (随机访问内存)、ROM (只读存储器)、FIFO (先入先出)。这三种存储器的区别如下:
-
RAM:通常掉电后数据丢失,支持随机读写操作。根据特性可分为:
- SRAM(静态随机存储器):速度快,无需刷新,但集成度低,常用于高速缓存
- DRAM(动态随机存储器):需周期性刷新,集成度高,用于大容量存储
- BRAM(块随机存储器):FPGA 内部专用存储块,低延迟、高带宽
-
ROM:系统断电后数据不丢失,数据写入需特定编程方式。在 FPGA 中常见类型:
- MROM(掩膜只读存储器):数据由制造商写入,不可更改
- PROM(可编程只读存储器):用户可一次性编程
- EPROM(可擦除可编程只读存储器):通过紫外线擦除重写
- EEPROM(电可擦可编程只读存储器):支持电信号擦除,常用于配置数据存储
-
FIFO:数据遵循先入先出原则,地址由内部指针自动管理。关键参数:
- 满标志 (Full):指示 FIFO 已写满
- 空标志 (Empty):指示 FIFO 已读空
- 可编程满 / 空阈值:支持自定义触发条件
- 同步 / 异步时钟域:分同步 FIFO(单时钟域)和异步 FIFO(跨时钟域)
应用场合对比:
存储器类型 | 典型应用场景 | 关键优势 | FPGA 实现方式 |
---|---|---|---|
RAM | 数据缓存、图像处理帧缓冲、高速数据暂存 | 随机读写、高速访问 | BRAM、分布式 RAM |
ROM | 波形表存储(如 DDS)、配置参数存储、查找表 (LUT) | 非易失性、数据稳定 | 初始化 BRAM、专用 ROM IP 核 |
FIFO | 跨时钟域数据传输、数据流速率匹配、突发数据缓冲 | 自动地址管理、同步隔离 | 专用 FIFO IP 核 |
在 DDS 设计中:
- ROM:用于存储预计算的正弦 / 方波波形数据,需配置为同步读模式
- FIFO:可用于缓存 DAC 输出数据,解决时钟域不匹配问题
- RAM:可扩展用于存储多组波形参数,支持动态切换波形类型
在调用 IP 核时,需特别注意:
- 同步与异步模式:跨时钟域设计必须使用异步 FIFO
- 深度与宽度权衡:增加深度可提高缓冲能力,但会占用更多 BRAM 资源
- 复位策略:合理设置同步复位或异步复位,确保系统可靠启动
- 数据对齐:注意数据位宽匹配,避免数据截断或扩展带来的精度损失
1、ROM简介
ROM 是只读存储器(Read-Only Memory)的简称,是一种只能读出事先所存数据的固态半导体存储器。其特性是一旦储存资料就无法再将之改变或删除,且资料不会因为电源关闭而消失。而事 实上在 FPGA 中通过 IP 核生成的 ROM 或 RAM(RAM 将在下一节为大家讲解)调用的都是FPGA 内部的 RAM 资源,掉电内容都会丢失(这也很容易解释,FPGA 芯片内部本来就没有掉电非易失存储器单元)。用 IP 核生成的 ROM 模块只是提前添加了数据文件(.coe 格式)(.mif/.hex格式),在 FPGA 运行时通过数据文件给 ROM 模块初始化,才使得 ROM 模块像个“真正”的掉电非易失存储器;也正是这个原因,ROM 模块的内容必须提前在数据文件中写死,无法在电路中修改。
最简单的使用有效时钟CLKA、有效地址ADDRA和有效使能EA,就可以输出DOUTA
单端口ROM:只提供一个独立的地址端口核一个读数据端口
2、ROM文件的设置
1.3 开发环境搭建
本次设计基于 DE2-115 开发板,开发环境选用 Quartus Prime 等 FPGA 开发工具。在开始设计之前,确保开发环境已经正确安装和配置,熟悉开发工具的基本操作流程,包括工程创建、IP 核调用、代码编写、编译综合、下载调试等环节,为后续的设计实现奠定基础。
二、DDS 信号发生器设计实现
2.1 系统架构设计
根据设计要求,DDS 信号发生器系统主要由相位累加器模块、波形存储器模块、频率控制字输入模块、波形转换模块(用于生成正弦波和方波)以及嵌入式逻辑分析仪模块组成。相位累加器模块根据输入的频率控制字,在时钟信号的驱动下进行相位累加;波形存储器模块存储正弦波和方波的数字化波形数据;频率控制字输入模块接收用户设置的频率参数,生成相应的频率控制字;波形转换模块根据相位累加器的输出,从波形存储器中读取数据,并进行相应的处理,生成正弦波和方波信号;嵌入式逻辑分析仪模块用于实时采集和分析输出波形的离散数据。
2.2 代码编写与模块实现
在 Quartus Prime 中创建工程,按照系统架构设计,分别编写各个模块的 Verilog HDL 代码。
- 相位累加器模块:根据输入的时钟信号和频率控制字,实现相位的累加功能。代码如下:
module phase_accumulator(input wire clk,input wire rst_n,input wire [31:0] freq_control_word,output reg [31:0] phase_accumulator_output
);
always @(posedge clk or negedge rst_n) beginif (!rst_n) beginphase_accumulator_output <= 32'd0;end else beginphase_accumulator_output <= phase_accumulator_output + freq_control_word;end
end
endmodule
2.DDS技术合成正弦波和方波
利用DDS技术合成正弦波和方波,很多EDA软件都需要.mif文件,比如使用Quartus 调用ROM IP核产生一个正弦波就需要对ROM IP核加载.mif文件,然后从.mif文件中读取数据产生正弦波
正弦波
1)利用matlab生成ROM初始化文件mif
% 参数设置
addr_width = 10; % ROM地址位宽(1024点)
data_width = 8; % 数据位宽(8位)
filename = 'sine_wave.mif'; % 输出文件名% 生成正弦波数据
rom_depth = 2^addr_width;
t = linspace(0, 2*pi, rom_depth); % 0到2π的相位
sine_data = sin(t); % 生成正弦波(范围[-1, 1])% 量化到8位无符号整数(0~255)
sine_data = round((sine_data + 1) * (2^(data_width-1) - 1));% 写入mif文件
fid = fopen(filename, 'w');
fprintf(fid, 'WIDTH=%d;\n', data_width);
fprintf(fid, 'DEPTH=%d;\n', rom_depth);
fprintf(fid, 'ADDRESS_RADIX=HEX;\n');
fprintf(fid, 'DATA_RADIX=HEX;\n\n');
fprintf(fid, 'CONTENT BEGIN\n');for addr = 0:rom_depth-1fprintf(fid, ' %04X : %02X;\n', addr, sine_data(addr+1));
endfprintf(fid, 'END;\n');
fclose(fid);
disp('mif文件生成成功!');
在运行完上面一段代码后也就在同一文件夹下生成了一个sine_wave.mif文件如下图所示
设置模块LPM_ROM参数的具体步骤如下:
1)在QuartusPrime主界面选择Tool一IPCatalog命令,在查找框内输入ROM,IP核目录(IPCatalog)栏
中会列出相关的IP核,选择ROM:1-PORT并双击,弹出保存IP设置界面,输入文件名,并选中Verilog,单击OK按钮。
3).输入mif文件中宽度和深度,要匹配上(8、1024)
4).全不选择即可,next
DDS模块设计
module dds_sine_wave (input clk, // 系统时钟input reset, // 复位input [31:0] fcw, // 频率控制字(Frequency Control Word)output [7:0] wave_out // 正弦波输出
);// 相位累加器(32位)
reg [31:0] phase_accumulator;// 相位累加器更新
always @(posedge clk or posedge reset) beginif (reset)phase_accumulator <= 32'd0;elsephase_accumulator <= phase_accumulator + fcw;
end// 取高10位作为ROM地址(相位截断)
wire [9:0] rom_address = phase_accumulator[31:22];// 实例化ROM
rom_sine_wave rom_inst (.address(rom_address),.clock(clk),.q(wave_out)
);endmodule
Testbench仿真
`timescale 1ns/1nsmodule tb_dds_sine_wave;// 输入信号
reg clk;
reg reset;
reg [31:0] fcw;// 输出信号
wire [7:0] wave_out;// 例化DDS模块
dds_sine_wave uut (.clk(clk),.reset(reset),.fcw(fcw),.wave_out(wave_out)
);// 时钟生成(50MHz)
initial beginclk = 0;forever #10 clk = ~clk; // 20ns周期 → 50MHz
end// 仿真流程
initial begin// 初始化reset = 1;fcw = 32'h0000_0000; // 初始频率控制字#100;reset = 0;// 设置fcw生成1kHz正弦波(示例值)// Fout = (50e6 * fcw) / 2^32 → fcw = Fout * 2^32 / 50e6fcw = 32'h00A3D70A; // 对应约1kHz// 仿真运行(至少覆盖多个周期)#2000000; // 仿真2ms(观察2个完整周期)$stop;
endendmodule
添加仿真文件:
然后一直ok到底
仿真效果
三、测试结果与总结
经过仿真和开发板实践测试,DDS 信号发生器能够成功生成正弦波和方波信号,输出信号的频率范围满足 10Hz~5MHz 的要求,最小频率分辨率小于 1kHz。通过嵌入式逻辑分析仪采集到的离散数据,也与设计预期相符,证明了设计的有效性和准确性。
在设计过程中,深入学习了 DDS 技术的原理和 IP 核的使用方法,掌握了 FPGA 开发的全流程。同时,也遇到了一些问题,如 IP 核参数设置不合理导致波形失真、代码逻辑错误等,通过查阅资料和调试解决了这些问题。本次设计为进一步深入研究 DDS 技术和 FPGA 应用奠定了坚实的基础,后续可以在此基础上进行功能扩展,如增加更多类型的波形生成、提高频率分辨率等。
以上分享了 DDS 信号发生器的设计过程。如有不妥之处还望各位海涵。祝好!
参考文献:
用FPGA实现dds的方案详解(保姆级入门教学)(VIVADO18.3、quartus13.1)_fpga开发_Jefferymeng-2048 AI社区
FPGA中级项目1——IP核(ROM 与 RAM)
【FIFO IP系列】FIFO IP参数配置与使用示例
【FPGA基础学习】DDS信号发生器设计-CSDN博客
DDS信号发生器原理与经典DDS信号发生器设计方案-CSDN博客