基于AD9767高速DAC的DDS信号发生器(Verilog&Vivado)


前言

基于AD9767高速DAC的DDS信号发生器


提示:以下是本篇文章正文内容,下面案例可供参考

一、 实现效果

1.做一个双通道的信号发生器;
2.简单调整每个通道的频率输出;
3.能够调整每个通道的输出相位;
4.能够输出正弦波,三角波,方波。

二、DDS_AD9767(顶层模块)

代码如下(示例):

`timescale 1ns / 1ps

module DDS_AD9767(
    Clk,
    Reset_n,
    Mode_SelA,
    Mode_SelB,
    DataA,
    ClkA,    //AD9767高速DAC驱动需要
    WRTA,
    DataB,  //AD9767高速DAC驱动需要
    WRTB,   //AD9767高速DAC驱动需要
    ClkB,   //AD9767高速DAC驱动需要
    Key
);
   input Clk;
   input Reset_n;
   input [1:0]Mode_SelA;//实现通道1的波形选择
   input [1:0]Mode_SelB;//实现通道的波形选择
   input [3:0]Key;      //按键实现Fword   Pward切换
   output [13:0]DataA;
   output ClkA;
   output WRTA;
   output [13:0]DataB;
   output ClkB;
   output WRTB;
   
   assign ClkA = Clk;
   assign ClkB = Clk;
   assign WRTA = ClkA;
   assign WRTB = ClkB;  
   
   reg [31:0]FwordA,FwordB;
   reg [11:0]PwordA,PwordB;
 //----------------------------------------------------------------------------
 //双通道例化两次  
   DDS_Module DDS_ModuleA(
        .Clk(Clk),
        .Reset_n(Key_State[2] & Key_State[3]),   //切换时保持统一频率
        .Mode_Sel(Mode_SelA),
        .Fword(FwordA),
        .Pword(PwordA),
        .Data(DataA)
    );
    
   DDS_Module DDS_ModuleB(
        .Clk(Clk),
        .Reset_n(Key_State[2] & Key_State[3]),
        .Mode_Sel(Mode_SelB),
        .Fword(FwordB),
        .Pword(PwordB),
        .Data(DataB)
    ); 
 //----------------------------------------------------------------------------


//----------------------------------------------------------------------------
//四个key按键的按键消抖   
 wire [3:0]Key_Flag;
 wire [3:0]Key_State;
 //按键消抖
 key_filter key_filter0(
    .Clk(Clk),
    .Reset_n(Reset_n),
    .Key(Key[0]),
    .Key_Flag(Key_Flag[0]),
    .Key_State(Key_State[0])
);   
 //按键消抖   
 key_filter key_filter1(
    .Clk(Clk),
    .Reset_n(Reset_n),
    .Key(Key[1]),
    .Key_Flag(Key_Flag[1]),
    .Key_State(Key_State[1])
); 
//按键消抖
 key_filter key_filter2(
    .Clk(Clk),
    .Reset_n(Reset_n),
    .Key(Key[2]),
    .Key_Flag(Key_Flag[2]),
    .Key_State(Key_State[2])
); 
//按键消抖
 key_filter key_filter3(
    .Clk(Clk),
    .Reset_n(Reset_n),
    .Key(Key[3]),
    .Key_Flag(Key_Flag[3]),
    .Key_State(Key_State[3])
);  
//----------------------------------------------------------------------------



//----------------------------------------------------------------------------
//实现按键切换
    reg [2:0]CHA_Fword_Sel;
    reg [2:0]CHB_Fword_Sel;

    reg [2:0]CHA_Pword_Sel;
    reg [2:0]CHB_Pword_Sel;
    
   //按键切换Fword
    always@(posedge Clk or negedge Reset_n)    
    if(!Reset_n)
        CHA_Fword_Sel <= 0;
    else if(Key_Flag[0] &&  (Key_State[0] == 0))
        CHA_Fword_Sel <= CHA_Fword_Sel + 1'd1;
        
    //按键切换Fword    
    always@(posedge Clk or negedge Reset_n)    
    if(!Reset_n)
        CHB_Fword_Sel <= 0;
    else if(Key_Flag[1] &&  (Key_State[1] == 0))
        CHB_Fword_Sel <= CHB_Fword_Sel + 1'd1;    
         
    //按键切换Pword
    always@(posedge Clk or negedge Reset_n)    
    if(!Reset_n)
        CHA_Pword_Sel <= 0;
    else if(Key_Flag[2] &&  (Key_State[2] == 0))
        CHA_Pword_Sel <= CHA_Pword_Sel + 1'd1;
        
     //按键切换Pword   
    always@(posedge Clk or negedge Reset_n)    
    if(!Reset_n)
        CHB_Pword_Sel <= 0;
    else if(Key_Flag[3] &&  (Key_State[3] == 0))
        CHB_Pword_Sel <= CHB_Pword_Sel + 1'd1;

    always@(*)
        case(CHA_Fword_Sel)
            0:FwordA = 86;//2**32 / 50000000;  85.89934592
            1:FwordA = 859;//2**32 / 5000000;
            2:FwordA = 8590;//2**32 / 500000;
            3:FwordA = 85899;//2**32 / 50000;
            4:FwordA = 858993;//2**32 / 5000;
            5:FwordA = 8589935;//2**32 / 500;
            6:FwordA = 85899346;//2**32 / 50;
            7:FwordA = 429496730;//2**32 / 10;
        endcase
        
    always@(*)
        case(CHB_Fword_Sel)
            0:FwordB = 86;//2**32 / 50000000;  85.89934592
            1:FwordB = 859;//2**32 / 5000000;
            2:FwordB = 8590;//2**32 / 500000;
            3:FwordB = 85899;//2**32 / 50000;
            4:FwordB = 858993;//2**32 / 5000;
            5:FwordB = 8589935;//2**32 / 500;
            6:FwordB = 85899346;//2**32 / 50;
            7:FwordB = 429496730;//2**32 / 10;
        endcase  
        
    always@(*)
        case(CHA_Pword_Sel)
            0:PwordA = 0;   //0
            1:PwordA = 341; //30
            2:PwordA = 683; //60
            3:PwordA = 1024;    //90
            4:PwordA = 1707;    //150
            5:PwordA = 2048;    //180
            6:PwordA = 3072;    //270
            7:PwordA = 3641;    //320
        endcase 

    always@(*)
        case(CHB_Pword_Sel)
            0:PwordB = 0;   //0
            1:PwordB = 341; //30
            2:PwordB = 683; //60
            3:PwordB = 1024;    //90
            4:PwordB = 1707;    //150
            5:PwordB = 2048;    //180
            6:PwordB = 3072;    //270
            7:PwordB = 3641;    //320
        endcase    

//----------------------------------------------------------------------------             
endmodule

三、DDS_Module

代码如下(示例):


module DDS_Module(
    Clk,
    Reset_n,
    Mode_Sel,
    Fword,
    Pword,
    Data
);
    input Clk;
    input Reset_n;
    input [1:0]Mode_Sel;
    input [31:0]Fword;
    input [11:0]Pword;
    output reg[13:0]Data;
    
    //频率控制字同步寄存器
    reg [31:0]Fword_r;
    always@(posedge Clk)
        Fword_r <= Fword;
    
    //相位控制字同步寄存器
    reg [11:0]Pword_r;
    always@(posedge Clk)
        Pword_r <= Pword; 
    
    //相位累加器    
    reg [31:0]Freq_ACC;
    always@(posedge Clk or negedge Reset_n)
    if(!Reset_n)
        Freq_ACC <= 0;
    else
        Freq_ACC <= Fword_r + Freq_ACC;
 
    //波形数据表地址
    wire [11:0]Rom_Addr;      
    assign Rom_Addr = Freq_ACC[31:20] + Pword_r;


//---------------------------------------------------------------------------
//实现波形选择    
    wire [13:0]Data_sine,Data_square,Data_triangular;
    rom_sine rom_sine(
      .clka(Clk),
      .addra(Rom_Addr),
      .douta(Data_sine)
    );
    
    rom_square rom_square(
      .clka(Clk),
      .addra(Rom_Addr),
      .douta(Data_square)
    ); 
     
    rom_triangular rom_triangular(
      .clka(Clk),
      .addra(Rom_Addr),
      .douta(Data_triangular)
    );  
    
    always@(*)
        case(Mode_Sel)
            0:Data = Data_sine;
            1:Data = Data_square;
            2:Data = Data_triangular;
            3:Data = 8192;
        endcase
//---------------------------------------------------------------------------
        
endmodule


四、key_filter

module key_filter(
    Clk,
    Reset_n,
    Key,
//    Key_P_Flag,
//    Key_R_Flag,
    Key_Flag,
    Key_State
);
    input Clk;
    input Reset_n;
    input Key;
//    output reg Key_P_Flag;
//    output reg Key_R_Flag;
    output Key_Flag;
    output reg Key_State;
    
    reg Key_P_Flag;
    reg Key_R_Flag;
    
    assign Key_Flag = Key_P_Flag | Key_R_Flag;
 
 //-----------------------------------------------------------
    //两个寄存器防止亚稳态
    reg [1:0]sync_Key;
    always@(posedge Clk)
        sync_Key <= {sync_Key[0],Key};
    
    reg [1:0] r_Key;
    always@(posedge Clk)
        r_Key <= {r_Key[0],sync_Key[1]};
 //-----------------------------------------------------------       


    wire pedge_key;
    assign pedge_key = r_Key == 2'b01;
    wire nedge_key;
    assign nedge_key = r_Key == 2'b10;
    
    reg [19:0]cnt;
    
    reg [1:0]state;
    always@(posedge Clk or negedge Reset_n)
    if(!Reset_n)begin
        state <= 0;
        Key_R_Flag <= 1'b0;
        Key_P_Flag <= 1'b0;
        cnt <= 0;
        Key_State <= 1;
    end
    else begin
        case(state)
            0:
                begin
                    Key_R_Flag <= 1'b0;
                    if(nedge_key)
                        state <= 1;
                    else
                        state <= 0;
                end
            
            1:
                if((pedge_key)&&(cnt <1000000 -1))begin
                    state <= 0;
                    cnt <= 0;
                end
                else if(cnt >= 1000000 -1)begin
                    state <= 2;
                    cnt <= 0;
                    Key_P_Flag <= 1;
                    Key_State <= 0;
                end
                else begin
                    cnt <= cnt + 1'b1;
                    state <= 1;
                end
                
            2:
                begin
                    Key_P_Flag <= 0;
                    if(pedge_key)
                        state <= 3;
                    else
                        state <= 2;
                 end
                    
            3:
                if((nedge_key)&&(cnt <1000000 -1))begin
                    state <= 2;
                    cnt <= 0;
                end
                else if(cnt >= 1000000 -1)begin
                    state <= 0;
                    cnt <= 0;
                    Key_R_Flag <= 1'b1;
                    Key_State <= 1;
                end
                else begin
                    cnt <= cnt + 1'b1;
                    state <= 3;               
                end
        endcase   
    end

endmodule

五、上板演示

1

【附件:】链接:https://pan.baidu.com/s/1dGSAj9wV1GpYPKa4Fl6KuA?pwd=ncix
提取码:ncix

  • 4
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 8
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

C.V-Pupil

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值