目录
一、认识DDS
- 定义: DDS即数字合成器,可以用做信号发生器,用来产生一些数字意义上的波形(即波形是不连续的)。
- 电路组成:DDS由相位累加器、只读存储器(ROM)、数模转换器(DAC)、低通平滑滤波器(LPF)构成。在时钟脉冲的控制下,频率控制字K由累加器累加得到相应的相码,相码寻址ROM进行相码-幅码变换输出不同的幅度编码,再经过DAC得到相应的阶梯波,最后经低通滤波器对阶梯波进行平滑,即得到由频率控制字K决定的连续变化的输出波形。
- 输出频率(fo)与频率控制字(K)之间的关系:
二、DDS设计
设计目标
目标1 DDS电路核心RTL
- 本阶段目标是设计一个DDS的核心RTL代码。
- 使用Matlab生成DDS的波表ROM(DDS的波表数据为2补码的格式)
- 验证方法:(1)使用RTL View观察电路的RTL结构 (2)使用Quartus的波形仿真器观察DDS的输出
模块:
1、module powerup_reset()
// 上电后自动生成复位信号,用于复位其他电路模块
// 根据Altera器件手册,芯片中的D触发器的上电值为0
// 工作原理,使用一个计数器,上电后自动计数到最大值,然后保持不变
// 在计数器计数到最大值之前,输出复位有效信号,之后输出复位无效信号
2、module button_in_out()
功能:模块用于按键输入,带有去抖电路
按键去抖原理:使用计数器,计数器每隔20毫秒会达到最大值然后溢出,在计数器达到
溢出值的 8/8, 7/8, 6/8, 0/8 时刻对按键的值进行采样,如果全部采样值相同则说明
没有抖动发生输出采样值,否则认为发生了抖动,输出值保持不变
时间轴方向 ---------------------------------------------->
按键采样值 :v0, v1, v2 v3
计数器值 :0, 1, 2, .... 6/8 max, 7/8 max, max
|<------计数器溢出时间 10ms------->|
模块的重用,根据时钟速率,合理配置计数器的溢出值,使得溢出时间为10毫秒
3、module dds_core_sin (DDS核心部分)
module dds_core_sin(
CLK , // clock, posedge valid
RST , // reset, high level reset
FWEN , // frequency word update enable, high level enable
FWIN , // input frequency word
CLKOUT, // output clock
SINOUT); // sine signal output, 2's complement format
input CLK;
input RST;
input FWEN;
input [32-1:0] FWIN;
output[12-1:0] SINOUT;
output CLKOUT;
parameter FW_WL = 32; // frequency word word length in bit
parameter RA_WL = 10; // rom address word length in bit
parameter RD_WL = 12; // rom data word word length in bit
reg [FW_WL -1:0] fwin_R; // freq word DFF
reg [FW_WL -1:0] acc_R; // phase ACC DFF
reg [RA_WL -1:0] addr_R; // rom address DFF
reg [RD_WL -1:0] sinout_R; // sin wave output DFF
wire [RD_WL -1:0] romout_W; // rom data output wire
always @ (posedge CLK or posedge RST) begin
if(RST) begin
fwin_R <= 0;
acc_R <= 0;
addr_R <= 0;
sinout_R <= 0;
end
else begin
// update fwin_R DFF
if(FWEN)
fwin_R <= #1 FWIN;
else
fwin_R <= #1 fwin_R;
// update acc_R
acc_R <= #1 fwin_R + acc_R;
// update addr_R, the acc_R high RA_WL is rom address
addr_R <= acc_R[FW_WL-1:FW_WL-1-(RA_WL-1)];
// update output DFF
sinout_R <= #1 romout_W;
end
end
DDS_CORE_ROM u_sinrom(
.CLK (CLK ), // clock
.RA (addr_R ), // read address
.RD (romout_W )); // read data
assign SINOUT = sinout_R;
assign CLKOUT = CLK;
endmodule // module dds_core
4、module top_sin_wave
本设计功能
// 生成不同频率的正弦波
// 输入:用户按键UP,DOWN
// 输出:2补码格式的波形
// 行为:以1MHz为步进,用户通过UP/DOWN按键生成1MHz~10MHz不同频率的正弦波
5、module DDS_CORE_ROM()
RTL(本设计加入了额外的D触发器流水线以减小ROM的I/O延迟带来的影响):
目标2 DDS开发板测试平台
- 本阶段目标是在开发板上运行DDS电路模块
- 使用按键来控制频率字的改变
- 设定频率的UP和DOWN按键,让DDS轮流输出1MHz,2MHz,....10MHz的时域波形
- 验证方法:使用Quartus的Signal TAP 观察DDS的输出波形
- 需要调节Signal TAP的观察格式为“有符号数的曲线”模式
1MHz:
3MHz:
6MHz:
10MHz:
- 验证方法:
- 导出 Signal TAP 的捕获数据至电脑(生成List文件)
- 用UltraEdit的列操作模式编辑数据的格式,使之成为一个Matlab的变量定义文件
复制采样点数据。新建Excel,粘贴,上方选择数据栏,然后选择分列,并选择固定宽度分列。
复制需要的SINOUT中的数据保存并到matlab里进行频谱分析。
...
- 使用Matlab分析DDS生成的正弦信号的频谱纯度
打开路径下的
并将上面加入matlab中的数据也打开,运行即可得到频谱图。
注意:红线位置需要更改为导入数据所在文件夹的名字。
可见:在每个图中,所要生成的频率分量幅度都是最高的。其他频率分量都有至少50dB的衰减,信号底噪在-100dB左右。在数字信号处理课程中学习设计的滤波器阻带衰减均在四五十dB左右,所以这个频谱纯度比较符合。
三、DDS设计要点
- 理解DDS的工作原理,为何它能生成不同频率的波形
- 根据时钟频率和输出波形的频率来计算DDS的频率字
- 下图展示了在一个 5比特的相位累加器,4比特的波形ROM地址线宽的DDS中,相位增量为1、2、4的情况下,输出波形和相位累加器以及ROM地址的关系
- 图中的红色数字是相位累加器的数值,黑色数字是相位累加值截断之后的ROM地址
四、实验作业
掌握DDS的原理,并且能够回答以下问题
1、如何根据CLK频率和输入频率字来设定输出波形的频率
输出频率(fo)与频率控制字(K)之间的关系:
2、补码格式能够直接送给DAC么?为什么仿真工具里观察数据有多种选项,
比如unsigned/hex/binary/signed decimal 等等
有符号数的补码要将最高位取反后送入DAC。有符号数的补码正数符号位为0,负数符号位为1。其他位正数为2进制,负数为2进制取反加1。将最高位取反之后正好是从小到大映射到无符号数范围内,即可实现生成无符号数的正弦波。
不同的数据形式对应不同的数据格式,观察到的效果也会不同。
3、如何自动生成波表ROM的verilog代码?
使用Matlab生成DDS的波表ROM。
4、如何调节ROM的地址空间容量和数据字长?调节这些参数有什么意义和代价?
更改RA_WL,RA_WL为ROM地址数据长度。降低地址容量会使能生成的最低频率升高,但ROM所需的存储空间也变少。增加地址容量可以生成更低频率的信号。但增加地址容量如果超过了目前ROM的存储范围,就需要扩充ROM的存储值,就需要更长的代码和更多的存储空间。
调节数据字长:更改RD_WL,RD_WL为ROM输出数据长度。增加字长则会提高精度,但需要更多的端口,如果字长超过了目前ROM的存储字长则需要提高ROM存储值的精度,同时也要求更多的存储空间。缩短字长会降低精度,但也减少了对端口的使用量。
5、如何评价DDS输出波形的质量?
可以用matlab进行频谱波形仿真。