码迷,mamicode.com
首页 > 其他好文 > 详细

DDS---相位累加器、ROM查找表的FPGA实现

时间:2016-04-26 21:39:02      阅读:1064      评论:0      收藏:0      [点我收藏+]

标签:

技术分享

图1 DDS原理框图

首先谈一下DDS(直接数字式频率合成器)的原理,如图1所示。 由相位累加器、ROM查找表、高速DAC、低通滤波器(LPF)组成。 设频率控制字的宽度为 N bits,则频率控制字的取值范围:0~2^N。 相位累加器是一个计数器,宽度一般要超过N+1位(抽样定理),在参考时钟Fref 的上升沿,计数器自增一次,步长为频率控制字对应的值。

相位累加器的输出 作为 R0M查找表的 “地址输入”,ROM查找表中存储了任意波形的 “ 幅值 - 相位 ” 对应表,相位累加器提供相位,ROM查找表根据这个相位输出对应的幅值。 设相位累加器的宽度为M位,即将2*pi 等分成 2^M 份,频率控制字为 K,即累加器步长为 K。则输出频率 Fout = Fref / (2^M) * K。 当K=1时,是最小输出频率,Fout = Fref / (2^M);其他输出频率都是这个频率的整倍数。

后面的高速DA和LPF就不是FPGA所做的事情了,就不赘述了。

下面我们通过VIVADO仿真一个简单的DDS工程:

1 建立一个VIVADO工程

2 设计相位累加器,Verilog HDL代码如下:

module PhaseAdder(
    input clk,
    input rst,
    input [10:0]FreqCtrl,   //频率控制字,相位累加步长
    output [11:0]phase
    );
    
    reg [11:0]phase_reg = 0;
    assign phase = phase_reg;
    always@(posedge rst or posedge clk)
    begin
        if(rst)
            phase_reg <= 12‘d0;
        else
            phase_reg <= phase_reg + FreqCtrl;  //溢出循环
    end
endmodule

说明:clk就是框图的Fref,可以连接FPGA板载晶振,或通过晶振分频后倍频后的时钟

    rst是复位引脚,因为basys3板上的按键接的是下拉电阻,所以这边的复位信号是高电平有效

   FreqCtrl是频率控制字,可以通过MCU提供,在程序中,作为计数器的累加步长。 

  phase是相位累加器的实时输出,作为ROM查找表的地址,因为本工程将正弦信号经4096点抽样,所以相位累加器的地址为12位(2^12 = 4096)

3 设计ROM查找表

通过Matlab将正弦信号作4096点抽样,并生成" .coe "文件(Quartus II是要求“ .mif ”文件,VIVADO是要求" .coe "文件,但最终还是要转换成“ .mif ”文件),

用于初始化ROM。

Matlab代码如下:


n = 0:4095 ;
yn = sin(2*pi/4096*n) ;


yn = round((yn+1)*2047); 


plot(n,yn);


fid = fopen(‘rom.coe‘,‘wt‘);
fprintf(fid,‘memory_initialization_radix = 10;\nmemory_initialization_vector = ‘);


for i = 1 : 4096
    if mod(i-1,16) == 0 
        fprintf(fid,‘\n‘);
    end
    fprintf(fid,‘%4d,‘,yn(i));
end

 生成COE文件之后,在VIVADO软件中添加IP核,如下图,双击Distributed Memory Generator


技术分享


出现下列界面,设置ROM的深度(抽样点数)和数据的宽度(根据高速DA的数据口宽度而定!!!)


技术分享


然后点击第3个选项卡(RST & Initialization),添加刚才由matlab生成的COE文件,Radix可以选择 2 , 10 , 16,代表COE文件中的数据进制。设置完成后点击OK即可。


技术分享


至此,我们已经成功 生成 并 初始化 了 ROM查找表,其vhd端口声明如下。我们可以在顶层文件中直接例化这个ROM查找表。

技术分享


4 设计顶层文件,串接相位累加器,代码如下:



module DDS(
   input clk,
   input rst,
   input [10:0]FreqCtrl,
   output [11:0]waveform
    );
    
    wire [11:0]phase;
    PhaseAdder u_PhaseAdder
    (
        .clk        (clk),
        .rst        (rst),
        .FreqCtrl   (FreqCtrl),
        .phase      (phase)
    );
    DDS_ROM u_DDS_ROM
    (
        .a      (phase[11:0]),
        .spo    (waveform)
    );
endmodule

至此,我们整个的工程设计完毕,Sources结构图如下图所示:

技术分享


RTL Analysis 如下:


技术分享


5 添加仿真文件,编写testbench,代码如下:



module simu(


    );
    
    reg clk = 0;
    always #5 clk <= ~clk;  //100 MHz
    
    reg rst = 0;
    
    reg [10:0]FreqCtrl =
1;
    wire [11:0]waveform;
    
    DDS u_DDS
    (
        .clk        (clk),
        .rst        (rst),
        .FreqCtrl   (FreqCtrl),
        .waveform   (waveform)
    );
    
endmodule


点击 Run Simulation 观察波形图:可见频率控制字FreqCtrl = 1时,在40960ns中输出 1个 正弦周期。


技术分享


修改频率控制字FreqCtrl = 2,重新仿真,如下图:可见频率控制字FreqCtrl = 2时,在40960ns中输出 2个 正弦周期。

技术分享





实验完毕!谢谢阅读!

DDS---相位累加器、ROM查找表的FPGA实现

标签:

原文地址:http://blog.csdn.net/u011964923/article/details/51232670

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!