打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
基于FPGA的DDS 信号发生器(三)

控制正弦波的频率和相位(频率控制字+相位控制字)

  • 1 DDS原理
    • 1.1 书上的解释
    • 1.2 自己的理解
  • 2 DDS IP的参数设置
  • 3 源码
    • 3.1 顶层文件
    • 3.2 频率控制字模块
    • 3.3 相位控制字模块
    • 3.4 testbench文件
  • 4 结果

1 DDS原理

1.1 书上的解释

DDS(Direct Digital Synthesizer)技术是一种全新的频率合成方法,是从相位概念出发直接合成所需波形的一种频率合成技术,通过控制相位的变化速度,直接产生各种不同频率、不同波形信号的一种频率合成方法。


系统的核心是相位累加器,其内容会在每个时钟周期(system clock)更新。相位累加器每次更新时,存储在Δ相位寄存器中的数字字M就会累加至相位寄存器中的数字。假设Δ相位寄存器中的数字为00…01(即M=1),相位累加器中的初始内容为00…00。相位累加器每个时钟周期都会按00…01(M=1)更新。如果累加器为32位宽,则在相位累加器返回至00…00前需要2^32(超过40亿)个时钟周期,周期会不断重复。

相位累加器的截断输出用作正弦(或余弦)查找表的地址。查找表中的每个地址均对应正弦
波的从0°到360°的一个相位点。查找表包括一个完整正弦波周期的相应数字幅度信息。
(实际上,只需要90°的数据,因为两个MSB中包含了正交数据)。因此,查找表可将相位
累加器的相位信息映射至数字幅度字,进而驱动DAC。图3用图形化的“相位轮”显示了这
一情况。
考虑n = 32,M = 1的情况。相位累加器会逐步执行2^ 32 (2^n/M)个可能的输出中的每一个,直至溢出并重新开始。相应的输出正弦波频率等于输入时钟频率 2 ^ 32分频。若M=2,相位累加器寄存器就会以两倍的速度“滚动”计算,输出频率也会增加一倍。以上内容可总结如下:

1.2 自己的理解

DDS系统主要由相位累加器、波形存储器、数模(D/A)转换器和低通滤波器等四个大的结构组成,其结构框图如下图所示。


参考时钟:
图中,参考频率f_clk为固定值,一般我们选择系统时钟(system clock),这里设置的是100MHz。
频率控制字:
用来调整输出信号的频率。如何根据参考频率得到输出频率,DDS IP的官方文档给出了相应公式。


相位控制字:

相位累加器:
由N位加法器与N位累加寄存器构成,它根据频率控制字k,完成相位值的累加,并将此累加值输入到波形存储器中。
波形存储器:
将相位累积器的值作为当地址,查找与相位值对应的信号数据,输出到D/A转换器。
D/A转换器:
将波形存储器输出的数字量转换为与之对应的模拟量。
低通滤波器:
由于D/A转换器存在量化误差,输出波形中存在混叠,需要在输出端使用低通滤波器进行滤波,提高信号的输出性能。

2 DDS IP的参数设置


需要注意的是,上面的频率分辨率(frequency resolution)的值是算出来的,这个值必须和summer的频率分辨率保持一致。100M/(2^20)=95.36743




3 源码

程序结构

3.1 顶层文件

`timescale 1ns / 1ps


module top(
    input           sys_clk         ,// 系统时钟
    input           rst_n           ,// 系统复位
    input  [1:0]    key_PINC        ,// 频率控制字对应的按键
    input  [1:0]    key_POFF         // 相位控制字对应的按键
    );
 
 

 //-----------频率控制字模块
wire  [23:0]   PINC ;  //频率字
Fword_set Fword_set_inst(
        //input
        .clk        (sys_clk            ),
        .rst_n      (rst_n              ),
        .key_PINC   (key_PINC           ),
        //output
        .PINC       (PINC               )
        );



 //-----------相位控制字模块
 wire  [23:0]   POFF ;  //相位字
POFF_set POFF_set_inst(
    //input
    .clk        (sys_clk   )    ,
    .rst_n      (rst_n     )    ,
    .key_POFF   (key_POFF  )    ,
    //output
    .POFF       (POFF      )
    );





 //-------------DDS模块
//input
wire [0:0]   fre_ctrl_word_en  ;    

//output
wire [0:0]   m_axis_data_tvalid    ;
wire [47:0]  m_axis_data_tdata     ;
wire [0:0]   m_axis_phase_tvalid   ;
wire [23:0]  m_axis_phase_tdata    ;

assign fre_ctrl_word_en=1'b1;

dds_sin dds_sin_inst (
  .aclk                 (sys_clk                ),    // input wire aclk
  .s_axis_config_tvalid (fre_ctrl_word_en       ),    // input wire s_axis_config_tvalid
  .s_axis_config_tdata  ({POFF,PINC}           ),    // input wire [47 : 0] s_axis_config_tdata
 
  .m_axis_data_tvalid   (m_axis_data_tvalid     ),    // output wire m_axis_data_tvalid
  .m_axis_data_tdata    (m_axis_data_tdata      ),    // output wire [47 : 0] m_axis_data_tdata
  .m_axis_phase_tvalid  (m_axis_phase_tvalid    ),    // output wire m_axis_phase_tvalid
  .m_axis_phase_tdata   (m_axis_phase_tdata     )     // output wire [23 : 0] m_axis_phase_tdata
); 



    
      
endmodule

3.2 频率控制字模块

`timescale 1ns / 1ps
//
// 通过按键来选择对应的频率控制字,进而选择对应的信号频率
//


