Calculating AD9834 Frequency Register Values for Embedded Systems

One of the things I’m working on now is an RF signal generator using the AD9834. I’ve done this before and once the hardware is in place setting the frequency is pretty simple. Using the desired frequency and reference clock frequency you calculate a 28 bit constant that is loaded into the frequency register using the SPI interface. The equation used to calculate the constant is:

AD9834 frequency register equation

and if you are dealing with fixed frequencies it’s a small matter to precalculate the appropriate values of N and load them in when needed. However, when you are dealing with embedded systems without access to floating point numbers and want to calculate the values on the fly it gets a little more complicated.

Divide and Conquer

On way to approach the problem is to view the frequency as a binary number and precalculate that portion of the constant corresponding to each bit. The appropriate precalculated numbers are then added together to get the final value for the frequency register.

For example, assume a design with clock frequency = 40 MHz and a desired frequency = 1 kHz. The precalculated values (rounded to the nearest integer) are:

Frequency register bit value calculations

and the frequency register value is calculated as:

Frequency register example calculation

This method has the advantage of using only 32 bit additions to get the final value but requires up to 112 bytes of memory to store the precalculated values, the exact number depending upon the maximum desired frequency value.

Integer Arithmetic

The frequency register value can also be calculated using integer arithmetic.

First, rewrite the equation used to calculate the constant as:

Alternate AD9834 frequency register equation

The numerator of the fraction on the left hand side is simply the desired frequency shifted left 32 times. The division can be done using a shift-subtract algorithm. Using the values from the previous example the algorithm would be:

int64 mask = 0x8000000000000000;
int64 dividend = 1000 << 32;
int64 quotient = 0;
int acc = 0;
for (int i = 0; i < 64; i++)
{
    acc << 1;
    if ((dividend & mask) != 0)
        acc += 1;
    if (acc >= 40000000)
    {
        quotient |= mask;
        acc -= 40000000;
    }
    mask >> 1;
}
int64 freqreg = quotient >> 4;

At first glance this method appears to require working with 64 bit numbers. However, consider some features of the problem.

First, because of the Nyquist limit the desired output frequency is limited to values of less than one-half the clock frequency. Therefore, the result of the comparison in the for loop will always be false the first 32 times around the loop. This means that we can preload the accumulator with the value of the desired frequency, eliminate the first 32 times around the loop, and assume the top 32 bits of the quotient will be 0.

Second, the lower 32 bits of the dividend are always 0 so there is no need to do the mask check the last 32 times around the loop. We’ve already eliminated the first 32 times around the loop so the check can be removed completely and replaced with shifting the accumulator left each time through the loop.

Once we make these changes the algorithm becomes (again using values from the previous example):

int32 mask = 0x80000000;
int32 acc = 1000;
int32 quotient = 0;
for (int i = 0; i < 32; i++)
{
    acc << 1;
    if (acc >= 40000000)
    {
        quotient |= mask;
        acc -= 40000000;
    }
    mask >> 1;
}
int32 freqreg = quotient >> 4;

which requires only 32 bit numbers, well within the capabilities of embedded processors.

Update 14 December 2011:  Found an error in the 32 bit calculation where the accumulator should have been shifted prior to the comparison.  Fixed in the current post.

Advertisements

Comments are closed.

Tabula Candida

Doodles of a distracted historian

rtl-sdr.com

A blog about RTL-SDR (RTL2832) and cheap software defined radio

DuWayne's Place

Computers, Electronics, and Amateur Radio from KC3XM

QRP HomeBuilder - QRPHB -

Computers, Electronics, and Amateur Radio from KC3XM

Open Emitter

Computers, Electronics, and Amateur Radio from KC3XM

Ripples in the Ether

Emanations from Amateur Radio Station NT7S

m0xpd's 'Shack Nasties'

Computers, Electronics, and Amateur Radio from KC3XM

%d bloggers like this: