第35讲:简易DDS信号发生器的设计与验证
理论部分
DDS是直接数字式频率合成器(Direct Digital Synthesizer),是一项关键的数字化技术。
与传统的频率合成器相比,DDS具有低成本、低功耗、高分辨率和快速转换时间等优点。
设计与实现
实验目标:实现四种波形的切换
各子功能模块设计
系统框图绘制
key_filter
`timescale 1ns/1ns
module key_filter
#(
parameter CNT_MAX = 20'd999_999 //计数器计数最大值
)
(
input wire sys_clk , //系统时钟50Mhz
input wire sys_rst_n , //全局复位
input wire key_in , //按键输入信号
output reg key_flag //key_flag为1时表示消抖后检测到按键被按下
//key_flag为0时表示没有检测到按键被按下
);
//reg define
reg [19:0] cnt_20ms ; //计数器
//cnt_20ms:如果时钟的上升沿检测到外部按键输入的值为低电平时,计数器开始计数
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
cnt_20ms <= 20'b0;
else if(key_in == 1'b1)
cnt_20ms <= 20'b0;
else if(cnt_20ms == CNT_MAX && key_in == 1'b0)
cnt_20ms <= cnt_20ms;
else
cnt_20ms <= cnt_20ms + 1'b1;
//key_flag:当计数满20ms后产生按键有效标志位
//且key_flag在999_999时拉高,维持一个时钟的高电平
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
key_flag <= 1'b0;
else if(cnt_20ms == CNT_MAX - 1'b1)
key_flag <= 1'b1;
else
key_flag <= 1'b0;
endmodule
key_control
`timescale 1ns/1ns
module key_control
(
input wire sys_clk , //系统时钟,50MHz
input wire sys_rst_n , //复位信号,低电平有效
input wire [3:0] key , //输入4位按键
output reg [3:0] wave_select //输出波形选择
);
//parameter define
parameter sin_wave = 4'b0001, //正弦波
squ_wave = 4'b0010, //方波
tri_wave = 4'b0100, //三角波
saw_wave = 4'b1000; //锯齿波
parameter CNT_MAX = 20'd999_999; //计数器计数最大值
//wire define
wire key3 ; //按键3
wire key2 ; //按键2
wire key1 ; //按键1
wire key0 ; //按键0
//wave:按键状态对应波形
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
wave_select <= 4'b0000;
else if(key0 == 1'b1)
wave_select <= sin_wave;
else if(key1 == 1'b1)
wave_select <= squ_wave;
else if(key2 == 1'b1)
wave_select <= tri_wave;
else if(key3 == 1'b1)
wave_select <= saw_wave;
else
wave_select <= wave_select;
//------------- key_fifter_inst3 --------------
key_filter
#(
.CNT_MAX (CNT_MAX ) //计数器计数最大值
)
key_filter_inst3
(
.sys_clk (sys_clk ) , //系统时钟50Mhz
.sys_rst_n (sys_rst_n) , //全局复位
.key_in (key[3] ) , //按键输入信号
.key_flag (key3 ) //按键消抖后标志信号
);
//------------- key_fifter_inst2 --------------
key_filter
#(
.CNT_MAX (CNT_MAX ) //计数器计数最大值
)
key_filter_inst2
(
.sys_clk (sys_clk ) , //系统时钟50Mhz
.sys_rst_n (sys_rst_n) , //全局复位
.key_in (key[2] ) , //按键输入信号
.key_flag (key2 ) //按键消抖后标志信号
);
//------------- key_fifter_inst1 --------------
key_filter
#(
.CNT_MAX (CNT_MAX ) //计数器计数最大值
)
key_filter_inst1
(
.sys_clk (sys_clk ) , //系统时钟50Mhz
.sys_rst_n (sys_rst_n) , //全局复位
.key_in (key[1] ) , //按键输入信号
.key_flag (key1 ) //按键消抖后标志信号
);
//------------- key_fifter_inst0 --------------
key_filter
#(
.CNT_MAX (CNT_MAX ) //计数器计数最大值
)
key_filter_inst0
(
.sys_clk (sys_clk ) , //系统时钟50Mhz
.sys_rst_n (sys_rst_n) , //全局复位
.key_in (key[0] ) , //按键输入信号
.key_flag (key0 ) //按键消抖后标志信号
);
endmodule
dds
`timescale 1ns/1ns
module dds
(
input wire sys_clk , //系统时钟,50MHz
input wire sys_rst_n , //复位信号,低电平有效
input wire [3:0] wave_select , //输出波形选择
output wire [7:0] data_out //波形输出
);
//parameter define
parameter sin_wave = 4'b0001 , //正弦波
squ_wave = 4'b0010 , //方波
tri_wave = 4'b0100 , //三角波
saw_wave = 4'b1000 ; //锯齿波
parameter FREQ_CTRL = 32'd42949 , //相位累加器单次累加值
PHASE_CTRL = 12'd1024 ; //相位偏移量
//reg define
reg [31:0] fre_add ; //相位累加器
reg [11:0] rom_addr_reg; //相位调制后的相位码
reg [13:0] rom_addr ; //ROM读地址
//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;
//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
rom_addr_reg <= fre_add[31:20] + PHASE_CTRL;
rom_addr <= rom_addr_reg;
end //正弦波
squ_wave:
begin
rom_addr_reg <= fre_add[31:20] + PHASE_CTRL;
rom_addr <= rom_addr_reg + 14'd4096;
end //方波
tri_wave:
begin
rom_addr_reg <= fre_add[31:20] + PHASE_CTRL;
rom_addr <= rom_addr_reg + 14'd8192;
end //三角波
saw_wave:
begin
rom_addr_reg <= fre_add[31:20] + PHASE_CTRL;
rom_addr <= rom_addr_reg + 14'd12288;
end //锯齿波
default:
begin
rom_addr_reg <= fre_add[31:20] + PHASE_CTRL;
rom_addr <= rom_addr_reg;
end //正弦波
endcase
//------------------------- rom_wave_inst ------------------------
rom_wave rom_wave_inst
(
.address (rom_addr ), //ROM读地址
.clock (sys_clk ), //读时钟
.q (data_out ) //读出波形数据
);
endmodule
top_dds
`timescale 1ns/1ns
module top_dds
(
input wire sys_clk , //系统时钟,50MHz
input wire sys_rst_n , //复位信号,低电平有效
input wire [3:0] key , //输入4位按键
output wire dac_clk , //输入DAC模块时钟
output wire [7:0] dac_data //输入DAC模块波形数据
);
//wire define
wire [3:0] wave_select ; //波形选择
//dac_clka:DAC模块时钟
assign dac_clk = ~sys_clk;
//-------------------------- dds_inst -----------------------------
dds dds_inst
(
.sys_clk (sys_clk ), //系统时钟,50MHz
.sys_rst_n (sys_rst_n ), //复位信号,低电平有效
.wave_select (wave_select), //输出波形选择
.data_out (dac_data ) //波形输出
);
//----------------------- key_control_inst ------------------------
key_control key_control_inst
(
.sys_clk (sys_clk ), //系统时钟,50MHz
.sys_rst_n (sys_rst_n ), //复位信号,低电平有效
.key (key ), //输入4位按键
.wave_select (wave_select) //输出波形选择
);
endmodule