【FPGA基础学习】DDS信号发生器设计
一、IP核简介
IP核的定义与核心作用
-
定义
IP核是芯片设计中独立功能的成熟模块,例如处理器、存储器、接口协议等。它们以硬件描述语言(HDL)、网表或物理版图形式交付,供其他设计者直接调用,避免重复开发 -
核心作用
-
缩短设计周期:通过复用已验证的模块,减少从零开发的时间,加速产品上市
-
降低成本与风险:避免重复设计错误,降低研发投入和测试成本
-
IP的种类
IP核有行为(Behavior)级、结构(Structure)级和物理(Physical)级三个层次的分类,对应着三个种类型的IP核,它们是由硬件描述语言设计的软核(Soft IP Core)、完成结构描述的固核(Firm IP Core) 和基于物理描述并经过工艺验证的硬核(Hard IP Core)。
软核: 它是用硬件描述语言(HDL)设计的独立功能的电路模块。从芯片设计程度来看,它只经过了RTL级设计优化和功能验证,通常是以HDL文本形式提交给用户。所以它不包含任何物理实现信息,因此,IP软核与制造工艺无关。软核相当于软件编程的库,比如Python调用一个四舍五入round(num,n) 函数一样。FPGA设计中也可以调用一个四舍五入的IP,这样就不用自己写代码了。
固核: 它的设计程度介于IP软核和IP硬核之间,它除了完成IP软核所有的设计外,还完成了门级电路综合和时序仿真等设计环节。一般地,它以门级电路网表的形式提供给用户。
硬核: 它提供了电路设计最后阶段掩模级的电路模块。它以最终完成的布局布线网表形式提供给用户。IP硬核既具有结果的可预见性,也可以针对特定工艺或特定IP提供商进行功耗和尺寸的优化。
二、采用DDS设计制作波形发生器
1.DDS简介
DDS技术最初是作为频率合成技术提出的,由于其易于控制,相位连续,输出频率稳定度高,分辨率高, 频率转换速度快等优点,现在被广泛应用于任意波形发生器(AWG)。基于DDS技术的任意波形发生器用高速存储器作为查找表,通过高速D/A转换器来合成出存储在存储器内的波形。所以它不仅能产生正弦、余弦、方波、三角波和锯齿波等常见波形,而且还可以利用各种编辑手段,产生传统函数发生器所不能产生的真正意义上的任意波形。
直接频率合成(Direct Dgital Sythesizer, DDS) 是种把-系列数字信号通过数字模拟转换器(igital to Analog Converter, DAC) 转换为模拟信号的新型频率合成技术。其优点有频率切换时间短,频率分析率高,输出信号的频率和相位可以快速切换,输出相位连续,并且很容易地实现信号频率、相位和幅度的控制。
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按钮。


2)选择一个port,在路径后输入文件名称/rom_sine_wave.v,点击next

3).输入mif文件中宽度和深度,要匹配上(8、1024)

4).全不选择即可,next

5).点击browse,选择项目路径下mif文件,完成后点击next

6).默认next即可,点击finish

点击yes

7).完成后再文件中可以看到生成的rom_sine_wave.v文件

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到底
仿真效果

这里我遇到一个问题就是modesim只输出方波,我一开始以为是我代码的问题,后来才发现是,需要设置modesim的输出格式:

方波
1)利用matlab生成ROM初始化文件mif
% 参数设置
addr_width = 10; % ROM地址位宽(1024点)
data_width = 8; % 数据位宽(8位)
duty_cycle = 0.5; % 占空比(50%)
filename = 'square_wave.mif'; % 输出文件名% 生成方波数据
rom_depth = 2^addr_width;
high_value = 2^data_width - 1; % 最大值(8'hFF)
low_value = 0;
split_point = round(rom_depth * duty_cycle);% 初始化ROM数据
rom_data = [high_value * ones(1, split_point), ...low_value * ones(1, rom_depth - split_point)];% 写入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, rom_data(addr+1));
endfprintf(fid, 'END;\n');
fclose(fid);
disp('mif文件生成成功!');


