最近在学习基于FPGA的DDS设计,借此机会把学习过程记录下来,当作自己的学习笔记也希望能够帮助到学习DDS的小伙伴。

  DDS(Direct Digital Synthesizer)直接数字合成器,这是直译过来的名字。设计人员一般把它叫做信号发生器,用它来产生一些数字意义上的波形。它的意义还是挺大的,例如我们学习滤波器,就需要一个高低频率叠加的波形,现时生活中到处都是,可以在设计中,怎么能做出这样的波形呢?学习各种载波调制,需要将信息加载到载波上,而载波也一般都是一定频率的正弦波。DDS就是能够产生这种波形,对于学习数字信号处理以及信号调制解调等有很大的作用。

  FPGA是数字电路,怎么产生模拟的波形呢?如果单纯的使用FPGA是无论如何也产生不了连续不断的波形,一般都是使用FPGA产生数字信号,再利用DAC(Digital-to-Analog Converter)转化成为模拟的波形(如图1)。DAC芯片是一堆模拟电路的东西了,如果感兴趣的小伙伴可以在自己学习一下数字信号转化为模拟信号的过程。  

图1

  FPGA是数字信号,通过DAC转化为模拟值,笔者在进行学习的时候一直有个疑问:既然FPGA是数字信号,那么也就只能输出数字信号,输出相邻的两个点中间一定是有一定距离的,输出的模拟波形应该像楼梯一样(有一定的幅值跳跃),而不是连续变化的,像这种情况下还是我们还可以用吗?答案是肯定的,如果“楼梯”的高度跳跃很小,并且在一个周期中有很多小的跳跃,那么就是可以用的。其实微积分的概念和这个道理应该差不多就是用无限多的矩形来近似曲线(如图2)。

图2

所以在设计时,只要将波形的一个周期(周期波形)中分成N段输出就可以了。

  DDS的实现一般都是由频率控制器、相位累加器和波形存储器构成(如图3)。

图3

  刚刚开始的时候接触到这个信息,笔者也不太理解,经过一段的时间思考,大概明白了其中的设计原理。我们直接从最终的输出开始分析,要输出的一个波形(数字意义上),例如正弦波。那么怎么输出呢,可以给出一个公式sin(2*pi*n/256),将n从0增长到255,就可以输出一个波形。如果这么写的话,就已经把一个周期分成了256份,也可以分成任意份,为了方便数字电路设计,一般都是2的整数次幂份。以下分析都当作一个周期分为256份。n等于一个数值就会输出一个值,把n所对应的位置看作是相位。例如n等于64时,输出的值正好对应于相位pi/2时。在FPGA中去计算sin,一般都是利用查表法,也就是说将一个周期分为N份,当输入的值比较接近与某一个相位时,就把这个相位点的值输出。那其实也就是把波形等分多份,存储在存储器中,而此时存储器就叫做波形存储器。存储器的输出是按照输入地址来决定的,如果想要输出一个完整的不断的波形,就需要地址从最小到最大不变循环,而存储器就会不断的输出波形。地址从最小到最大的累加,就被成为相位累加器。如果相位累加器1S从最小到最大循环了1000次,那么输出的波形的频率就为1KHz。故而相位累加器累加的速度决定输出波形的频率,而累加速度是由外部控制器来决定,所以此控制器被称作频率控制器。

  原理就是上述的那样,下面可以考虑如何来实现上述的过程。

  在设计中,笔者采用INTEL FPGA来实现,故此采用Quartus Prime 18。首先制作波形存储器,在FPGA中有很多存储器资源可以来用,在此选择ROM来当作存储器。利用ROM当存储需要制作初始化文件.mif或者.hex,这两种都可以,在这里采用.mif文件。

.mif在Quartus 中显示为一个一个小区域(如图4),但是其实就是一种文件格式(如图5)。

  

图4

图5

  

  利用某些计算工具将数值计算出来,然后填入表格中,这种速度太慢,也太麻烦。我们一般采用下面所述的两种方法:

利用mifmaker软件生成(QQ群:173560979群文件中),此软件用起来比较简单。只需要简单的设置“设定波形”即可。在设定成功后,点击“文件->保存”即可生成对应的.mif文件(如图6)。

图6

  

  另外一种方法就是利用matlab实现,此方法要求设计者要有一定的matlab基础。源码如下:

 clear;
clc; width = ;
depth = ; file_handle = fopen('sin.mif','w+');
fprintf(file_handle,'--Created by Author xxx\r\n');
fprintf(file_handle,'WIDTH = %d;\r\n',width);
fprintf(file_handle,'DEPTH = %d;\r\n',depth);
fprintf(file_handle,'ADDRESS_RADIX = HEX;\r\n');
fprintf(file_handle,'DATA_RADIX = HEX;\r\n');
fprintf(file_handle,'CONTENT BEGIN\r\n');
for i = : depth-
fprintf(file_handle,'%4x : %4x ; \r\n',i,floor((0.5+0.5*sin(*pi*i/depth) ) *(^width - 1)));
end
fprintf(file_handle,'END;\r\n');
fclose(file_handle);

  产生了.mif后,就可以加载到ROM中。在quartus工程中,采用50MHz的时钟来进行驱动整个设计,让rom的地址每个时钟周期增加1。经过仿真可以得到正弦波(如图7)。

图7

  产生了正弦波,在设置modelsim时,因为波形是按照无符号生成的数据,所以在设置成为模拟之前要先把进制改为无符号类型。即可产生图7波形。经过使用modelsim工具测试,产生的波形的频率为195.313KHz。我们自己也算以下:系统的驱动时钟为50MHz,一个周期为20ns,256个周期输出一个完整的波形。所以波形的周期为256x20ns=5120ns,经过计算频率为195.3125KHz,与上述使用modelsim工具测试结果一直,只是modelsim测试保留了频率的两位小数而已。

  相位累加器每次累加1,产生的波形的频率为195.313KHz,那么只要改变每次累加的数字就可以得到其他频率。如果每次增加的是整数比较好办,那如果每次增加的是带有小数呢?又该如何实现呢?

  笔者水平有限,如有不妥之处,恳请大佬指出。

  欢迎加好友探讨QQ:746833924,QQ群:173560979。

