DDS频率控制字设计详解
前言:
DDS的频率精度受限于,其中, 为频率控制字寄存器宽度。书上说,N可以比查找表的地址宽度大,到时候只需要截取高位送到查找表即可。说的很粗糙,怎么量化分析这个过程?为什么只需要截取高位呢?本文将带你分析一下这个问题。
首先,假定我们需要产生模拟域频率为
如果查找表存了整个周期的正弦值,那么地址范围从
那么查找表的地址就应该是
当时间无限延展,地址也会无限扩展,显然,由于信号是周期的,我们可以对地址进行绕回,也就是
如此生成的正弦波,将会是一个更为精确的数字。
算法中有一个关键的问题:
1.n是无限延展的,如何用定点数表示?
2.如何进行mod操作?
先来解答第一个问题,分析式
第二个问题,如何进行mod操作?这个也简单,直接取整数部分的低位即可。
给出一个设计的例子。
首先,对 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代码:
copymodule 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
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步