后面的步骤与正弦波的操作相似
DDS模块设计(方波合成)
module dds_square_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_square_wave rom_inst (.address(rom_address),.clock(clk),.q(wave_out)
);endmodule
编写Testbench
`timescale 1ns/1nsmodule tb_dds_square_wave;// 输入信号
reg clk;
reg reset;
reg [31:0] fcw;// 输出信号
wire [7:0] wave_out;// 例化DDS模块
dds_square_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// 仿真运行#200000; // 仿真200us(观察多个周期)$stop;
endendmodule
添加仿真文件:

仿真效果:

参考链接:
零基础学FPGA(四):IP是什么东西(什么是软核,硬核)
FPGA开发——IP核的RAM调用(单端口)
FPGA中级项目1——IP核(ROM 与 RAM)
【FIFO IP系列】FIFO IP参数配置与使用示例
FPGA_DDS生成正弦波
相关文章:
【FPGA基础学习】DDS信号发生器设计
一、IP核简介 IP核的定义与核心作用 定义 IP核是芯片设计中独立功能的成熟模块,例如处理器、存储器、接口协议等。它们以硬件描述语言(HDL)、网表或物理版图形式交付,供其他设计者直接调用,避免重复开发 核心作用 缩…...
【四川省第三届青少年C++算法设计大赛 (小低组) 第 一试】
一、单项选择题(共15题,每题2分,共计30分;每题有且仅有一个正确选项) 1、计算机中负责执行算术和逻辑运算的部件是() A. 内存 B.CPU C.硬盘 D.鼠标 2、近期备受关注的国产开源生成式人工智能大模型是() A. AlphaChat B. OpenPilot …...
linux ceres库编译注意事项及测试demo
最近linux编译了ceres库,因为要涉及到一个程序源代码的编译,但是反复测试,一直各种错误,所以一个个问题排除; 虽然前面ceres库编译成功了,但是版本自定义扔进去的,所以在进行代码编译的时候各种报错。 参考…...
Flux.1+ComfyUI组合实战!本地部署生成高质量AI图片全流程指南
文章目录 前言1. 本地部署ComfyUI2. 下载 Flux.1 模型3. 下载CLIP模型4. 下载 VAE 模型5. 演示文生图6. 公网使用 Flux.1 大模型6.1 创建远程连接公网地址 7. 固定远程访问公网地址 前言 在这个AI技术风起云涌的时代,图像生成模型已经从科幻变成了现实中的‘印钞机…...
css hover 实现鼠标放上去后略微放大的效果
代码如下: <div class"button">文字</div>css代码如下: .button{width: 100px;height: 50px;margin-top: 100px;margin-left: 100px;color: white;background-color: gray;line-height: 50px;text-align: center;transition: all…...
UWB定位技术目前主要应用在哪些行业(更新2025)
UWB定位技术的主要行业应用 一、工业制造领域 人员与设备定位:通过厘米级精度追踪工人、叉车及设备位置,优化生产流程并提升安全管理效率(如高危区域实时报警)。防撞预警与工时统计:结合电子围栏实现设…...
深入解析C++引用:安全高效的别名机制及其与指针的对比
一、引用的核心概念 1.1 引用定义 引用(Reference)是C为变量创建的别名,通过&符号声明。其核心特性: 指针适用场景: 现代C黄金法则: "引用是指针的安全马甲,而智能指针是带着安全帽的…...
分词与倒排索引的原理:深入解析与 Java 实践
在信息检索领域,如搜索引擎和全文检索系统,分词(Tokenization)和倒排索引(Inverted Index)是核心技术。分词将文本拆分为语义单元,为索引构建提供基础;倒排索引则高效映射词项到文档…...
vscode格式化为什么失效?自动保存和格式化(Prettier - Code formatter,vue-format)
vscode自动格式化保存最终配置 博主找了好多的插件,也跟着教程配置了很多,结果还是没有办法格式化,最终发现了一个隐藏的小齿轮,配置完后就生效了 关键步骤 关键配置 一定要点小齿轮!!! 这个小…...
鸿蒙应用元服务开发-Account Kit配置登录权限
一、场景介绍 华为账号登录是基于OAuth 2.0协议标准和OpenID Connect协议标准构建的OAuth2.0 授权登录系统,元服务可以方便地获取华为账号用户的身份标识,快速建立元服务内的用户体系。 用户打开元服务时,不需要用户点击登录/注册按钮&#…...
如何提高webrtc操作跟手时间,降低延迟
第一次做webrtc项目,操作延迟,一直是个问题,多次调试都不能达到理想效果。偶尔发现提高jitterBuffer时间可以解决此问题。关键代码 const _setJitter (values: number) > { const receives peerConnection.getReceivers();receives.f…...
Promise链式调用、async和await
目录 回调函数地狱与Promise链式调用 一、回调函数地狱 1. 典型场景示例 2. 回调地狱的问题 二、Promise链式调用 1. 链式调用解决回调地狱 2. 链式调用的核心规则 三、链式调用深度解析 1. 链式调用本质 2. 错误处理机制 四、回调地狱 vs 链式调用 五、高级链式技…...
React ROUTER之嵌套路由
第一张是需要修改router文件createBrowserRouterd参数数组中的路由关系 第二张是需要在一级路由的index.js中选择二级路由的位置 第一步是在全局的router.js文件中加入新的children属性,如图 第二步是在一级路由的index.js文件中声明outLet组件 默认二级路由 在…...
TestNG 单元测试详解
1、测试环境 jdk1.8.0 121 myeclipse-10.0-offline-installer-windows.exe TestNG 插件 org.testng.eclipse 6.8.6.20130607 0745 2、介绍 套件(suite):由一个 XML 文件表示,通过<suite>标签定义,包含一个或更多测试(test)。测试(test):由<test>定义…...
测试100问:http和https的区别是什么?
哈喽,大家好,我是十二,今天给大家分享的问题是:http和https的区别是什么? 首先我们要知道 HTTP 协议传播的数据都是未加密的,也就是明文的,因此呢使用 http协议传输一些隐私信息也就非常不安全&…...
通过python实现bilibili缓存视频转为mp4格式
需要提前下好ffmpeg import os import fnmatch import subprocess Bilibili缓存的视频,*280.m4s结尾的是音频文件,*050.m4s结尾的是视频,删除16进制下前9个0,即为正常音/视频 使用os.walk模块,遍历每一个目录…...
高效爬虫:一文掌握 Crawlee 的详细使用(web高效抓取和浏览器自动化库)
更多内容请见: 爬虫和逆向教程-专栏介绍和目录 文章目录 一、Crawlee概述1.1 Crawlee介绍1.2 为什么 Crawlee 是网页抓取和爬取的首选?1.3 为什么使用 Crawlee 而不是 Scrapy1.4 Crawlee的安装二、Crawlee的基本使用2.1 BeautifulSoupCrawler的使用方式2.2 ParselCrawler的使…...
React中 点击事件写法 的注意(this、箭头函数)
目录 1、错误写法:onClick{this.acceptAlls()} 2、正确写法:onClick{this.acceptAlls}(不带括号) 总结 方案1:构造函数绑定 方案2:箭头函数包装方法(更简洁) 方案3&am…...
【分享】Ftrans文件摆渡系统:既保障传输安全,又提供强集成支持
【分享】Ftrans文件摆渡系统:既保障传输安全,又提供强集成支持! 在数字化浪潮中,企业对数据安全愈发重视,网络隔离成为保护核心数据的关键防线,比如隔离成研发网-办公网、生产网-测试网、内网-外网等。网络…...
Day31笔记-进程和线程
一、进程和线程简介 1.概念 1.1多任务 程序的运行是CPU和内存协同工作的结果 操作系统比如Mac OS X,UNIX,Linux,Windows等,都是支持“多任务”的操作系统 问题1:什么是多任务? 就是操作系统可以同时运行多个任务。打个比方,你一边在用浏览器上网,一边在听MP3,一边…...
python每日一练
题目一 输入10个整数,输出其中不同的数,即如果一个数出现了多次,只输出一次(要求按照每一个不同的数第一次出现的顺序输出)。 解题 错误题解 a list(map(int,input().split())) b [] b.append(a[i]) for i in range(2,11):if a[i] not in b:b.append(a[i]) print(b)但是会…...
深入理解 RxSwift 中的 Driver:用法与实践
目录 前言 一、什么是Driver 1.不会发出错误 2.主线程保证 3.可重放 4.易于绑定 二、Driver vs Observable 三、使用场景 1.绑定数据到UI控件 2.响应用户交互 3.需要线程安全的逻辑 4.如何使用Driver? 1.绑定文本输入到Label 2.处理按钮点击事件 3.从网络请求…...
算法思想之前缀和(二)
欢迎拜访:雾里看山-CSDN博客 本篇主题:算法思想之前缀和(二) 发布时间:2025.4.11 隶属专栏:算法 目录 算法介绍核心思想大致步骤 例题和为 K 的子数组题目链接题目描述算法思路代码实现 和可被 K 整除的子数组题目链接题目描述算法…...
C++ - 数据容器之 unordered_map(声明与初始化、插入元素、访问元素、遍历元素、删除元素、查找元素)
一、unordered_map unordered_map 是 C STL 中的一个关联容器,它有如下特点 unordered_map 存储键值对,使用哈希表实现 unordered_map 的每个键在容器中只能出现一次 unordered_map 的存储的键值对是无序的 平均情况下,查找、插入、删除都…...
六、分布式嵌入
六、分布式嵌入 文章目录 六、分布式嵌入前言一、先要配置torch.distributed环境二、Distributed Embeddings2.1 EmbeddingBagCollectionSharder2.2 ShardedEmbeddingBagCollection 三、Planner总结 前言 我们已经使用了TorchRec的主模块:EmbeddedBagCollection。我…...
硬件知识积累 单片机+ 光耦 + 继电器需要注意的地方
1. 电路图 与其数值描述 1.1 单片机引脚信号为 OPtoCoupler_control_4 PC817SB 为 光耦 继电器 SRD-05VDC-SL-A 的线圈电压为 67Ω。 2. 需注意的地方 1. 单片机的推挽输出的电流最大为 25mA 2. 注意光耦的 CTR 参数 3. 注意继电器线圈的 内阻 4. 继电器的开启电压。 因为光耦…...
Dockerfile 学习指南和简单实战
引言 Dockerfile 是一种用于定义 Docker 镜像构建步骤的文本文件。它通过一系列指令描述了如何一步步构建一个镜像,包括安装依赖、设置环境变量、复制文件等。在现实生活中,Dockerfile 的主要用途是帮助开发者快速、一致地构建和部署应用。它确保了应用…...
MCU屏和RGB屏
一、MCU屏 MCU屏:全称为单片机控制屏(Microcontroller Unit Screen),在显示屏背后集成了单片机控制器,因此,MCU屏里面有专用的驱动芯片。驱动芯片如:ILI9488、ILI9341、SSD1963等。驱动芯片里…...
Elasticsearch 向量数据库,原生支持 Google Cloud Vertex AI 平台
作者:来自 Elastic Valerio Arvizzigno Elasticsearch 将作为第一个第三方原生语义对齐引擎,支持 Google Cloud 的 Vertex AI 平台和 Google 的 Gemini 模型。这使得联合用户能够基于企业数据构建完全可定制的生成式 AI 体验,并借助 Elastics…...
蓝桥杯基础数论入门
一.试除法 首先我们要了解,所有大于1的自然数都能进行质因数分解。试除法作用如下: 质数判断 试除法通过验证一个数是否能被小于它的数(一般是用2到用根号x)整除来判断其是否为质数。根据定义,质数只能被1和自身整除…...
