FPGA入门学习笔记(十八)Vivado设计高速DAC信号发生器

设计要求

1、设计一个双通道的信号发生器输出
2、能够简单的调整每个通道的频率输出(通过按键来循环切换几个固定频率输出)
3、能够简单的调整每个通道的输出相位(通过按键来循环切换几个固定相位输出)
4、能够简单的调整输出的波形形式(正弦波、方波、三角波)

仿真波形

在这里插入图片描述

设计文件程序

`timescale 1ns / 1ns

module DDS_Module(
        Clk,
        Reset_N,
        Model_Sel,
        Fword,
        Pword,
        Data
    );
    input Clk;
    input Reset_N;
    input [1:0]Model_Sel;
    input [31:0]Fword;
    input [11:0]Pword;
    output reg [13:0]Data;
    wire [31:0]Data_Sine;
    wire [31:0]Data_Triangular;
    wire [31:0]Data_Square;
    
    //频率控制字的同步寄存器
    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;
    
    //波形数据表的地址
    //查ROM表输出序列
    wire [11:0]Rom_Addr;
    assign Rom_Addr = Freq_ACC[31:20] + Pword_r;
        
    Rom_Sine Rom_Sine (
      .clka(Clk),
      .addra(Rom_Addr),
      .douta(Data_Sine)
    );
    Rom_Triangular Rom_Triangular (
      .clka(Clk),
      .addra(Rom_Addr),
      .douta(Data_Triangular)
    );
    Rom_Square Rom_Square (
      .clka(Clk),
      .addra(Rom_Addr),
      .douta(Data_Square)
    );
    
    always@(*)
        case(Model_Sel)
            0:Data <= Data_Sine;
            1:Data <= Data_Triangular;
            2:Data <= Data_Square;
            3:Data <= 8192;
        endcase
endmodule
`timescale 1ns / 1ns

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 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]R_Key;
    reg [1:0]Sync_Key;

    wire Pedge_Key;
    wire Nedge_Key;
    
    always@(posedge Clk)begin
        Sync_Key <= #1 {Sync_Key[0],Key};
    end
    
    always@(posedge Clk)begin
        R_Key <= #1 {R_Key[0],Sync_Key[1]};
