线性插值提高DDS相位分辨率

news2024/11/23 21:56:40

  DDS(Direct Digital Synthesizer)即直接数字频率合成技术,主要由正弦查找表与控制器组成,通过控制器给出的相位,在正弦查找表中查找对应的正余弦值并予以输出。通过多个 DDS 信号的组合,可以进一步构建出 AM、FM、PM 等信号发生器。

  关于 DDS 的知识不多赘述,本文主要介绍正弦波生成模块的 FPGA 实现,里面涉及一个在不增加 ROM 容量的情况下,大幅提高相位分辨率的方法(线性插值)。如果需要更高的精度,可以更进一步采用三次样条差值等技术。

生成 ROM 文件(正弦查找表)

  使用 Matlab 生成 .coe 文件(这个是 Xilinx 的 rom 需要的初始化文件,如果是 Altera 的板子,rom 需要用 .mif 文件),代码如下

%--------------生成正弦查找表.coe---------------------
clc,clear,close all

%% 生成 rom 数据
Width=16;
Depth=256;

phi=linspace(0,2*pi,Depth+1);
phi=phi(1:end-1)';

sin_sig=sin(phi);
sin_sig=floor(sin_sig*2^(Width-1)*0.9999); %*0.9999防止出现溢出
sin_sig=sin_sig+2^(Width-1);

plot(sin_sig)

%% 生成.coe文件
filename='.\sin_rom.coe';
fid = fopen(filename,'w');

radix = 16;
fprintf(fid,"memory_initialization_radix=%d;\n",radix); %使用的进制
fprintf(fid,"memory_initialization_vector=");

for i=1:size(sin_sig,1)
    fprintf(fid,"\n%x",sin_sig(i));
end
fprintf(fid,";");

fclose(fid);

正弦查找器

  一般为了节约 FPGA 资源,不会生成太大的 rom,为了保证幅度的精度,一般选取 16bit,而查找表深度一般选择 256,然而这就导致相位分辨率很低,如果直接使用这个 rom 的数据作为正弦信号输出,这个信号将是很不理想的。比如需要的相位分辨率为 T/65536,如果直接相位下取整作为 rom 地址,并输出对应的正弦数据,将会产生如下的误差

在这里插入图片描述

可以看到最大的误差将达到 ± 800 \pm800 ±800,这对于 [ − 32768 ,   32768 ] [-32768,\ 32768] [32768, 32768] 的取值范围来说,相对误差达到了惊人的 2.44 % 2.44\% 2.44%!即使采用改进方案,相位取整采取四舍五入,而不是下取整,误差也仅仅降低一半,仍有 1.22 % 1.22\% 1.22%,在精度要求较高的场所这仍然是不可接受的。

  为提高相位分辨率,一种方法是直接生成更高相位分辨率的正弦查找表,而这将大大增加 FPGA 资源的消耗(想当年我就是用这种方法获取更高分辨率的,结果被资源耗尽的问题搞得焦头烂额(╥﹏╥),往事不堪回首啊 hhhh)。但如果采用两个 256 深度的查找表,一个按给定相位的下取整查找对应正弦信号的值,一个相位上取整查找,然后通过线性插值
y = y 1 + ( y 2 − y 1 ) x − x 1 x 2 − x 1 y=y_1+(y_2-y_1)\frac{x-x_1}{x_2-x_1} y=y1+(y2y1)x2x1xx1
来计算,就可以获得给定相位处的高精度正弦值了。其中 x 1 x_1 x1 是 16bit 输入相位 x x x 对 256 下取整的相位, x 2 x_2 x2 是输入相位 x x x 对 256 上取整的相位, x 2 − x 1 = 256 x_2-x_1=256 x2x1=256,因此下面代码中除 256 就直接做了移位运算(右移 8 位), y 1 y_1 y1 是下取整相位的正弦查找值, y 2 y_2 y2 是上取整相位的正弦查找值,计算结果 y y y 就是线性插值获得的正弦输出。

  采用线性差值的正弦信号发生器代码如下

/* 
 * file			: sin_gen.v
 * author		: 今朝无言
 * date			: 2023-05-16
 * version		: v1.0
 * description	: 根据给定相位输出正弦信号
 */
module sin_gen(
input			clk,

input	[15:0]	phase,		//相位,0~65535对应[0~2pi)
output	[15:0]	sin_out
);

//---------------------正弦查找表-------------------------
wire	[7:0]	addr1;
wire	[7:0]	addr2;
wire	[15:0]	sin_dat1;
wire	[15:0]	sin_dat2;

//sin rom, 16bit, 256 depth
sin_rom sin_rom_inst1(
	.clka	(clk),
	.addra	(addr1),
	.douta	(sin_dat1)
);

sin_rom sin_rom_inst2(
	.clka	(clk),
	.addra	(addr2),
	.douta	(sin_dat2)
);

//-----------线性插值获取更精确的相位分辨率-------------------
assign	addr1	= (phase>>8);
assign	addr2	= (phase>>8)+1;

wire	[15:0]	phase1;
wire	[15:0]	phase2;

