FPGA学习之 直接数字频率合成器(DDS)
Posted 满足没有
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了FPGA学习之 直接数字频率合成器(DDS)相关的知识,希望对你有一定的参考价值。
FPGA学习之 直接数字频率合成器(DDS)
DDS的原理:
直接数字频率合成器(Direct Digital Synthesizer, DDS)是一种把数字信号通过 D/A 转换成模拟信号的数字合成技术。它有查表法和计算法两种基本合成方法。由于查表法结构简单,只需要在 ROM中存放不同相位对应的幅度序列,然后通过相位累加器的输出对其寻址,经过数/模转换和低通滤波(LPF)输出便可以得到所需要的模拟信号。DDS系统主要有相位累加器、波形存储器、数模(D/A)转换器和低通滤波器等四大结构组成
这里,我们只通过改变频率控制字来达到控制波形频率的目的。
原理图:
代码部分:
顶层:
module dds_top(
input clk ,
input rst_n ,
input [1:0] key_in ,
output [7:0] dout //dds的输出
);
//信号定义
wire [1:0] key_out ;
wire clk_100m ;
wire locked ;
//模块例化
key_debounce /*#(.KEY_W(2)) */u_key(
.clk (clk ),
.rst_n (rst_n ),
.key_in (key_in ),
.key_out (key_out ) //检测到按下,输出一个周期的高脉冲,其他时刻为0
);
DDS u_DDS(
.clk (clk_100m ),
.rst_n (rst_n ),
.freq_set (key_out[0] ),//设置频率控制字
.set_done (key_out[1] ),//设置完成
.dout (dout ) //输出数据
);
pll u_pll( //锁相环例化
.areset (~rst_n ),
.inclk0 (clk ),
.c0 (clk_100m ),
.locked (locked )
);
endmodule
DDS模块:
module DDS(
input clk ,
input rst_n ,
input freq_set ,//设置频率控制字
input set_done ,//设置完成
output [7:0] dout //输出数据
);
//信号定义
reg [7:0] fcw_tmp ; //频率控制字 0--255
reg [7:0] fcw ; //中间寄存控制字
reg [9:0] phase_accum ; //相位累加器寄存器
wire [7:0] q_out ;
//fcw
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
fcw_tmp <= 0;
end
else if(freq_set)begin
fcw_tmp <= fcw_tmp + 1;
end
else if(set_done)begin
fcw_tmp <= 0;
end
end
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
fcw <= 1;
end
else if(set_done)begin
fcw <= fcw + fcw_tmp;
end
end
//phase_accum
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
phase_accum <= 0;
end
else begin
phase_accum <= phase_accum + fcw;
end
end
//dout
assign dout = q_out;
//正弦波数据查找表
rom rom_inst (
.address (phase_accum ),
.clock (clk ),
.q (q_out )
);
endmodule
按键消抖模块:
//按键消抖模块
module key_debounce(
input clk,
input rst_n,
input [1:0] key_in,
output reg [1:0] key_out
);
//parameter KEY_W = 2;
parameter TIME_20MS = 100000;
//当检测到下降沿之后,计数使能拉高,计数器开始计数计时20ms
reg [19:0] cnt;
wire add_cnt;
wire end_cnt;
reg add_flag;
wire nedge;
reg [1:0] key_r0;
reg [1:0] key_r1;
always@(posedge clk or negedge rst_n)begin
if(~rst_n)
cnt <= 0;
else if(add_cnt)begin
if(end_cnt)
cnt<=0;
else
cnt<=cnt+1;
end
end
assign add_cnt = add_flag;
assign end_cnt = add_cnt && cnt ==TIME_20MS - 1;
//当检测到下降沿之后,使能信号拉高
always@(posedge clk or negedge rst_n)begin
if(~rst_n)
add_flag <= 0;
else if(nedge)begin
add_flag <=1;
end
else if(end_cnt)begin
add_flag <=0;
end
end
//进行同步打拍产生下降沿
always@(posedge clk or negedge rst_n)begin
if(~rst_n)begin
key_r0<=1;
key_r1<=1;
end
else begin
key_r0 <= key_in;//同步
key_r1 <= key_r0;//打拍
end
end
assign nedge = ~key_r0 & key_r1;
always@(posedge clk or negedge rst_n)begin
if(~rst_n)
key_out<=0;
else
key_out<=end_cnt?~key_r1:0;
end
endmodule
这里我们利用按键来控制频率控制字改变,两个按键,一个控制增加,一个将增加的值设置给频率控制字。通过频率控制字来改变寻址的地址,达到控制数据输出频率的目的。
上图就是我们要输出的波形,每个数据8bit,一共1024个。利用Mif_Maker2010软件画图并产生 .mif文件(存储图像中各点数据)。然后将其保存在ROM中,根据输入的地址读取相应的值。
signal tap仿真输出效果:
这是放大之后的图像,可以看到就是一个一个的点,我们控制步长(频率控制字)就可以改变它的频率
以上是关于FPGA学习之 直接数字频率合成器(DDS)的主要内容,如果未能解决你的问题,请参考以下文章
FPGA教程案例28基于FPGA的DDS直接数字频率合成器之一——原理介绍
FPGA+sin基于DDS(直接数字合成)的正弦信号发生器模块FPGA实现