基于vivado+Verilog FPGA开发 — 基于AD9767高速DAC的DDS信号发生器

这篇具有很好参考价值的文章主要介绍了基于vivado+Verilog FPGA开发 — 基于AD9767高速DAC的DDS信号发生器。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

 一、功能定义

二、设计输入 

1、主模块

2、DDS模块

3、 按键消抖模块

三、功能仿真 

四、综合优化

五、布局布线

六、时序仿真

七、板级调试 

代码规范:Verilog 代码规范_verilog代码编写规范-CSDN博客

开发流程:FPGA基础知识----第二章 FPGA 开发流程_fpga 一个项目的整个流程-CSDN博客 

源码下载:GitHub - Redamancy785/FPGA-Learning-Record: 项目博客:https://blog.csdn.net/weixin_51460407

 一、功能定义

基于vivado+Verilog FPGA开发 — 基于AD9767高速DAC的DDS信号发生器,FPGA,fpga开发

二、设计输入 

1、主模块

这段代码是一个Verilog模块,名为dds_ad9767,它实现了一个双通道的直接数字频率合成器(DDS)系统。DDS是一种用于生成模拟波形(如正弦波、方波等)的电子技术,广泛应用于信号发生器、通信系统等领域。这个模块特别为与AD9767这类数字信号处理器(DSP)芯片协同工作而设计。

基于vivado+Verilog FPGA开发 — 基于AD9767高速DAC的DDS信号发生器,FPGA,fpga开发

基于vivado+Verilog FPGA开发 — 基于AD9767高速DAC的DDS信号发生器,FPGA,fpga开发

