0
点赞
收藏
分享

微信扫一扫

野火FPGA强化(3):简易DDS信号发生器


文章目录

  • ​​第35讲:简易DDS信号发生器的设计与验证​​
  • ​​理论部分​​
  • ​​设计与实现​​
  • ​​key_filter​​
  • ​​key_control​​
  • ​​dds​​
  • ​​top_dds​​

第35讲:简易DDS信号发生器的设计与验证

理论部分

DDS是直接数字式频率合成器(Direct Digital Synthesizer),是一项关键的数字化技术。

与传统的频率合成器相比,DDS具有低成本、低功耗、高分辨率和快速转换时间等优点。

野火FPGA强化(3):简易DDS信号发生器_系统时钟



设计与实现

实验目标:实现四种波形的切换

各子功能模块设计

野火FPGA强化(3):简易DDS信号发生器_系统时钟_02


系统框图绘制

野火FPGA强化(3):简易DDS信号发生器_fpga开发_03

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

野火FPGA强化(3):简易DDS信号发生器_sed_04

野火FPGA强化(3):简易DDS信号发生器_系统时钟_05

`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

野火FPGA强化(3):简易DDS信号发生器_正弦波_06


野火FPGA强化(3):简易DDS信号发生器_正弦波_07

`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

野火FPGA强化(3):简易DDS信号发生器_sed_08

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


举报

相关推荐

0 条评论