集成电路技术分享

 找回密码
 我要注册

QQ登录

只需一步,快速开始

搜索
查看: 12327|回复: 16

雾盈FPGA笔记之(四):基于FPGA实现频率相位可调的DDS波形发生器(Verilog)

[复制链接]
雾盈 发表于 2016-8-2 10:58:08 | 显示全部楼层 |阅读模式
本帖最后由 雾盈 于 2016-8-28 13:39 编辑


基于FPGA实现频率相位可调的DDS波形发生器(Verilog)
                                                                                                                   雾盈 2016-08-02


雾盈FPGA笔记汇总目录

一、原理
让我们先理解以下几个概念:
1)何为DDS?
   DDS是直接数字式频率合成器(Direct Digital Synthesizer)的英文缩写。与传统的频率合成器相比,DDS具有低成本、低功耗、高分辨率和快速转换时间等优点,广泛使用在电信与电子仪器领域,是实现设备全数字化的一个关键技术。
2)什么是波形发生器?
    波形发生器是一种数据信号发生器,在调试硬件时,常常需要加入一些信号,以观察电路工作是否正常。加入的信号有:正弦波、三角波、方波和任意波形等等。
3)什么是相位可调?
    相位(phase)是对于一个波,特定的时刻在它循环周期中的位置:一种它是否在波峰、波谷或它们之间的某点的标度。相位描述信号波形变化的度量,通常以度(角度)作为单位,也称作相角。 当信号波形以周期的方式变化,波形循环一周即为360°。那么相位可调也可以简单的理解为:改变初始相位。

4)什么是频率可调?
频率,是单位时间内完成周期性变化的次数,是描述周期运动频繁程度的量,常用符号f或ν表示,单位为秒分之一,符号为s-1。频率可调也就是改变单位时间内完成周期性变化的次数。


二、系统框架
理解了几个概念后,我们来看一下框图,对系统整体有个初步的了解


   由框图可以看出,这个系统分为两个模块,dds_ctrl控制地址输出模块和存储有波形数据mif文件的rom(调用IP核)。

三、载有波形数据的mif文件制作
首先,我们先来制作载有波形数据的mif文件,这里会使用一个小软件———mifmake,是专门用来生成mif文件的,软件压缩包我会挂在后面。

打开mifmake ,点击全局参数,如图:

弹出全局参数设置窗口,如图:

选择想要的长度和宽度,格式选择无符号10进制。

点击设定波形,选择想要生成的波形,我这里选择正弦波,

出现波形后,点击保存。

至此,这样就生成了一个载有正弦波数据的mif文件,打开mif文件,里面是这样的,如下图:

这时,这个mif文件还不能直接被使用,我们先通过quartus新建一个空白mif文件,随意输入数据后保存,然后打开这个新的mif文件。
把之前我们生成的载有波形数据mif的内容,全选复制粘贴替换掉新mif文件相应的部分。如图部分:

最后,在调用IP核ROM的使用,将这个mif文件包含进去。一个载有正弦波数据的ROM存储器就制作完了。




四、相位可调,频率可调
相位可调实际是改变波形的初相,也就是改变复位时的初始地址。
if(!rst_n)
       begin
          cnt_addr <= 1'b0;
          addr_out <= PWORD;
       end
这里,改变PWORD的值就能改变初相。PWORD的值在0—255之间。

频率可调一个完整周期的正弦波形里系统时钟计数了256次,可计算地址输出频率公式:

如果想要改变输出的频率,我们可以选择改变时钟或者输出点的个数!显而易见,我们的设计不能够时时刻刻去改变时钟的频率,那么想要输出别的频率,我们只能改变输出的点的个数,也就是改变有效地址的数量。
我们可以定义一个位宽为N(N>8)的地址计数器,让地址计数器每次增加一定的值,然后把高八位当作有效地址输送给rom,这样的话,就实现了降低地址改变的频率,进而达到降低输出波形的频率。
[table]