基于FPGA的DDS设计(一)的更多相关文章

  1. 基于FPGA的DDS设计(二)

    在DDS设计中,如果相位累加器每个时钟周期累加1,就会输出频率为195.313KHz的波形.如果每个时钟周期累加2,就会输出频率为2*195.313KHz的波形·······,如果每两个时钟周期累加1 ...

  2. 基于FPGA的DDS任意波形发生器设计

    一.简介       DDS技术最初是作为频率合成技术提出的,由于其易于控制,相位连续,输出频率稳定度高,分辨率高, 频率转换速度快等优点,现在被广泛应用于任意波形发生器(AWG).基于DDS技术的任 ...

  3. 基于FPGA(DDS)的正弦波发生器

    记录背景:昨晚快下班时,与同事rk聊起怎么用FPGA实现正弦波的输出.我第一反应是利用高频的PWM波去滤波,但感觉这样的波形精度肯定很差:后来想起之前由看过怎么用FPGA产生正弦波的技术,但怎么都想不 ...

  4. 38.基于FPGA的FIR设计二

    利用fdatool工具生成的滤波器系数与用代码生成的系数不一致,在网上查询得知,fdatool生成的滤波器系数是有符号小数,而且是浮点型,而代码生成的滤波器系数是定点型有符号数,故不一样. 浮点型数据 ...

  5. 优化基于FPGA的深度卷积神经网络的加速器设计

    英文论文链接:http://cadlab.cs.ucla.edu/~cong/slides/fpga2015_chen.pdf 翻译:卜居 转载请注明出处:http://blog.csdn.net/k ...

  6. 自己动手写CPU(基于FPGA与Verilog)

    大三上学期开展了数字系统设计的课程,下学期便要求自己写一个单周期CPU和一个多周期CPU,既然要学,就记录一下学习的过程. CPU--中央处理器,顾名思义,是计算机中最重要的一部分,功能就是周而复始地 ...

  7. 基于FPGA的XPT2046触摸控制器设计

    基于FPGA的XPT2046触摸控制器设计 小梅哥编写,未经许可,文章内容和所涉及代码不得用于其他商业销售的板卡 本实例所涉及代码均可通过向 xiaomeige_fpga@foxmail.com  发 ...

  8. 基于FPGA的HDMI显示设计(三)

    上一篇:基于FPGA的VGA显示设计(二) 10月10日 ~ 20日期间实习,令我万万没想到的是实习题目是 “便携式高清电视显示屏测试系统原型设计” 也就是 “基于FPGA的视频显示”. 实习要求用 ...

  9. 基于FPGA的VGA显示设计(二)

    上一篇:基于FPGA的VGA显示设计(一)     参照 CrazyBingo 的 基于FPGA的VGA可移植模块终极设计代码  的工程代码风格,模块化处理了上一篇的代码,并增加了一点其它图形. 顶层 ...

随机推荐

  1. STL标签与EL表达式之间的微妙关系

    很高兴,今天能和大家分享刚学的一些新知识.我们在java开发过程中经常会在jsp中嵌入一些java代码,比如<%=request.getParameter("id")%> ...

  2. 团队开发中,eclipse中安装jre

    团队合作中配置jre时,jre名称应该保持一致,否则不要提交.classpath文件 window-preferences     团队合作中,JRE name一定要一致!

  3. 心情烦闷annoying,贴几个图!唉!annoying

    nothing could be more annoying!!!!! lost!failed!

  4. 解决qpidd服务安装不上的问题

    前几天对一个文件夹命名,忘记了qpidd的路径在这个文件夹的下面,导致后来qpidd用不了. 并且有打开计算机-管理-服务时,看到Advanced MessageQueuing Protocol 未启 ...

  5. Array对象常用方法

    不改变原数组: 1.concat()  连接两个或多个数组 不改变原数组 返回被连接数组的一个副本 2.join()  把数组中所有元素放入一个字符串 不改变原数组 返回字符串 3.slice()   ...

  6. Substring Search

    查找子字符串 Introduction 在长度为 N 的文本里寻找长度为 M 的模式(子串),典型情况是 N >> M. 这个应用就很广泛啦,在文本中寻找特定的模式(子串)是很常见的需求. ...

  7. MySQL知识总结(三)存储过程

    1. 创建存储过程 1.1 无参数存储过程 CREATE PROCEDURE bruce_procedure () BEGIN --1.声明变量 --2.执行业务逻辑 END 1.2 有参数的存储过程 ...

  8. Maven实战(八)pom.xml简介

    目录 pom作为项目对象模型.通过xml表示maven项目,使用pom.xml来实现.主要描述了项目:包括配置文件.开发者需要遵循的规则.缺陷管理系统.组织和licenses.项目的url.项目的依赖 ...

  9. screen 命令基本操作教程

    sreen 命令提供的基本功能与 tmux 较为相似( 关于 tmux 基本操作可参见笔者的博文 终端复用工具 tmux 基本操作教程 ).screen 命令以会话( session )为基础为用户提 ...

  10. P4906 小奔关闹钟

    题目背景 由于今天是星期一,闹钟准时响了,由于小奔太困了,所以她想关停闹钟. 题目描述 可是,他的闹钟电路太复杂了,有很多个开关,每个开关都连着其他开关,其他开关又连着更多的开关,当且仅当所有开关都关 ...