assign	phase1	= addr1<<8;
assign	phase2	= addr2<<8;

reg		[15:0]	phase_d0;
reg		[15:0]	phase_d1;	//由于rom数据2拍后才给出,因此phase需要与之同步
reg		[15:0]	phase1_d0;
reg		[15:0]	phase1_d1;

always @(posedge clk) begin
	phase_d0	<= phase;
	phase_d1	<= phase_d0;

	phase1_d0	<= phase1;
	phase1_d1	<= phase1_d0;
end

wire	[31:0]	multi;
assign	multi	= (sin_dat2 > sin_dat1)? 
				(sin_dat2 - sin_dat1)*(phase_d1 - phase1_d1) : 
				(sin_dat1 - sin_dat2)*(phase_d1 - phase1_d1);

assign	sin_out	= (sin_dat2 > sin_dat1)? sin_dat1 + (multi >> 8) : sin_dat1 - (multi >> 8);

endmodule

  对这个模块的输出与对应的正弦函数真值进行比较,误差如下

在这里插入图片描述

可以看到误差急剧缩减到 ± 4 \pm4 ±4 ,相对误差只有 1.22 × 1 0 − 4 1.22\times10^{-4} 1.22×104,大概万分之一。误差相较于相位下取整然后直接查找的方法缩小了 2 个数量级,而资源消耗仅仅增加了一个 16x256 的 rom,相较于 16x65536 rom 的恐怖资源消耗量可谓具有极高的性价比了。

