DDS频率控制字设计详解

前言:
DDS的频率精度受限于fs/2N,其中,2N为频率控制字寄存器宽度。书上说,N可以比查找表的地址宽度大,到时候只需要截取高位送到查找表即可。说的很粗糙,怎么量化分析这个过程?为什么只需要截取高位呢?本文将带你分析一下这个问题。

首先,假定我们需要产生模拟域频率为fc的正弦信号,时钟频率为fs,采样周期为Ts=1/fs

(1)x(t)|t=nTs=cos(2πfct)|t=nTs=cos(2πfc/fsn)

如果查找表存了整个周期的正弦值,那么地址范围从[0:1:2N1]对应了相位的[0:1/2N:12N],在式(1)中,相位为

phase=fc/fsn

那么查找表的地址就应该是

(2)addr=floor(phase2N)=floor(fc/fsn2N), n=0,1,2,...,+

当时间无限延展,地址也会无限扩展,显然,由于信号是周期的,我们可以对地址进行绕回,也就是

(3)addr=mod(addr,2N)

如此生成的正弦波,将会是一个更为精确的数字。

算法中有一个关键的问题:
1.n是无限延展的,如何用定点数表示?
2.如何进行mod操作?
先来解答第一个问题,分析式(2),可以看出,每次addr的增量是固定的,即fc/fs2^N,那么我们可以把乘法替代为累加运算,也就是改写为addr = addr + fc/fs2^N的形式,发生溢出时正常溢出即可,因为无符号数溢出不会影响低位的正确性。
第二个问题,如何进行mod操作?这个也简单,直接取整数部分的低位即可。

algorithmInput:fcOutput:addr1.addr_temp=0;2.(2),const0=fc1/fs3.addr_delta=const02N4.:addr_temp=addr_delta+addr_temp;addr=mod(addr_temp,2N)

给出一个设计的例子。
fs=12MHz, fc=18Hz,查找表深度为216
首先,对 1/fs 进行定点化。

copy
>> fi(1/12e6,0,12) ans = 8.3324e-08 DataTypeMode: Fixed-point: binary point scaling Signedness: Unsigned WordLength: 12 FractionLength: 35 >> bin(ans) ans = '101100101111'

对输入频率进行量化,假定指定输入频率定点方案为u(16,0),即输入范围为0Hz~2^17-1Hz
对其进行全精度运算,const0=u(12,35)*u(16,0)=u(28,35)
计算地址增量,对const0乘2^16,相当于小数点右移16bit,结果为addr_delta = u(28,19),二进制表示不变
对addr_temp做加法,addr_temp需要确保有16位整数值,以容纳所有可能的wrap,故运算结果应为u(35,19)
addr为取了整数位的addr_temp,即量化方式位wrap,量化结果为u(16,0)。这一步实际上就是引言中对频率控制字寄存器取高位的步骤。
给出伪Verilog代码:

copy
module dds_inftyPrecise ( input clk,rstn input [15:0] fc, output [15:0] addr ) wire [11:0] 1_fs = 12'b101100101111; wire [27:0] const0 = fc*1_fs; wire [34:0] addr_delta = {7'b0,const0}; reg [34:0] addr_temp; always @(posedge clk or negedge rstn) if(rstn==0) addr_temp<=0; else addr_temp<=addr_temp+addr_delta; assign addr = addr_temp[34-:16]; endmodule
posted @   蕉太羊  阅读(120)  评论(2编辑  收藏  举报
点击右上角即可分享
微信分享提示
🚀