/*
    Tips:
    1、可分别于A、B通道同时输出两路波形 
    2、每次按下 f_switch_button_a_i , 通道A输出频率在预设的四种情况切换;通道B同理。
    3、每次按下 p_switch_button_a_i , 通道A输出相位在预设的两种情况切换;通道B同理。
*/
module dds_ad9767(
    reset_n_i,
    clk_i,
    mode_switch_button_a_i,
    f_switch_button_a_i,
    p_switch_button_a_i,
    mode_switch_button_b_i,
    f_switch_button_b_i,
    p_switch_button_b_i,
    data_a_o,
    data_b_o
    );
    
    input  reset_n_i,clk_i;
    input [1:0]mode_switch_button_a_i,mode_switch_button_b_i;
    input f_switch_button_a_i,p_switch_button_a_i,f_switch_button_b_i,p_switch_button_b_i;
    output  [13:0] data_a_o;
    output  [13:0] data_b_o;
    
    // A通道dds例化
    reg [31:0] u_f_word_a;
    reg [11:0] u_p_word_a;

    dds U_dds_a( 
        .reset_n_i(reset_n_i),
        .clk_i(clk_i),
        .f_word_i(u_f_word_a),
        .p_word_i(u_p_word_a),
        .mode_i(mode_switch_button_a_i),
        .data_o(data_a_o)
    );
    
    //  A通道频率切换
    wire f_switch_button_a_press_key_flag;    
    key_filter U_f_switch_button_a_i(
        .clk_i(clk_i),
        .reset_n_i(reset_n_i),
        .key_i(f_switch_button_a_i),
        .press_key_flag_o(f_switch_button_a_press_key_flag)
    );
    
    reg [1:0] f_switch_cnt_a;
    
    always@(posedge clk_i or negedge reset_n_i)
    if(!reset_n_i)
        f_switch_cnt_a <= 0;
    else if(f_switch_button_a_press_key_flag == 1)
        f_switch_cnt_a <= f_switch_cnt_a + 1;
    
    always@(*)
    case(f_switch_cnt_a)
        0 : u_f_word_a <= 65536;
        1 : u_f_word_a <= 65536*2;
        2 : u_f_word_a <= 65536*3;
        3 : u_f_word_a <= 65536*4;
    endcase

    //  A通道相位切换
    wire p_switch_button_a_press_key_flag;    
    key_filter U_p_switch_button_a_i(
        .clk_i(clk_i),
        .reset_n_i(reset_n_i),
        .key_i(p_switch_button_a_i),
        .press_key_flag_o(p_switch_button_a_press_key_flag)
    );
    
    reg  p_switch_cnt_a;
    
    always@(posedge clk_i or negedge reset_n_i)
    if(!reset_n_i)
        p_switch_cnt_a <= 0;
    else if(p_switch_button_a_press_key_flag == 1)
        p_switch_cnt_a <= p_switch_cnt_a + 1;
    always@(*)
    case(p_switch_cnt_a)
        0 : u_p_word_a <= 0;
        1 : u_p_word_a <= 1024;
    endcase
    
    // B通道dds例化
    reg [31:0] u_f_word_b; 
    reg [11:0] u_p_word_b;
    dds U_dds_b( 
        .reset_n_i(reset_n_i),
        .clk_i(clk_i),
        .f_word_i(u_f_word_b),
        .p_word_i(u_p_word_b),
        .mode_i(mode_switch_button_b_i),
        .data_o(data_b_o)
    );
    
    //  B通道频率切换
    wire f_switch_button_b_press_key_flag;    
    key_filter U_f_switch_button_b_i(
        .clk_i(clk_i),
        .reset_n_i(reset_n_i),
        .key_i(f_switch_button_b_i),
        .press_key_flag_o(f_switch_button_b_press_key_flag)
    );
    
    reg [1:0] f_switch_cnt_b;
    
    always@(posedge clk_i or negedge reset_n_i)
    if(!reset_n_i)
        f_switch_cnt_b <= 0;
    else if(f_switch_button_b_press_key_flag == 1)
        f_switch_cnt_b <= f_switch_cnt_b + 1;
    always@(*)
    case(f_switch_cnt_b)
        0 : u_f_word_b <= 65536;
        1 : u_f_word_b <= 65536*2;
        2 : u_f_word_b <= 65536*3;
        3 : u_f_word_b <= 65536*4;
    endcase

    //  B通道相位切换
    wire p_switch_button_b_press_key_flag;    
    key_filter U_p_switch_button_b_i(
        .clk_i(clk_i),
        .reset_n_i(reset_n_i),
        .key_i(p_switch_button_b_i),
        .press_key_flag_o(p_switch_button_b_press_key_flag)
    );
    
    reg  p_switch_cnt_b;
    
    always@(posedge clk_i or negedge reset_n_i)
    if(!reset_n_i)
        p_switch_cnt_b <= 0;
    else if(p_switch_button_b_press_key_flag == 1)
        p_switch_cnt_b <= p_switch_cnt_b + 1;
    always@(*)
    case(p_switch_cnt_b)
        0 : u_p_word_b <= 0;
        1 : u_p_word_b <= 1024;
    endcase
    
endmodule

 2、DDS模块

1、IP设置

基于vivado+Verilog FPGA开发 — 基于AD9767高速DAC的DDS信号发生器,FPGA,fpga开发

 基于vivado+Verilog FPGA开发 — 基于AD9767高速DAC的DDS信号发生器,FPGA,fpga开发

 基于vivado+Verilog FPGA开发 — 基于AD9767高速DAC的DDS信号发生器,FPGA,fpga开发

 2、初始文件生成设置

基于vivado+Verilog FPGA开发 — 基于AD9767高速DAC的DDS信号发生器,FPGA,fpga开发

3、代码部分

这段代码是一个Verilog模块,名为dds,它实现了一个直接数字频率合成器(DDS)的功能。DDS是一种电子系统,能够通过数字技术生成模拟波形,如正弦波、方波和三角波等。这个模块通过接收频率字(f_word_i)和相位字(p_word_i)输入,以及模式选择信号(mode_i),来输出相应的波形数据。