我们使用的是50MHz的晶振,周期为20ns,假设fword为1,地址计数器的输出为N位的,那么每20ns,地址计数器加1,要加到2^N,需要20ns x 2^N 时间,这个时间就是输出.一个完整信号的周期,那么我们可以知道,输出信号的频率为 Fout = Fclk/2^N,其中,Fclk为我们的晶振频率,再假如,fword= B的时候,地址间隔提高 B 倍,因此计满一个周期的时间缩小了 B 倍,频率提高的 B 倍。综上所述,我们得出了输出信号的频率计算公式:

由此公式,可以计算出任意频率值所对应的B值。其实,不想费心理解,只要熟记这个公式就可以了。
   再然后,我们取地址计数器的前八位,相当于把一个波形的相位分成了256个点,每个点对应一个数据,正好和我们的波形数据点的个数是一样的。

仿真波形如下图:


经测试得输出波形频率确为5KHZ。
初相地址为128。

附:源代码
  1. module        dds_ctrl(
  2.                                 // system signal
  3.                                  input                         clk,
  4.                                  input                        rst_n,
  5.                                 // 输出地址                                                  
  6.                                  output        reg [7:0]   addr_out
  7. );

  8. /*=========================================================================================================
  9. **************************     Define parameter and internal signals                 *********************************
  10. =========================================================================================================*/

  11. parameter PWORD = 8'd128;         // 可调相位初值
  12. parameter FWORD = 20'd105; // B=21 可调频率控制字
  13. parameter CNT_MAX = 20'hf_ffff;

  14. reg        [19:0] cnt_addr; // 地址计数器  fout = B * ( fclk / 2^N)  N=20 目标频率fout=5000hz 得B=21

  15. /*=========================================================================================================
  16. **************************                         Main                         code                 *********************************
  17. =========================================================================================================*/

  18. // 地址计数器
  19. always @ (posedge clk or negedge rst_n)
  20. begin
  21.      if(!rst_n)
  22.         begin
  23.                    cnt_addr <= 1'b0;
  24.                    addr_out <= PWORD;
  25.         end
  26.      else  begin
  27.            if( cnt_addr < CNT_MAX )  
  28.                         begin
  29.                           cnt_addr <= cnt_addr + FWORD;// 改变频率控制字来改变计数器达到最大值的时间,从而改变输出波形的频率
  30.                           addr_out <= cnt_addr[19:12];         // 让输出的地址取地址计数器的高八位,刚好256个点
  31.                         end
  32.                    else begin
  33.                           cnt_addr <= 1'b0;
  34.                           addr_out <= PWORD;               
  35.                                 end
  36.              end
  37. end

  38. endmodule       
复制代码

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?我要注册

x
 楼主| 雾盈 发表于 2016-8-2 11:19:31 | 显示全部楼层
第二第三有空再发
芙蓉王 发表于 2016-8-2 17:49:58 | 显示全部楼层
               很棒
chenchunqi 发表于 2016-8-3 20:26:52 | 显示全部楼层
那个软件压缩包呢?
 楼主| 雾盈 发表于 2016-8-4 11:04:57 | 显示全部楼层
chenchunqi 发表于 2016-8-3 20:26
那个软件压缩包呢?

贴出来了,帖子后面
chenchunqi 发表于 2016-8-4 13:53:50 | 显示全部楼层
非常感谢,支持你多写一点这些东西对于初学者很有帮助,
zhiweiqiang33 发表于 2016-8-10 17:48:05 | 显示全部楼层
学习了 资料写的很基础很全面 基础入门资料 谢谢
Esmiamor 发表于 2016-8-17 16:40:07 | 显示全部楼层
                   不错。
辉煌 发表于 2016-8-21 11:39:05 | 显示全部楼层
支持                                
您需要登录后才可以回帖 登录 | 我要注册

本版积分规则

关闭

站长推荐上一条 /1 下一条

QQ|小黑屋|手机版|Archiver|fpga论坛|fpga设计论坛 ( 京ICP备20003123号-1 )

GMT+8, 2024-12-23 23:33 , Processed in 0.075308 second(s), 21 queries .

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表