查看: 3568|回复: 1

DDS学习

[复制链接]
  • TA的每日心情
    开心
    2015-7-14 09:10
  • 签到天数: 9 天

    连续签到: 1 天

    [LV.3]偶尔看看II

    发表于 2017-7-26 14:57:32 | 显示全部楼层 |阅读模式
    分享到:

    • 什么是DDS?         DDS是直接数字式频率合成器(Direct Digital Synthesizer)的英文缩写,与传统的频率合成器相比,DDS具有低成本,高分辨率,低功耗,高分辨率,和快速转换时间等优点,广泛应用在电信与电子仪器领域,是实现设备全数字化的一个关键技术。
    • 什么是信号发生器?     波形发生器就是一种数据信号发生器,在调试硬件的时候,常常需要加入一些信号,以观察电路工作是否正常,加入的信号有正玄波,三角波,方波,以及任意波形。
    • 何为调频         调频就是改变单位时间内完成周期性变化的次数。
    • 何为调相        相位对于一个波来说,特定时刻在它循环周期中的位置:一种是否在波峰,波谷或他们之间的某点的标度。相位可调其实就是改变初始相位。
    • 怎么实现任意波形的DDS
    重点理解:
    调频原理
    频率可调的原理分析:
               如何得到我们想要的任意频率的波形发生器呢?   因为事先的波形数据是存在ROM里面的,每给rom一个地址,就可以读出ROM里的相应的数据,rom的深度是事先定好的256,地址范围是0-255。所以DDS就是循环读取ROM里的数据,系统时钟是50MHZ,若每个时钟地址加1,则有输出的信号为50M/256=195.3K。此时的频率就是这么大,但是我们不想要这个频率怎么办?
    观察上述描述,我们看到最后的输出时钟是由采样时钟和地址深度决定的,所以可以通过对这两个地方着手更改,首先先看下采样时钟,原来是每个时钟的作用下,采集数据加1,现在可以通过对时钟计数,然后让地址在两个时钟作用下采集1,这样就可以实现分频的目的。
    说完采样时钟,那么看下地址深度的问题,因为地址深度是由定制ROM时,就已经确认下来的,所以不能直接更改地址深度,但是可通过更改读取ROM的地址,使其只读其中的一半等,也可以达到效果。  有奈奎斯特采样原理我们知道,在做ADDA转换的过程当中,采样频率要大于信号最高频率的两倍,才能保证信号不失真,这个方法说白了其实就是改变采样的点数,然后达到倍频的目的,不过因为这样做,点数采样的比较少,会导致波形失真。
       说完前面两种方法,也只是实现了整数倍频,和分数分频的目的,并不能实现我们所说的任意分频,那么怎么实现任意分频呢,这里就要介绍一种相对简单并且实用的方法。
    首先需要明确的是输出信号的频率计算公式:
    index3.png
    频率控制字fword和幅度控制字pword
    前面介绍的两种方法中,一个是让时钟计数,时钟记多次地址加一下,另一种是地址每次加,但是不是加1 而是2,3,4这样的加,也可以实现分频。不过这两种方法都有各自的坏处,不能实现任意分频,现在我们介绍一种比较简单的调频原理,前面那个公式说了输出信号 = 50M/256。这里的256 = 2^8。所以我们的地址之前定义[7:0]就够了,前面两种都是通过计数的方式实现的调频,现在我们改变下思路,可以通过改变地址位宽的方法,然后读取的时候取数据地址的高八位,是否就可以实现功能。假设我们拓展为32位,最终输出的地址 取高8位。那么输出信号的最低频率是不是 = 50M/2^32 = 0.01164HZ。如果我们想要其他的频率,再在这个基础上乘就行了。怎么乘前面是不是已经讲过了,如果我要得到1K的,1K/0.01164 = 85911,我们让地址计数器每个时钟来了加85911。这样就可以实现比较方便的调频原理。
    调相原理:
       调相相对来说比较简单,无外乎就是改变初始相位就可以了,实现方法就是定义一个调相控制字,当复位赋初值的时候将想要的初始相位赋给地址初值就可以了,实现起来相对简单。
       调相计算公式:
               假设是256个点则有
                                                    地址初值=256*(初始相位/360)
    • 系统框架
    index4.png

    • Rom (单口rom)        Quarters IP核调用
    • Mif文件生成的方法        1.Quarters自带工具生成
                   2.mifmaker 软件生成
                   3.MATLAB mif文件函数
                   4.C语言  mif文件生成
    • 代码分析
    1. module         DDS(
    2.         input        wire    sclk,
    3.         input        wire    rst_n,
    4.         input        wire     [7:0]    odata_1,//sine_wave
    5.         input        wire     [7:0]    odata_2,//square_wave
    6.         input        wire    [1:0]    flag,
    7.         output    wire    [7:0]    addr_num,
    8.         output    reg    [7:0]    o_wave
    9.         );
    10.         
    11. parameter    pword    =0;   

    12.         
    13. reg    [31:0]    cnt;
    14. reg    [1:0]        flag_S;
    15. reg    [1:0]        flag_F;
    16. reg    [31:0]    fword;


    17. always @(posedge sclk    or negedge    rst_n)
    18.     if(!rst_n)
    19.             flag_S    <=0;
    20.     else    if(flag_S==1 && flag[0])
    21.             flag_S    <=0;
    22.     else    if(flag[0])
    23.         begin
    24.             flag_S<=flag_S+1;
    25.         end

    26. always@(posedge    sclk    or negedge    rst_n)
    27.         case(flag_S)
    28.             0:    o_wave    <=    odata_1;
    29.             1:    o_wave    <=    odata_2;
    30.             default:    o_wave    <= o_wave;
    31.         endcase
    32.    
    33.    
    34. always @(posedge sclk    or negedge    rst_n)
    35.     if(!rst_n)
    36.           flag_F    <=0;
    37.     else if(flag_F==1 && flag[1])
    38.         flag_F    <=0;
    39.     else    if(flag[1])
    40.         begin
    41.             flag_F<=flag_F+1;
    42.         end

    43. always@(posedge    sclk    or negedge    rst_n)
    44.         case(flag_F)
    45.             0:    fword    <= 4295533;
    46.             1:  fword <= 8591065;
    47.             2:  fword <= 42955326;
    48.             3:  fword <= 85910653;
    49.         default: fword <= fword;
    50.      endcase   

    51. always@(posedge sclk or negedge rst_n)   
    52. begin                                       
    53.     if(~rst_n)                                
    54.         cnt <= {pword,23'b0};                 
    55.     else if(|flag)                        
    56.         cnt <= {pword,23'b0};                 
    57.     else                                      
    58.         cnt <= cnt + fword;                     
    59. end                                         
    60.                                           
    61. assign addr_num = cnt[31:24];         

    62. endmodule
    复制代码
    2.Modelsim 仿真波形
    index5.png

    本文转自互联网


    回复

    使用道具 举报

    该用户从未签到

    发表于 2019-7-30 20:05:03 | 显示全部楼层
    非常好,语言通俗特别好懂!谢谢楼主
    回复 支持 反对

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

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



    手机版|小黑屋|与非网

    GMT+8, 2024-12-28 16:54 , Processed in 0.139114 second(s), 21 queries , MemCache On.

    ICP经营许可证 苏B2-20140176  苏ICP备14012660号-2   苏州灵动帧格网络科技有限公司 版权所有.

    苏公网安备 32059002001037号

    Powered by Discuz! X3.4

    Copyright © 2001-2024, Tencent Cloud.