基于vivado+Verilog FPGA开发 — 基于AD9767高速DAC的DDS信号发生器,FPGA,fpga开发

基于vivado+Verilog FPGA开发 — 基于AD9767高速DAC的DDS信号发生器,FPGA,fpga开发

/*
    Tips:
    1、修改 mode_i 可以切换三种不同的输出波形 
    2、f_word_i 频率字输入,当等于典型值2^16=65536时,dds输出的波形频率在738Hz左右
    3、p_word_i 相位字输入,当等于典型值1024时,dds输出的波形起始相位为90°
*/
module dds( 
    reset_n_i,
    clk_i,
    f_word_i,
    p_word_i,
    mode_i,
    data_o
    );
    
    input [1:0] mode_i;
    input reset_n_i,clk_i;
    input [31:0]f_word_i; 
    input [11:0]p_word_i;
    output reg [13:0] data_o;
    
    // 频率字输入寄存器 r_f_word_i
    reg [31:0] r_f_word_i; 
    always@(posedge clk_i)
        r_f_word_i <= f_word_i;
        
    // 相位字输入寄存器 r_f_word_i
    reg [11:0] r_p_word_i; 
    always@(posedge clk_i)
        r_p_word_i <= p_word_i;
         
    // 相位累加器 phase_accumulator
    reg [31:0] phase_accumulator;
    always@(posedge clk_i or negedge reset_n_i)
        if(!reset_n_i)
            phase_accumulator <= 0;
        else
            phase_accumulator <= phase_accumulator + r_f_word_i;
            
    // 波形数据表地址 rom_addr
    reg [11:0] rom_addr;
    always@(posedge clk_i or negedge reset_n_i)
        if(!reset_n_i)
            rom_addr <= 0;
        else
            rom_addr <= r_p_word_i + phase_accumulator[31:20];
    // sine波形         
    wire [13:0] sine_data_o;
    sine_rom U_sine_rom (
        .clka(clk_i),    // input wire clka
        .addra(rom_addr),  // input wire [11 : 0] addra
        .douta(sine_data_o)  // output wire [13 : 0] douta
    );
    
    // square波形
    wire [13:0] square_data_o;
    square_rom U_square_rom (
        .clka(clk_i),    // input wire clka
        .addra(rom_addr),  // input wire [11 : 0] addra
        .douta(square_data_o)  // output wire [13 : 0] douta
    );

    // triangular波形
    wire [13:0] triangular_data_o;
    triangular_rom U_triangular_rom (
        .clka(clk_i),    // input wire clka
        .addra(rom_addr),  // input wire [11 : 0] addra
        .douta(triangular_data_o)  // output wire [13 : 0] douta
    );  
    
    // 模式选择
    always@(*)
        case(mode_i)
            0 : data_o = sine_data_o;
            1 : data_o = square_data_o;
            2 : data_o = triangular_data_o;
            3 : data_o = 8192;
        endcase 
    
     
endmodule

3、 按键消抖模块

这段代码是一个Verilog模块,名为key_filter,它实现了一个按键滤波器的功能。该模块用于检测按键的按下和释放,并确保按键动作至少持续20毫秒。模块提供了按键按下和释放的输出标志,以及当前按键的状态。

基于vivado+Verilog FPGA开发 — 基于AD9767高速DAC的DDS信号发生器,FPGA,fpga开发

基于vivado+Verilog FPGA开发 — 基于AD9767高速DAC的DDS信号发生器,FPGA,fpga开发

