• 方案介绍
  • 相关推荐
申请入驻 产业图谱

DDS波形发生器Verilog QuartusII正点原子开发板

09/29 08:31
920
加入交流群
扫码加入
获取工程师必备礼包
参与热点资讯讨论

概要信息

  • 名称:DDS波形发生器Verilog Quartus II正点原子开发板
  • 软件:QuartusII
  • 语言:Verilog

代码功能

该工程实现一个基于数控直接数字合成(DDS)的波形发生器,能输出正弦、方波三角波锯齿波四种波形;通过按键选择波形并通过加/减键调整输出频率;波形数据经 ROM 查表后送往 DAC 接口,同时将频率在 6 位数码管上实时显示。即实现了下图中的基本要求(不含发挥)

请添加图片描述

代码实现思路

整体采用分层模块化设计:顶层 top.v负责端口映射,top_dds.v集成子模块并生成 DAC 时钟。核心dds.v使用 32 位相累加器(fre_add)累加步长FREQ_CTRL以控制频率,将高位作为 ROM 地址并通过地址偏移选择不同波形(各波形在 ROM 中按区间排列)。rom_wave提供 8-bit 波形点序列。按键经key_filter去抖并由key_ctl解码为波形选择信号,f_word_set根据加/减键调整FREQ_CTRL并维护显示计数;seg_led 负责多位数码管的分时驱动与数字解码。

简单模块连接示意:

top.v
└─ top_dds.v
├─ dds.v ── rom_wave (ROM)
├─ key_ctl.v
├─ key_filter.v (用于按键去抖,f_word_set 中亦实例化)
├─ f_word_set.v
└─ seg_led.v / count.v(用于数码管显示和计时)

该方法优点:结构清晰、易扩展(增加波形或改变ROM深度只需修改ROM与地址映射);基于查表的波形输出效率高,适合 FPGA 实时输出。注意相位偏移(PHASE_CTRL)与 ROM 地址位宽需一致以保证波形连续性。

上板演示

本代码已在开发板验证

请添加图片描述
请添加图片描述

代码结构(各模块一句话说明)

  • top.v:顶层端口映射,实例化 top_dds 并连接外设引脚(DAC、按键、数码管)。
  • top_dds.v:系统整合模块,生成 DAC 时钟并把子模块(DDS、按键控制、数码管驱动、频率设置)串联起来。
  • dds.v:DDS 核心;32 位相累加器加步进量 FREQ_CTRL,通过高位索引 rom_wave 并用地址偏移区分四种波形,输出 8-bit 波形数据给 DAC。
  • rom_wave.*(ROM/初始化文件):查表存储波形数据(多个波形按地址区分),供 dds.v 读取。
  • key_filter.v:按键消抖模块,计时确认按键按下以产生稳定的按键触发信号。
  • key_ctl.v:根据按键编码产生波形选择信号 wave_select
  • f_word_set.v:频率步进管理,响应加/减键修改 FREQ_CTRL 并维护显示计数 cn
  • seg_led.v:数码管显示驱动,完成多位分时扫描和七段编码显示(包括小数点/符号处理)。
  • count.v:定时/采样模块,用于按周期输出当前 FREQ_CTRL 到显示或上层逻辑(与 seg_led/f_word_set 配合)。

设计注意点与建议

  • ROM 地址映射:当前设计将四种波形放在 ROM 的不同时段(偏移 0/4096/8192/12288),如需扩展精度应同时调整相位累加位宽与地址偏移量。
  • 定时与去抖:key_filter 使用计数器去抖,门限(CNT_MAX)应与系统时钟匹配以获得期望的按键响应时间。
  • 固定参数:PHASE_CTRL 等常量影响相位偏移,若需要相对相位控制或相位同步,建议增加相位寄存与外部控制接口。
  • 仿真与验证:建议对 dds.v 做时序仿真,观察相位累加器、ROM 读出与输出波形的一致性;在硬件上观察 DAC 输出并用示波器验证频率与波形类型。

关键源文件

trl/top.vtrl/top_dds.vtrl/dds.vtrl/key_ctl.vtrl/key_filter.vtrl/f_word_set.vtrl/seg_led.vtrl/count.v

