• 基于DDS的任意波形发生器


    实验原理

    DDS的原理

    DDS(Direct Digital Frequency Synthesizer)直接数字频率合成器,也可叫DDFS。

    • DDS是从相位的概念直接合成所需波形的一种频率合成技术。

    不仅可以产生不同频率的正弦波,而且可以控制波形的初始相位。

    DDS原理框图

    整体框架及其说明

        

    框架说明:该模块的主要功能为产生任意信号,这里的任意信号为:正弦波、三角波、方波、锯齿波这四种波形。整个工程主要分为五个模块:按键消抖、按键编码、DDS信号发生器(在做这个实验前一定要先把DDS的原理弄懂!!!)DAC TLC5615驱动、低通滤波器(硬件板上已经有了)。

    按键消抖模块:由于需要控制波形、幅值、频率、相位三个参数,所以该模块需要三个按键,由于按键为机械按键,在按下的时候会产生抖动,为了达到控制比较稳定,在按键的输入端我们采用软件对按键进行消抖,这里采用的消抖方法为状态机消抖,具体的过程可以看教程的按键消抖那个章节。

    /********************************版权声明**************************************

    ** 大西瓜团队

    **

    **----------------------------文件信息--------------------------

    ** 文件名称: key.v

    ** 创建日期:

    ** 功能描述:按键消抖

    ** 硬件平台:大西瓜第三代开发板,http://daxiguafpga.taobao.com

    ** 版权声明:本代码属个人知识产权,本代码仅供交流学习.

    **---------------------------修改文件的相关信息----------------

    ** 修改人:

    ** 修改日期:    

    ** 修改内容:

    *******************************************************************************/

    module key(clk,key,key_out);

    input clk,key;//时钟输入,按键输入

    output key_out;//经消抖后的按键信号输出

    wire clk;

    wire key;

    reg key_out;

    parameter s0=2'b00,s1=2'b01,s2=2'b10,s3=2'b11;

    reg[1:0] state;

    always@(posedge clk)

    begin

    case(state)

    s0:

    begin

    key_out<=1'b1;

         if(key==1'b0)

             state<=s1;

         else

         state<=s0;

         end

         s1:

         begin

         if(key==1'b0)

             state<=s2;

         else

         state<=s0;

         end

         s2:

         begin

         if(key==1'b0)

             state<=s3;

         else

         state<=s0;

         end

         s3:

         begin

         if(key==1'b0)

         begin

             key_out<=1'b0;

             state<=s3;

             end

            else

             begin

             key_out<=1'b1;

             state<=s0;

         end

         end

         default:

         state<=s0;

    endcase

    end

    endmodule

    按键编码:即是对已经经过按键消抖后的按键信号进行编码,通过按键的按下控制幅值控制变量、频率控制变量、相位控制变量的大小。该模块采用的方法是每按下按键一次相对应的控制变量的值便会增加,最后的相应的输出也会变化。

    /********************************版权声明**************************************

    ** 大西瓜团队

    **

    **----------------------------文件信息--------------------------

    ** 文件名称: key_coding.v

    ** 创建日期:

    ** 功能描述:按键编码

    ** 硬件平台:大西瓜第三代开发板,http://daxiguafpga.taobao.com

    ** 版权声明:本代码属个人知识产权,本代码仅供交流学习.

    **---------------------------修改文件的相关信息----------------

    ** 修改人:

    ** 修改日期:    

    ** 修改内容:

    *******************************************************************************/

    module key_coding(

    reset,

    set_waveform_key,

    set_f_key,

    set_a_key,

    set_p_key,

    set_waveform,

    f_control,

    a_control,

    p_control

    );

    input reset;

    input set_waveform_key;

    input set_f_key,set_a_key,set_p_key;

    output[1:0] set_waveform;

    output[15:0] f_control;

    output[3:0] a_control;

    output[9:0] p_control;

    wire reset;

    wire set_waveform_key;

    wire set_f_key,set_a_key,set_p_key;

    reg[1:0] set_waveform;

    reg[15:0] f_control;

    reg[3:0] a_control;

    reg[9:0] p_control;

    /******************波形设置****************************************/

    always@(negedge set_waveform_key ornegedge reset)

    begin

    if(!reset)

    set_waveform<=2'b00;

    else

    begin

    if(!set_waveform_key)//判断按键是否按下

    begin

    set_waveform<=set_waveform+1'b1;

    end

    end

    end

    /****************频率设置*******************************************/

    always@(negedge set_f_key ornegedge reset)

    begin

    if(!reset)

    f_control<=16'b0100001100011011;//200Hz

    else

    begin

    if(!set_f_key)//判断按键是否按下

    begin

    if(f_control==16'hffff)

    f_control<=16'h0;

    else

    f_control<=f_control+16'd50;

    end

    end

    end

    /***************幅值控制****************************************/

    always@(negedge set_a_key ornegedge reset)

    begin

    if(!reset)

    a_control<=4'd1;

    else

    begin

    if(!set_a_key)//判断按键是否按下

    begin

    if(a_control==4'd10)

    a_control<=4'd1;

    else

    a_control<=a_control+4'd1;

    end

    end

    end

    /***************相位设置******************************************/

    always@(negedge set_p_key ornegedge reset)

    begin

    if(!reset)

    p_control<=10'b00_0000_0000;//0

    else

    begin

    if(!set_p_key)//判断按键是否按下

    begin

    if(p_control==10'b11_1111_1111)

    p_control<=10'b0;

    else

    p_control<=p_control+10'd100;

    end

    end

    end

    endmodule

    DDS信号发生器:这里的采用DDS来产生四种波形:正弦波、三角波、方波、锯齿波,采用的位数为10位,因为我们的DAC芯片是10位分辨率的。这四种波形通过一个按键进行控制,同时我们需要调用4个ROM来存放这四个波形。而这四ROM里面的数据通过寻址来调用,这里需要一个加法器和一个累加器来产生ROM 的地址。同过不断让地址累加,从而不断地从ROM中读取波形数据,然后将数据送往DACTLC5615的驱动模块中,这样最终便输出模拟的波形。DDS的具体过程这里不详讲,具体看"嵌入式逻辑分析仪的调用相关章节"。

    频率累加器和相位累加器,通过改变频率累加器的频率控制字就可以控制输出的波形频率,通过改变相位累加器的相位控制字就可以控制输出波形的相位。而幅值的改变是通过将通过ROM里面读出的数据就行等比例的缩减,通过改变缩减倍数就可以改变输出波形的幅值(0~3.3V),而改变的过程是通过外部的按键进行改变。

    /********************************版权声明**************************************

    ** 大西瓜团队

    **

    **----------------------------文件信息--------------------------

    ** 文件名称: DDS.v

    ** 创建日期:

    ** 功能描述:DDS信号发生与嵌入式逻辑分析仪的调用

    ** 硬件平台:大西瓜第三代开发板,http://daxiguafpga.taobao.com

    ** 版权声明:本代码属个人知识产权,本代码仅供交流学习.

    **---------------------------修改文件的相关信息----------------

    ** 修改人:

    ** 修改日期:    

    ** 修改内容:

    *******************************************************************************/

    module DDS(clk,dds_data_out,set_waveform,set_f,set_a,set_p);

    input clk;//时钟输入

    input[1:0] set_waveform;

    input[15:0] set_f;

    input[4:0] set_a;

    input[9:0] set_p;

    output[9:0] dds_data_out;

    wire clk;

    wire[1:0] set_waveform;

    wire[15:0] set_f;

    wire[4:0] set_a;

    wire[9:0] set_p;

    wire[9:0] dds_data_out;

    /**************连接线***************/

    wire[31:0] f32_bus;//AC频率控制字输入

    wire[31:0] reg32_out;//32位寄存器输出

    wire[31:0] reg32_in;//32位寄存器输入

    wire[9:0] reg10_in;

    wire[9:0] reg10_out_address;

    /************************************/

    wire[9:0] sin_data;

    wire[9:0] tri_data;

    wire[9:0] squ_data;

    wire[9:0] saw_data;

    reg[9:0] dds_data_reg;

    parameter[15:0] f32_bus_init=16'b0000_0000_0000_0000;

    assign f32_bus[31:16]=f32_bus_init;//初始化,高位置低

    assign f32_bus[15:0]=set_f;//低位可以设置DDS的输出频率

    //1010011111000100(500Hz)

    //1000011000110110(400Hz)

    //0100001100011011(200Hz)

    //0010000110001001(100Hz)

    //0000011010110101(20Hz)

    /*********************元件例化************************************/

    adder_32 u1(.data1(f32_bus),.data2(reg32_out),.sum(reg32_in));

    reg32 u2(.clk(clk),.data_in(reg32_in),.data_out(reg32_out));

    adder_10 u7(.data1(set_p),.data2(reg32_out[31:22]),.sum(reg10_in));

    reg_10 u8(.clk(clk),.data_in(reg10_in),.data_out(reg10_out_address));

    /*****************波形选择*******************************************/

    sin_rom u3(.address(reg10_out_address),.clock(clk),.q(sin_data));//正弦

    tri_rom u4(.address(reg10_out_address),.clock(clk),.q(tri_data));

    squ_rom u5(.address(reg10_out_address),.clock(clk),.q(squ_data));

    saw_rom u6(.address(reg10_out_address),.clock(clk),.q(saw_data));

    always@(set_waveform,sin_data,tri_data,squ_data,saw_data)

    begin

    case(set_waveform)

    2'b00: dds_data_reg<=sin_data;

    2'b01: dds_data_reg<=tri_data;

    2'b10: dds_data_reg<=squ_data;

    2'b11: dds_data_reg<=saw_data;

    default:dds_data_reg<=sin_data;

    endcase;

    end

    assign dds_data_out=dds_data_reg*set_a/10;

    endmodule

    DAC TLC5615驱动: 参考进阶实验的相关章节;

    硬件原理图

    实验效果

    大西瓜FPGA-->https://daxiguafpga.taobao.com

    博客资料、代码、图片、文字等属大西瓜FPGA所有,切勿用于商业! 若引用资料、代码、图片、文字等等请注明出处,谢谢!

    每日推送不同科技解读,原创深耕解读当下科技,敬请关注微信公众号“科乎”。

  • 相关阅读:
    判断有向无环图(DAG)
    单向连通图 Going from u to v or from v to u? poj2762
    百度地图的实时路况 2016 计蒜之道 复赛
    快速模取幂
    fibonacci数列(二)_矩阵快速幂
    数与矩阵快速幂基本知识
    Brute-force Algorithm_矩阵快速幂&&欧拉公式*****
    Nearest number
    Zipper_DP
    Jumping Cows_贪心
  • 原文地址:https://www.cnblogs.com/logic3/p/5303590.html
Copyright © 2020-2023  润新知