//        R_Key[0] <= Key;
//        R_Key[1] <= R_Key[0];
    end
    //Posedge Check
    assign Pedge_Key = (R_Key == 2'b01);
    //Negedge Check
    assign Nedge_Key = (R_Key == 2'b10);
    
    reg [19:0]Counter;
    localparam IDLE = 0;
    
    reg [1:0]state;
    always@(posedge Clk or negedge Reset_N)
    if(!Reset_N)begin
        state <= #1 0;
        Counter <= #1 0;
        Key_P_Flag <= #1 0;
        Key_R_Flag <= #1 0;
        Key_State <= #1 1;
    end
    else begin
        case(state)
            0:
                begin
                    Key_R_Flag <= #1 0;
                    if(Nedge_Key)
                        state <= #1 1;
                    else
                        state <= #1 0;
                end
            1:
                if((Pedge_Key)&&(Counter < 1000000 - 1))begin
                    state <= #1 0;
                    Counter <= #1 0;
                end
                else if(Counter >= 1000000 - 1)begin
                    state <= #1 2;
                    Counter <= #1 0;
                    Key_P_Flag <= #1 1;
                    Key_State <= #1 0;
                end
                else begin
                    Counter <= #1 Counter + 1'd1;
                    state <= #1 1;
                end
            2:
                begin
                    Key_P_Flag <= #1 0;
                    if(Pedge_Key)
                        state <= #1 3;
                    else
                        state <= #1 2;
                end
            3:
                if((Nedge_Key)&&(Counter < 1000000 - 1))begin
                    state <= #1 2;
                    Counter <= #1 0;
                end
                else if(Counter >= 1000000 -1)begin
                    state <= #1 0;
                    Counter <= #1 0;
                    Key_R_Flag <= #1 1;
                    Key_State <= #1 1;
                end
                else begin
                    Counter <= #1 Counter + 1'd1;
                    state <= #1 3;
                end
        endcase
    end
endmodule
`timescale 1ns / 1ns
module DDS_AD9767(
        Clk,
        Reset_N,
        Model_SelA,
        Model_SelB,
        Key,
        DataA,
        DataB
    );
    input Clk;
    input Reset_N;
    input [1:0]Model_SelA;
    input [1:0]Model_SelB;
    input [3:0]Key;
    output [13:0]DataA;
    output [13:0]DataB;
    
    wire [3:0]Key_Flag;
    wire [3:0]Key_State;
    reg [31:0]FwordA,FwordB;
    reg [11:0]PwordA,PwordB;
    
    DDS_Module DDS_ModuleA(
            Clk,
            Reset_N,
            Model_SelA,
            FwordA,
            PwordA,
            DataA
        );
        
    DDS_Module DDS_ModuleB(
            Clk,
            Reset_N,
            Model_SelB,
            FwordB,
            PwordB,
            DataB
        );
    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;
    
    always@(posedge Clk or negedge Reset_N)
    if(!Reset_N)
        CHA_Fword_Sel <= 0;
    // Key_Flag == 1    发生按键按下或释放动作
    // Key_State == 0   低电平标志位
    else if(Key_Flag[0] && (Key_State[0] == 0))
        CHA_Fword_Sel <= CHA_Fword_Sel + 1'b1;
        
    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'b1;
        
    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'b1;
        
    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'b1;

    always@(*)
        case(CHA_Fword_Sel)
            0: FwordA = 86;
            1: FwordA = 859;
            2: FwordA = 8590;
            3: FwordA = 85899;
            4: FwordA = 858993;
            5: FwordA = 8589935;
            6: FwordA = 85899346;
            7: FwordA = 429496730;
        endcase
    always@(*)
        case(CHB_Fword_Sel)
            0: FwordB = 86;
            1: FwordB = 859;
            2: FwordB = 8590;
            3: FwordB = 85899;
            4: FwordB = 858993;
            5: FwordB = 8589935;
            6: FwordB = 85899346;
            7: FwordB = 429496730;
        endcase
    always@(*)
        case(CHA_Pword_Sel)
            0: PwordA = 0;
            1: PwordA = 341;
            2: PwordA = 683;
            3: PwordA = 1024;
            4: PwordA = 1707;
            5: PwordA = 2048;
            6: PwordA = 3072;
            7: PwordA = 3641;
        endcase
    always@(*)
        case(CHB_Pword_Sel)
            0: PwordB = 0;
            1: PwordB = 341;
            2: PwordB = 683;
            3: PwordB = 1024;
            4: PwordB = 1707;
            5: PwordB = 2048;
            6: PwordB = 3072;
            7: PwordB = 3641;
        endcase
endmodule

仿真文件程序

`timescale 1ns / 1ns

module DDS_AD9767_tb();
    reg Clk;
    reg Reset_N;
    reg [1:0]Model_SelA;
    reg [1:0]Model_SelB;
    reg [3:0]Key;
    wire [13:0]DataA;
    wire [13:0]DataB;
    DDS_AD9767 DDS_AD9767(
            Clk,
            Reset_N,
            Model_SelA,
            Model_SelB,
            Key,
            DataA,
            DataB
        );
    initial Clk = 1;
    always #10 Clk = !Clk;
    initial begin
        Reset_N = 0;Key = 4'b1111;
        #201;
        Reset_N = 1;
        Model_SelA = 1;
        Model_SelB = 0;
        #2000;
        Key = 4'b1100;
        #50000000;
        Key = 4'b1111;
        #50000000;
        Key = 4'b0000;
        #50000000;
        Key = 4'b1111;
        #20000000;
        $stop;
    end
endmodule
  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
根据DDS技术原理,在vavido上编写DDS信号源硬件逻辑语言,可以实现频率、幅度和波形可调的信号源发生器。DDS是以数控振荡器的方式产生频率和相位可控制的波形,它需要基准时钟源、相位累加器、相位调制器和正弦ROM查找表等组成。有人在Zedboard上用Vivado编写了DDS信号发生器的工程文件,适用于产生任意波形,并且作者对此进行了几天的验证,是学习的最佳教材。所以,FPGA DDS信号发生器Vivado是一种使用Vivado软件编写的硬件逻辑语言来实现DDS信号发生器的方法。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [基于FPGA的DDS信号发生器vivado版本)](https://blog.csdn.net/m0_58714286/article/details/128924266)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *3* [Xilinx DDS信号发生器vivado工程文件](https://download.csdn.net/download/u010879745/22647209)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值