NCO bit true model in a single equation

kaz - October 23, 2011 Coded in Matlab

In Hardware design of NCO(Numerically Controlled Oscillator), a popular method is to use one cycle worth of sine data stored in memory(LUT), which is then addressed by a phase pointer derived from a phase accummulator. Many finite parameters affect the NCO output such as amplitude resolution, phase accumulator resolution and LUT resolution. In turn, these variations affect its bit true modelling. In the following code, a single equation is used to model all variables.

It is then compared with a more friendly piece of code that models the hardware NCO more closely.

Note: Some NCOs interpolate intermediate values from LUT. This model does not cover that case.

%NCO bit true model
clear all; close all;

%example NCO parameters
n = 20000;                     %number of test samples
A = 2^15 - 1;                  %max amplitude, amplitude resolution 16 bit signed
M = 2^32;                      %NCO accumulator phase resolution
inc = round(M*.001);           %NCO accumulator phase increment 
k = 2^12;                      %lut phase resolution (lut size), may equal M

%single equation for NCO bit true model
y1 = round(A*sin(2*pi*round(k*mod((0:n-1)*inc/M,M))/k));      

%%%%%%%%%%%%%%%%%%%%%%%%% equivalent code %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
lsb = log2(M) - log2(k);                 %LSBs discarded when addressing
lut = round(A*sin(2*pi*(0:k-1)/k));      %lut, one cycle sine data

ptr = 0; 
addr = 0;
for i = 1:n 
    y2(i) = lut(addr+1);          %add 1 for matlab LUT
    ptr = mod(ptr + inc, M);      %phase accumulator(ramp)
    addr = round(ptr/2^lsb);      %discard LSBs
    addr(addr >= k) = addr - k;   %check address overflow

plot(y1 - y2,'g--')