赞
踩
用Verilog通过DDS合成正弦波信号
转自:http://bbs.elecfans.com/jishu_421844_1_1.html
主要原理:
DDS:直接数字合成,正弦波0-2pi周期内,相位到幅度是一一对应的。首先需要的将正弦波查询表存储起来,然后在时钟下,通过相位累加模块和地址查询模块实现正弦波信号。
一个更好理解的DDS算法 的基本原理:
DDS是直接式数字频率合成的简称。它在无线通信系统实现中是一门关键技术。其实,DDS在FPGA中的实现方法说白了就是在定义好的ROM数据中寻址并找到该地址对应的波形数据。在系统参考时钟的驱动下,通过控制频率控制字来驱动相位累加寄存器数值的变化,从而是在ROM中寻址并找到对应数据,最后输出为波形数据。其中,在每一个系统时钟脉冲来临时,相位累加寄存器都会相应叠加一次频率控制字。其实,频率控制字的功能就是控制步进长度,也就是形成的波形的频率和系统时钟频率的比例关系,最终可以确定输出波形的频率。比如要输出正弦波,系统参考时钟频率为20M,输出每位宽度为10bit,则令频率控制字位宽为20bit,f(out)=(频率控制字/2^20)*f(clk)。这样就可以控制输出波形的频率。
正弦波查询表:存储的是量化的正弦波在一个周期的幅度信息(幅度的“地址”也蕴含相位)。幅度的地址数目决定了相位量化的误差。而存储每一个幅度的比特数决定了幅度的量化误差。可以通过Quartus II的IP核资源创建。
Verilog编写的DDS模块主要由三部分组成,
一、相位累加器,用于决定输出信号频率的范围和精度;
二、正弦函数功能表(波形存储器),用于存储经量化和离散后的正弦函数的幅值;
三、查表模块,相位累加器的输出地址查表。
两种方法可以改变输出信号的频率:
(1)改变查表寻址的时钟频率,可以改变输出波形的频率。
(2)改变寻址的步长来改变输出信号的频率。步长即为对数字波形查表的相位增量。由累加器对相位增量进行累加,累加器的值作为查表地址。
输出正弦波周期为fo=fc* K/2^N,最小分辨率为f=fc/2^N。(通过fc和K控制正弦波频率精度) 其中,N 为累加器位宽,K 为步长,fc 为时钟频率。计数模(最大值):M=2^N。
一般正弦波表幅度地址位宽与累加的查表地址位宽不同,按前者位宽取后者对应高位的位宽即可。(具体见实例)
Verilog程序
1、sine_top.v顶层设计
`timescale 10ns /1ns //时延:时间单位/时间精度
module sine_top(//采用直接数字合成(Direct Digital Synthesis)
sine,
clk,
rst_n
);
output[7:0]sine; //输出叠加的正弦波
input rst_n;
input clk;
wire [15:0] rom_ad; //16bit内部连接线,传递相位增量(频率控制字的整数倍)
wire [9:0] address; //10bit
wire signed [7:0] sine1; //8位大小的存储器阵列
assign sine=sine1;
//M=2^N=2^16=65536(N控制频率分辨率,fc/M),通过相位增量K(频率控制字)控制输出频率。fout=K*fclk/M
//通过查表输出正弦波,一个周期内,1024(10位)点 X 8bit(幅度量化精度)
//fclk=100MHz(10ns)
//10MHz //带参数的模块实例化
adder #(.fcw(6554)) uut0( //10MHz-->6554(频率控制字),实例化adder模块,uut0
.clk(clk),
.rst(rst_n),
.sum(rom_ad) //rom_ad,16bit大小内部连接线
);
assign address=rom_ad [15:6];//address,10bit取rom_ad高10位作为地址,与表中1024个值一一对应。
rom_sine0 rom0( //IP核
.address(address),//输入10位的地址,查出正弦波表对应的幅度值
.clock(clk),
.q(sine1) //输出结果
);
endmodule
2、adder.v文件,累加模块
module adder#(parameter fcw=16'd10000)( //参数为16位大小 默认参数(10000)
sum,
clk,
rst
);
output [15:0] sum; //输出地址
input clk;
input rst;
reg [15:0] sum; //初值
always @(posedge clk)//正沿触发
begin
if(!rst) //复位0有效
sum<=16'd0;
else
sum<=sum+fcw; //求和
end
endmodule
3、sine_stimulate.v仿真测试文件
//sine_stimulate.v,my testbench
`timescale 1ns/1ns
modulesine_stimulate; //
reg rst_n; //复位信号
reg clk; //时钟信号
wire signed[7:0]sine;
sine_top uut0(
.sine(sine),
.clk(clk),
.rst_n(rst_n)
);
initial //过程语句,只执行一次(与always不同)
begin
clk=0;
rst_n=0;
#50; //延迟50ns
rst_n=1;
end
always #5 clk=~clk;
endmodule
Quartus II 13.0 和ModelsimSE 10.1a联合仿真结果
仿真输出的正弦波:
插值后的正弦波图形:
这就是我用Verilog编程,采用DDS合成正弦波的所有流程。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。