/*
    Tips:
    1、检测到按键按下,会产生一个周期的 press_key_flag_o 提示信号
    2、按键按下时间需要持续20ms
*/
module key_filter(
    clk_i,
    reset_n_i,
    key_i,
    press_key_flag_o,
    release_key_flag_o,
    key_state_o
    );
    
    input clk_i,reset_n_i,key_i; 
    output press_key_flag_o,release_key_flag_o,key_state_o;
    
    reg press_key_flag_o,release_key_flag_o;
    reg [1:0] state; 
    wire time_20ms_reached;
    reg key_state_o;
    localparam IDLE = 0;
    localparam PRESS_FILTER = 1;
    localparam WAIT = 2;
    localparam RELEASE_FILTER = 3;
    
    // 输入 key_i 同步处理 消除亚稳态
    reg r_key_i,sync_d_0_key_i,sync_d_1_key_i; 
    wire nedge_key,pedge_key;
    always@(posedge clk_i)
        sync_d_0_key_i <= key_i;
    always@(posedge clk_i)
        sync_d_1_key_i <= sync_d_0_key_i;
    always@(posedge clk_i)
        r_key_i <= sync_d_1_key_i;
   
    assign nedge_key = r_key_i & (~sync_d_1_key_i); 
    assign pedge_key = ~r_key_i & sync_d_1_key_i;

    // 状态机 
    always@(posedge clk_i or negedge reset_n_i)
    if(!reset_n_i) begin
        release_key_flag_o <= 0;
        press_key_flag_o <= 0;
        state <= IDLE;
        key_state_o <= 1;
    end
    else begin 
        case(state)
            IDLE :
                begin
                    release_key_flag_o <= 0;
                    if(nedge_key)
                        state <= PRESS_FILTER;
                    else 
                        state <= IDLE;
                end
                
            PRESS_FILTER :
                if(time_20ms_reached) begin
                    state <= WAIT;
                    press_key_flag_o <= 1;
                    key_state_o <= 0;
                end
                else if(pedge_key)
                    state <= IDLE;
                else 
                    state <= PRESS_FILTER;
                    
            WAIT :
                begin
                    press_key_flag_o <= 0;
                    if(pedge_key)
                        state <= RELEASE_FILTER;
                    else
                        state <= WAIT;
                end
                
            RELEASE_FILTER :
                if(time_20ms_reached) begin
                    state <= IDLE;
                    release_key_flag_o <= 1;
                    key_state_o <= 1;
                end
                else if(nedge_key)
                    state <= WAIT;
                else 
                    state <= RELEASE_FILTER;    
        endcase
    end
    
    // time_20ms_reached 
    parameter MCNT = 1000_000;
    reg [29:0] counter;
    always@(posedge clk_i or negedge reset_n_i)
        if(!reset_n_i)
            counter <= 0;
        else if(state == RELEASE_FILTER || state == PRESS_FILTER) 
            counter <= counter + 1;
        else
            counter <= 0;
    
    assign time_20ms_reached = ( counter >= (MCNT - 1) );    
 
endmodule

三、功能仿真 

这段代码是一个Verilog测试平台(testbench),名为dds_ad9767_tb,用于模拟和测试dds_ad9767模块的行为。测试平台没有物理硬件,它通过模拟输入信号来验证dds_ad9767模块的功能是否符合预期。

基于vivado+Verilog FPGA开发 — 基于AD9767高速DAC的DDS信号发生器,FPGA,fpga开发

基于vivado+Verilog FPGA开发 — 基于AD9767高速DAC的DDS信号发生器,FPGA,fpga开发

 