module Fword_set(
    input               clk         ,
    input               rst_n       ,
    input  [1:0]        key_PINC    ,
    
    output reg [23:0]   PINC
    );
    
    
//always@(posedge clk or negedge rst_n)
//begin
//    if(!rst_n)
//        key_sel <= 4'd0;
//    else
//        key_sel <= key_sel;
//end
   
   
//  The output frequency(f_out ) , of the DDS waveform is a function of the system clock frequency(f_clk ) .
//  the phase width, that is, number of bits (B )  in the phase accumulator 
//  and the phase increment value (deta_theta) . 
//  The output frequency in Hertz is defined by:f_out=f_clk*deta_theta/(2^B)
//  fre_ctrl_word是如何确定的?
// 根据IP核的summery, phase width=20bits   Frequency per channel=100MHz
// 输出频率的计算公式f_out=f_clk*deta_theta/(2^B)=100M* 104857/(2^20 )= 10M             
always@(*)
begin
    case(key_PINC)
        0:  PINC <= 'h28f5;     //1Mhz  10485  每次相位增加的值  deta_theta
        1:  PINC <= 'h51eb;     //2Mhz  20971
        2:  PINC <= 'ha3d7;     //4Mhz  41943
        3:  PINC <= 'h19999;    //10Mhz  104857
    endcase
end

 
endmodule

3.3 相位控制字模块

`timescale 1ns / 1ps
//
// 通过按键来选择对应的相位控制字,进而选择对应的信号初始相位
/


module POFF_set(
    input               clk         ,
    input               rst_n       ,
    input  [1:0]        key_POFF    ,
    
    output [23:0]       POFF
    );
    
    
//always@(posedge clk or negedge rst_n)
//begin
//    if(!rst_n)
//        key_sel <= 4'd0;
//    else
//        key_sel <= key_sel;
//end
   
   

// 根据IP核的summery, phase_width=20bits   Frequency per channel=100MHz
// 输出相位的计算公式:POFF=phase*phase_modulus/360
// phase:想要输出的相位,输入0~360即可
// phase_modulus:相位系数为2^phase_width-1=2^20-1,
// phase_width即相位位宽,在生成IP的summary可以查看
reg  [8:0]   phase;    //0-360   
   
always@(*)
begin
    case(key_POFF)
        0:  phase <= 'h0;         //0
        1:  phase <= 'h5a;        //90
        2:  phase <= 'hb4;        //180
        3:  phase <= 'h10e;       //270
    endcase
end

assign POFF=phase*1048575/360;
 
 
endmodule

3.4 testbench文件

`timescale 1ns / 1ps


module sim_top;

    reg         sys_clk ;
    reg         rst_n   ;
    reg [1:0]   key_PINC; 
    reg [1:0]   key_POFF; 

    //例化源文件
    top top_inst(
       .sys_clk      (sys_clk      ),
       .rst_n        (rst_n        ),
       .key_PINC     (key_PINC     ),
       .key_POFF     (key_POFF     )
        );
        
             
    initial
        begin
            //初始化
            sys_clk=0;
            rst_n=0;
            key_PINC=2'd0;
            key_POFF=2'd0;  //30
            
            
            
            #100
            rst_n=1;
            key_PINC=0;  //1Mhz  10485  每次相位增加的值  deta_theta
            #4000
            key_PINC=1;  //2Mhz  20971
            #4000
            key_PINC=2;  //4Mhz  41943
            #4000
            key_PINC=3;   //10Mhz  104857
            
            #4000
            key_POFF=1;  //60
            #4000
            key_POFF=2;  //90
            #4000
            key_POFF=3;   //180
        end
        
        
        // create clock;
        always #5 sys_clk=~sys_clk;//每次间隔5ns,取一次反,也就是周期为10ns,所以频率为100MHz



endmodule

4 结果


本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
第九章 为所欲为——教你什么才是真正的任意分频
基于FPGA的DDS波形发生器
【精品博文】详细解析基于FPGA(DDS)的正弦波发生器
杨老师:今天,必须要和大家谈谈DDS
浅谈DDS IP核之频率控制字与相位控制字
如何在FPGA中构建数控振荡器 (NCO)
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服