部分代码展示:
`timescale  1ns/1ns
module  dds
(
    input   wire            sys_clk     ,//系统时钟,50MHz
    input   wire            sys_rst_n   ,//复位信号,低电平有效
    input   wire    [1:0]   wave_select ,//输出波形选择,通过之前的key_trl选好了波形
    input   wire    [31:0]  FREQ_CTRL,//频率选择,通过之前的f_word_set选好频率了
    output  reg             sin_wave_lab,
    output  reg             squ_wave_lab,
    output  reg             tri_wave_lab,
    output  reg             saw_wave_lab,
    output  wire            dac_clk,//输入DAC模块时钟
    output  wire    [7:0]   data_out        //波形输出
);

//********************************************************************//
//****************** Parameter and Internal Signal *******************//
//********************************************************************//
//parameter define
parameter   sin_wave    =2'b11     ,//正弦波
            squ_wave    =2'b10     ,//方波
            tri_wave    =2'b01     ,//三角波
            saw_wave    =2'b00     ;//锯齿波

//FREQ_CTRL=32'd42949,//相位累加器单次累加值500HZ  
parameter   PHASE_CTRL  =12'd1024  ;//相位偏移量

//reg   define
reg     [31:0]  fre_add     ;//相位累加器
reg     [11:0]  rom_addr_reg;//相位调制后的相位码
reg     [13:0]  rom_addr    ;//ROM读地址

assign    dac_clk=~sys_clk;
//reg     sin_wave_lab=1'b1;
//reg     squ_wave_lab=1'b1;
//reg     tri_wave_lab=1'b1;
//reg     saw_wave_lab=1'b1;


//********************************************************************//
//***************************** Main Code ****************************//
//********************************************************************//
//fre_add:相位累加器
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n==1'b0)
        fre_add<=32'd0;
else
        fre_add<=fre_add + FREQ_CTRL;//频率选择,通过之前的f_word_set选好频率了

//rom_addr:ROM读地址
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n==1'b0)
        begin
            rom_addr        <=14'd0;
            rom_addr_reg    <=11'd0;
        end
else
case(wave_select)
        sin_wave://正弦波
            begin
                squ_wave_lab    <=1'b0;
                tri_wave_lab    <=1'b0;
                saw_wave_lab    <=1'b0;
                rom_addr_reg    <=  fre_add[31:20]+ PHASE_CTRL;//相位偏移量PHASE_CTRL
                rom_addr        <=  rom_addr_reg;
                sin_wave_lab    <=1'b1;
            end  		
        squ_wave://方波
            begin
                sin_wave_lab    <=1'b0;
                tri_wave_lab    <=1'b0;
                saw_wave_lab    <=1'b0;
                rom_addr_reg    <=  fre_add[31:20]+ PHASE_CTRL;
                rom_addr        <=  rom_addr_reg +14'd4096;
                squ_wave_lab    <=1'b1;
            end   			
        tri_wave://三角波
            begin
                sin_wave_lab    <=1'b0;
                squ_wave_lab    <=1'b0;
                saw_wave_lab    <=1'b0;
                rom_addr_reg    <=  fre_add[31:20]+ PHASE_CTRL;
                rom_addr        <=  rom_addr_reg +14'd8192;
                tri_wave_lab    <=1'b1;
            end 		
        saw_wave://锯齿波
        begin   
                sin_wave_lab    <=1'b0;
                squ_wave_lab    <=1'b0;
                tri_wave_lab    <=1'b0;
                rom_addr_reg    <=  fre_add[31:20]+ PHASE_CTRL;
                rom_addr        <=  rom_addr_reg +14'd12288;
                saw_wave_lab    <=1'b1;
            end
default://正弦波
            begin
                squ_wave_lab    <=1'b0;
                tri_wave_lab    <=1'b0;
                saw_wave_lab    <=1'b0;
                rom_addr_reg    <=  fre_add[31:20]+ PHASE_CTRL;
                rom_addr        <=  rom_addr_reg;
                sin_wave_lab    <=1'b1;
            end    
        endcase

//********************************************************************//
//*************************** Instantiation **************************//
//********************************************************************//
//------------------------- rom_wave_inst ------------------------
rom_wave    rom_wave_inst
(
.address(rom_addr   ),//ROM读地址
.clock(sys_clk    ),//读时钟
.q(data_out   )//读出波形数据
);
endmodule

代码下载(付费可见):

点击链接获取代码文件:http://www.hdlcode.com/index.php?m=home&c=View&a=index&aid=1547

相关推荐