数控振荡器NCO使用verilog实现时NCO初始值和上限值设定时的注意事项

设驱动时钟频率为Fc,相位增量为M,寄存器计数值上限为uplimit,输出频率为Fo,则Fo=Fc*M/uplimit;

 

在进行verilog编程时,以下UP=uplimit

always@(posedge Fc)
if(nco >= UP) begin

  nco <=  nco - UP; 

  pulse <= 1;
end
else begin
  pulse <= 0;
  nco <=  nco + M;
end
end

 

经仿真可以发现,这个pulse的频率并不是Fo=Fc*M/UP,而是Fc*M/(UP+M)

这是为什么呢?

我们用一个简单的例子进行一下做一个假设,以便清楚的说明问题:

设Fc=16MHz,M=2,uplimit=8,则输出Fo=16*2/8=4MHz

但按以上程序实现时,nco初始值为UP,则判断 if(nco >= UP) 成立,执行nco <= nco - UP; 后nco变为0 ,以下列出了8个时钟的nco值:

第n个时钟   1    2    3    4    5    6    7    8……

nco的值       0    2    4    6    8    0    2    4…… 

由此可见,nco的值是0-2-4-6-8-0-2-4-6-8……周期为5个值的循环,而我们期待的是4个值的循环,问题出现在nco的循环初值和终值的选取上,初值和终值的选取应保证nco的循环周期是4个值即可……

因此可以将UP设为uplimit-M,或者将初值设为 nco <= nco - UP+M就可以了……

 

也许会有朋友问为什么nco到达上限后不将其设为0(或者M),而是设为nco-UP(或者nco-UP+M),这是因为并不是每一个我们需要产生的Fo的频率都是Fc的整数分之一,当Fo不是Fc的整数分之一时,如果到上限后清零nco的话会产生一个固定的频率偏差,而如程序中所设则可以使用pulse的输出频率从平均的意义上来讲是所需的Fo,例如:

当up=7时,所产生的频率为Fo=16*2/7=32*7=4.57

按程序中所设(此处将UP按上所阐述设为limit-M=5):

第n个时钟 1 2 3 4 5 6 7 8 9 10 11  12……

nco的值      0 2 4 6 1 3 5 0  2  4  6  1……

即一次是0-2-4-6的四值循环,一次是1-3-5的三值循环,四值循环的输出频率为Fo=Fc/4=4MHz 和Fo=Fc/3=16/3=5.33,平均频率为Fo=Fc/(3+4)/2=4.57……

注意:这里计算平均频率不能简单的将两个输出频率相加除2……


但是,若if(nco >= UP) 成立后直接将nco置0,则nco的循环将一直是0-2-4-6的四值循环,输出频率也将一直是4Mhz,并非是需要的4.57Mhz了……

 

你可能感兴趣的:(编程,UP)