正弦信号发生器

  懒得写了,看以后心情再补上这里。─=≡Σ(((つ•̀ω•́)つ

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/539871.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【源码解析】Disruptor框架的源码解析

Disruptor初始化 初始化Disruptor实例 //单线程模式&#xff0c;获取额外的性能 Disruptor<MessageModel> disruptor new Disruptor<>(factory, bufferSize, executor,ProducerType.SINGLE, new BlockingWaitStrategy());创建RingBuffer实例 Deprecatedpublic D…

Midjourney|文心一格prompt教程[Text Prompt(上篇)]:品牌log、App、徽章、插画、头像场景生成,各种风格选择:科技风、运动风

Midjourney|文心一格prompt教程[Text Prompt&#xff08;上篇&#xff09;]&#xff1a;品牌log、App、徽章、插画、头像场景生成&#xff0c;各种风格选择&#xff1a;科技风、运动风 1.撰写 Text Prompt 注意事项 Midjourney 跟 ChatGPT 在 prompt 的使用上有很多不一样的地…

怎么做好媒体邀约

传媒如春雨&#xff0c;润物细无声&#xff0c;大家好 要做好媒体邀约&#xff0c;以下是一些关键步骤和建议&#xff1a; 1. 制定媒体邀约方案&#xff1a;首先&#xff0c;确定您希望邀约的目标媒体。了解他们的受众、内容定位和报道风格&#xff0c;确保与您的品牌和目标受众…

ChatGPT 的工作原理:深入探究

本文首发于微信公众号&#xff1a;大迁世界, 我的微信&#xff1a;qq449245884&#xff0c;我会第一时间和你分享前端行业趋势&#xff0c;学习途径等等。 更多开源作品请看 GitHub https://github.com/qq449245884/xiaozhi &#xff0c;包含一线大厂面试完整考点、资料以及我的…

opencv实践项目-图片拼接之缝合线算法

目录 1. stitcher_detail执行过程2. 源码3. stitching_detail 程序接口介绍4. 执行5. 结果图 1. stitcher_detail执行过程 stitcher_detail是opencv官网提供的一个用于多福图像拼接的Demo&#xff0c;其主要过程如下&#xff1a; 1.输入待拼接图像集合&#xff1b;2.分别对每幅…

Jetson Nano调试记录:机电设备控制

边缘应用中,机电控制是一项非常重要的能力。 当我们的智能设备在远端环境中,根据所识别的状况变化去执行应对措施,更大程度度地降低对人为操作的依赖,这些都是能产生更大经济效益的应用,包括无人驾驶车、自动机械手臂等等。 实际工业应用场景中的控制元件是非常多样化的,…

惠普暗影精灵5 super 873-068rcn怎样用u盘重装系统win10

当我们的戴尔电脑出现问题的时候&#xff0c;无法进入系统要怎么重装系统win10修复呢?比较常用的就是借助u盘重装系统win10&#xff0c;需要用到装机工具。下面就给大家详细介绍下戴尔电脑怎样用u盘重装系统win10教程。 工具/原料&#xff1a; 系统版本&#xff1a;windows1…

LSTM-理解 Part-3(LSTM Networks)

之前博客中有涉及前两部分的介绍&#xff1a; 第一部分LSTM-理解 Part-1&#xff08;RNN&#xff1a;循环神经网络&#xff09; 第二部分LSTM-理解 Part-2&#xff08;RNN的局限性&#xff09; 这是其中的第三部分&#xff0c;讲解 LSTM Networks。 LSTM Networks 长短期记忆网…

【Python MySQL】零基础也能轻松掌握的学习路线与参考资料

Python是一种广泛使用的编程语言&#xff0c;MySQL是一个流行的关系数据库管理系统。学习Python和MySQL可以帮助开发人员更有效地处理数据&#xff0c;并构建可扩展和强大的Web应用程序。本文将介绍Python MySQL学习路线&#xff0c;参考资料和优秀实践。 Python MySQL学习路线…

美的智家、海尔智家,吹响新一轮AI竞赛号角

ChatGPT大行其道&#xff0c;各行各业迫不及待披上了AI大模型的“盔甲”&#xff0c;有的企业自研AI大模型&#xff0c;有的企业牵手头部科技企业&#xff0c;寻求智能产品价值的最大化&#xff0c;智能家电行业也不例外。 在国内&#xff0c;百度AI大模型文心一言一经推出就吸…

卷绕模型介绍

卷绕模型是收放卷应用的基础知识,这篇博客帮大家整理分析,有关收放卷的其它相关基础知识请参看专栏相关文章。和这篇文章相关联的知识点大家可以参看下面的博客 体积法计算卷径详细介绍 卷径计算详解(通过卷绕的膜长和膜厚进行计算)_RXXW_Dor的博客-CSDN博客有关卷绕+张力控…

LoRA:大模型的低秩自适应微调模型

对于大型模型来说&#xff0c;重新训练所有模型参数的全微调变得不可行。比如GPT-3 175B&#xff0c;模型包含175B个参数吗&#xff0c;无论是微调训练和模型部署&#xff0c;都是不可能的事。所以Microsoft 提出了低秩自适应(Low-Rank Adaptation, LoRA)&#xff0c;它冻结了预…

企业级体验:未来体验管理的价值与趋势

我从事企业级体验相关领域的工作已十六载有余&#xff0c;曾经就职的企业既有阿里巴巴、腾讯这样的互联网“大厂”&#xff0c;也有顺丰、龙湖这样的线下“传统”企业。在这些企业中&#xff0c;我所工作的场景横跨了软件、电商、互联网、物流、零售、地产、金融等诸多业务领域…

11.计算机基础-计算机网络面试题—基础知识

本文目录如下&#xff1a; 计算机基础-计算机网络 面试题一、基础知识简述 TCP 和 UDP 的区别&#xff1f;http 与 https的区别?Session 和 Cookie 有什么区别&#xff1f;详细描述一下 HTTP 访问一个网站的过程&#xff1f;https 是如何实现加密的&#xff1f;URL是什么&…

Linux下网络编程(3)——socket编程实战,如何构建一个服务器和客户端连接

经过前几篇的介绍&#xff0c;本文我们将进行编程实战&#xff0c;实现一个简单地服务器和客户端应用程序。 编写服务器程序 编写服务器应用程序的流程如下&#xff1a; ①、调用 socket()函数打开套接字&#xff0c;得到套接字描述符&#xff1b; ②、调用 bind()函数将套接字…

Deep Supervised Dual Cycle Adversarial Network for Cross-Modal Retrieval 论文阅读笔记

​# 1. 论文信息 论文名称Deep Supervised Dual Cycle Adversarial Network for Cross-Modal Retrieval作者Lei Liao 中山大学会议/出版社IEEE Transactions on Circuits and Systems for Video Technologypdf&#x1f4c4;在线pdf代码&#x1f4bb;无代码 本文是基于公共空间…

mov转换为mp4格式怎么转,多方法教程

mov转换为mp4格式怎么转&#xff1f;如果你连mov都不了解&#xff0c;那就更别说将其进行转换了。其实使用过苹果手机的人应该接触的很多&#xff0c;但是我们时常不关注这个视频格式。MOV是一种音频和视频文件格式&#xff0c;它在苹果手机上使用。它不兼容安卓或Windows电脑&…

cookie、session、JWT(Json Web Token) 的区别?

cookie、session、JWT(Json Web Token) 的区别&#xff1f; 答&#xff1a; 要从http的无状态说起&#xff0c;http是无状态的&#xff0c;也就是如果你第一次访问服务器&#xff0c;之后再次访问的时候&#xff0c;服务器是不会意识到你再次来进行访问的。不想让已经登录的用…

敏捷ACP 常用关键词整理 敏捷ACP 常用知识点整理

敏捷ACP 常用关键词整理 敏捷ACP 常用知识点整理 一、MoSCoW 1、MoSCoW &#xff1a; 读作"莫斯科"&#xff0c;适用于故事优先级的排序&#xff0c;首次出现在 3-13敏捷产品实践&#xff1a;产品待办事项列表的排序 &#xff1b; 基于价值的分析的一种技术 &#…

mac python3.9安装pyqt5、qt5、pyqt5-tools

一 pip安装 转义安装 # 一条代码就可以搞定没错&#xff0c;使用的是Rosetta2 x86_64模式安装的 arch -x86_64 python3 -m pip install PyQt5arch -x86_64 python3 -m pip install pyqt5-tools二 brew安装 arm版 以下pip命令自行更具自己环境选择pip或pip3 在安装pyqt前必须先…