最近在学习基于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. Fatal error: Can't use function return value in write context

    这个的出错原因很简单,先贴出错代码: <?php $contact = array("id"=>1, "姓名"=>"老高" ...

  2. Oracle 启用归档

    [applprod@erp10 ~]$ watch ps -fu applprod[applprod@erp10 ~]$ kill -9 82902 84923 [applprod@erp10 ~]$ ...

  3. Java中对文件的序列化和反序列化

    public class ObjectSaver { public static void main(String[] args) throws Exception { /*其中的 D:\\objec ...

  4. Django 补充

    在Django项目的外面操作这个Django内部的models: 当你创建Django项目的时候你在用的时候,你是在这个Django项目中使用的  那么你怎么在你的这个Django项目的外面使用这个D ...

  5. 编写带有点击特效的UIButton

    编写带有点击特效的UIButton 效果: 源码: // // ViewController.m // Button // // Created by XianMingYou on 15/1/18. ...

  6. QuickBI助你成为分析师-数据建模(二)

    摘要: 数据集编辑功能界面介绍以及常见问题总结. 在数据集编辑界面可以进行数据建模来更好的展示数据,创建数据集默认将数值类型字段作为度量,日期.字符串等类型作为维度,度量可以根据维度分组展示.下面来介 ...

  7. 应用程序-特定 权限设置并未向在应用程序容器 不可用 SID (不可用)中运行的地址 LocalHost (使用 LRPC) 中的用户

    这是安装biztalk server 2013出现的问题,很多天了没解决,下边这个解决办法也搜到过类似的,但上次实验时出现设置组件权限时发现都是按钮都是灰的,无法操作. 这次设置好了.谢谢ibg. 文 ...

  8. (1)String类 (2)StringBuilder类和StringBuffer类 (3)日期相关的类

    1.String类(重中之重)1.1 常用的方法(练熟.记住)(1)常用的构造方法 String() - 使用无参的方式构造空字符串对象. String(byte[] bytes) - 根据参数指定的 ...

  9. 3-urllib的post请求方式

    在urllib 中,要进行post请求时,需传入相应的data值,这里通过http://www.iqianyue.com/mypost这个网站进行测试. 案例代码如下: #post 请求 import ...

  10. mybatis中使用in查询时的注意事项

    1. 当查询的参数只有一个时 findByIds(List<Long> ids)  1.a 如果参数的类型是List, 则在使用时,collection属性要必须指定为 list < ...