`timescale 1ns / 1ps

module dds_ad9767_tb();
    reg  u_reset_n_i,u_clk_i;
    reg [1:0] u_mode_switch_button_a_i,u_mode_switch_button_b_i;
    reg u_f_switch_button_a_i,u_p_switch_button_a_i,u_f_switch_button_b_i,u_p_switch_button_b_i;
    wire [13:0] u_data_a_o;
    wire [13:0] u_data_b_o;
    
    dds_ad9767 U_dds_ad9767(
        .reset_n_i(u_reset_n_i),
        .clk_i(u_clk_i),
        .mode_switch_button_a_i(u_mode_switch_button_a_i),
        .f_switch_button_a_i(u_f_switch_button_a_i),
        .p_switch_button_a_i(u_p_switch_button_a_i),
        .mode_switch_button_b_i(u_mode_switch_button_b_i),
        .f_switch_button_b_i(u_f_switch_button_b_i),
        .p_switch_button_b_i(u_p_switch_button_b_i),
        .data_a_o(u_data_a_o),
        .data_b_o(u_data_b_o)
    );
    
    initial u_clk_i = 1;
    always #10 u_clk_i = ~u_clk_i;  // 50MHz
    
    initial begin
        u_reset_n_i = 0; 
        u_f_switch_button_a_i = 1;
        u_f_switch_button_b_i = 1;
        u_p_switch_button_a_i = 1;
        u_p_switch_button_b_i = 1;
        
        // 通道 波形类型 频率倍数 相位
        // a sine x1 0 \ b square x1 0
        u_mode_switch_button_a_i = 0;
        u_mode_switch_button_b_i = 1;
        #201;
        u_reset_n_i = 1;  
        #10_000_000;
        
        // a square x1 0 \ b square x1 0
        u_mode_switch_button_a_i = 1;
        
        // a square x2 0 \ b square x1 0
        u_f_switch_button_a_i = 0;
        #20_000_000;
        u_f_switch_button_a_i = 1;
        #10_000_000;
        
        // a square x2 90 \ b square x1 0
        u_p_switch_button_a_i = 0;
        #20_000_000;
        u_p_switch_button_a_i = 1;
        #10_000_000;
        
        // a square x2 90 \ b square x1  90
        u_p_switch_button_b_i = 0;
        #20_000_000;
        u_p_switch_button_b_i = 1;
        #10_000_000;
        
        // a square x2 90 \ b triangular  x1 90
        u_mode_switch_button_b_i = 2;
        
        // a square x2 90 \ b triangular x2 90
        u_f_switch_button_a_i = 0;
        #20_000_000;
        u_f_switch_button_a_i = 1;
        #10_000_000;

        $stop;
    end
endmodule

基于vivado+Verilog FPGA开发 — 基于AD9767高速DAC的DDS信号发生器,FPGA,fpga开发文章来源地址https://www.toymoban.com/news/detail-841122.html

四、综合优化

五、布局布线

六、时序仿真

七、板级调试 

到了这里,关于基于vivado+Verilog FPGA开发 — 基于AD9767高速DAC的DDS信号发生器的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 基于FPGA的高速数据采集ATA接口Verilog开发与Matlab

    基于FPGA的高速数据采集ATA接口Verilog开发与Matlab 摘要: 本文介绍了基于FPGA的高速数据采集ATA接口的Verilog开发与Matlab的应用。通过使用Verilog语言进行FPGA的硬件设计,实现了ATA接口的数据采集功能。同时,结合Matlab进行数据处理和分析,实现了对采集的数据进行实时处理和显

    2024年02月07日
    浏览(55)
  • 基于vivado+Verilog FPGA开发 — GT收发器

    代码规范:Verilog 代码规范_verilog代码编写规范-CSDN博客 开发流程:FPGA基础知识----第二章 FPGA 开发流程_fpga 一个项目的整个流程-CSDN博客   源码下载:GitHub - Redamancy785/FPGA-Learning-Record: 项目博客:https://blog.csdn.net/weixin_51460407 零、低速通信接口的缺陷 1、同步通信要求传输数据

    2024年04月17日
    浏览(64)
  • 基于FPGA的AES加密解密vivado仿真,verilog开发,包含testbench

    目录 1.算法描述 2.仿真效果预览 3.verilog核心程序 4.完整verilog          AES, 高级加密标准, 是采用区块加密的一种标准, 又称Rijndael加密法. 严格上来讲, AES和Rijndael又不是完全一样, AES的区块长度固定为128比特, 秘钥长度可以是128, 192或者256. Rijndael加密法可以支持更大范围的区

    2024年02月01日
    浏览(57)
  • 半导体运动台基于dsp+fpga+ad+endac的高速数据采集FPGA设计(二)

    4 系统 FPGA 程序的设计 4.1 设计方法及逻辑设计概述 4.1.1 开发环境与设计流程 Quartus II 是 Altera 公司综合开发工具,它集成了 FPGA/CPLD 开发过程中所设计 的所有工具和第三方软件接口,支持多时钟分析, LogicLock 基于块的设计,片上可编 程系统 SOPC, 内嵌在线逻辑分析仪 Signal

    2024年02月12日
    浏览(48)
  • FPGA实验笔记_Vivado:DDS信号发生器;数码管;基于DHT11的温湿度传感器

    目录 1、 FPGA的DDS信号发生器 1.1、DDS简介 1.2、ROM IP核的生成 1.3、波形数据的生成 1.4、 ROM的调用 1.5、 完整代码(包括拓展部分) 2、数码管显示 2.1、数码管简要说明 2.2、SM410564 3、基于DHT11的温湿度传感器 3.1、DHT11 3.2、基本思路 3.3、数据分离模块(BTD) 3.4、数据转换模块(

    2024年02月04日
    浏览(59)
  • 基于dsp+fpga+AD+ENDAC的半导体运动台高速数据采集电路仿真设计(四)

    整个调试验证与仿真分析分三个步骤:第一步是进行 PCB 检查及电气特性测试,主 要用来验证硬件设计是否正常工作;第二步进行各子模块功能测试,包括高速光纤串行 通信的稳定性与可靠性测试, A/D 及 D/A 转换特性测试, EnDat 串行通信相关时序测试 与验证等,主要用来验

    2024年02月01日
    浏览(54)
  • 光刻机基于dsp+fpga+ad+endac光纤传输的高速数据采集与伺服接口系统设计(一)

    光刻机双工件台运动控制系统,控制任务相当复杂,要求极高的速度和精度,且设 备体积庞大,各传感器执行器空间距离较远,线缆众多现场电磁干扰严重。 为满足控制系统要求,本文利用 DSP 的高速浮点运算能力、 FPGA 强大的并行处理 能力及光纤通信传输距离远、抗干扰

    2024年02月03日
    浏览(53)
  • 基于FPGA的DDS原理信号发生器设计 quartusII 9.1平台 Verilog HDL语言编程 可产生正弦波

    基于FPGA的DDS原理信号发生器设计 quartusII 9.1平台 Verilog HDL语言编程  可产生正弦波、方波、锯齿波以及三角波   频率幅度可调节   代码+原理图 在现代电子技术领域,针对各种应用的信号发生器是一种非常核心的设备,而基于现场可编程逻辑门阵列(FPGA)的直接数字合成(

    2024年04月27日
    浏览(63)
  • 基于vivado(语言Verilog)的FPGA学习(5)——跨时钟处理

    慢时钟到快时钟一般都不需要处理,关键需要解决从快时钟到慢时钟的问题,因为可能会漏信号或者失真,比如: 第一种办法是开环解决方案,也就是人为设置目标信号脉宽大于1.5倍的周期。但是容易和设计要求冲突 所以第二个大方法是闭环解决方案,也就是从改善同步方

    2024年02月03日
    浏览(49)
  • 基于vivado(语言Verilog)的FPGA学习(2)——zedboard开机测试和程序烧写

    终于找到之前写的部分了,在OneNote上,以后还是专注写在一个地方 ZedBoard 可以通过四个不同的方法烧写,这些方法是: USB-JTAG 这是默认的并且是最直接的烧写 ZedBoard 的方法 , 这只要通过 ZedBoard 工具包的 USB 到 micro-USB 连接线就可以直接完成。 传统 JTAG 板卡上有一个可用的

    2024年02月16日
    浏览(56)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包