The simplest sine wave generator within an FPGA
Ever need a sine wave when working within an FPGA? When you see the solution to this problem presented below, you may never use a canned digital synthesizer again.
Digital Oscillator phase
The first step to building this synthesizer is creating the phase input for the sine wave you wish to create.
We’ve already discussed the ideal units for phase within an
FPGA
here.
Basically, you’ll want to keep track of phase in a digital unit that
naturally wraps at your word width, N. (We’ll arbitrarily choose to use
N=32
for our examples below.) To convert from radians to these digital
units, simply multiple by 2^N and divide by 2PI. Likewise to convert from
degrees to these digital units, multiple by 2^N and divide by 360.
Frequency in a digital synthesis system is nothing more than a change in phase. Hence, a phase can change by a small delta on every clock cycle to create the frequency you need. Something like the following will work well.
This assumes you have a signal (sample_clock_ce
) that is 1
anytime the DAC
needs an output, and 0
otherwise. This will allow you to work with
slower signal rates than your system clock rate if necessary. You can
also just set the sample_clock_ce
value to a constant 1
in order process samples at your
FPGA’s
clock rate.
The right frequency step will depend upon your sample clock rate. Note, this rate may be slower than your FPGA’s system clock rate.
To make certain we have the formula right, consider a frequency which is
at the Nyquist sample rate of one half of your sample clock rate. This
frequency should take two steps to wrap back to where it came from.
Looking at the frequency step above, in this case the frequency step would
become 2^(N-1)
and two steps (2*frequency_step
) would indeed wrap back
around. Smaller steps should naturally represent lower frequencies.
Let’s assume a 100MHz sample clock rate for the sake of discussion.
If you choose to represent both phase and frequency step with N=32
bits,
you can represent any frequency between zero and your sample clock rate
divided by two, with a precision given by:
This is nothing more than solving for the frequency associated with the difference between two steps. Equivalently, this is the frequency associated with a step of one, or the smallest frequency that this approach can generate.
If our system has a 100MHz sample rate clock, a 32-bit frequency step would allow us to represent any frequency between zero and 50MHz in steps of about 0.02 Hz.
Not bad, but how about generating a sine wave from this phase?
The “No more logic” Solution
Since I offered this post as the “Simplest Sine Wave Generator”, I feel compelled to provide the following even simpler solution:
If you don’t want to use any more logic than your phase generator requires, then just output the top bit of the phase accumulator. That’ll give you a square wave at the frequency you want — with 0.02Hz precision.
As this isn’t really much of a sine wave, but rather a square wave, let’s continue looking for a better alternative.
Digital Oscillator frequency output
Now that we know the phase of our outgoing digital oscillator, it’s time to generate the sine wave itself. Since an FPGA offers free lookup tables, let’s use them to generate our sine wave.
Notice that we only used the top 8-bits from the phase. This keeps our logic simple, while still giving you the full 0.02 Hz resolution we had above. While we could use an 8-bit phase accumulator alone, that would’ve only given us frequency steps in the 400kHz range.
What happens with the 32-bit phase is that eventually the upper 8-bits will repeat or skip steps as necessary to provide the frequency resolution you want.
Gosh, that was so easy, we could end this post right there. The task is done!
Before leaving the topic, though, let’s examine two more items: First, let’s look at the mechanics of setting the sinewave table above, and second let’s make some rough estimates as to the cost and performance of the synthesizer.
How to set the table?
Since all of the logic is captured within that sinewave table, perhaps we should spend some time working out how to set the values of the table. In general, there are three basic approaches for setting the values of the table. All three are roughly equivalent in the functionality they will use.
The first approach is to build a giant case statement:
The synthesizer will turn the logic from this case statement into the table lookup implementation we want.
The second approach would be to use an actual table read-only register array, and to set all of the values of the table with individual values of the sine wave as we want it.
This approach, though, get’s old really fast–especially if you are building it by hand. A better approach is to use $readmemh. (Be aware, in my experience Xilinx’s ISE can’t handle $readmemh.)
Using $readmemh, you’ll create a hexadecimal text file first. In our case, it would probably look something like:
The first part of the line indicates where in the array the coming values will be placed, whereas the rest of the line consists of values to be placed in the array separated by spaces.
Then, to use this approach, you’ll need one more line within your Verilog code to read and set your array:
where table.hex
is the name of your hexadecimal text file.
Given that you are trying to make a sine wave, and that a sine is a rather complex function, you might want to create this table via a C++ program instead of by hand (I did). Just remember: the maximum sine wave value needs to be +/- 63 since it’s the maximum 7-bit value that has an identical positive and negative integer value.
Estimating the Cost of the Synthesizer
While we’re essentially done here, having presented how to generate a quick and simple sine wave, let’s spend another moment or too looking at how many table entries we want (32, 64, 128, or 256), as well as how many bits wide the elements in the table should be.
In general, this will cost us one look up table per output bit in for each output sample our sinewave. However, on the Xilinx architecture, two output bits can share a 6-LUT if they share the same 5-bit inputs. Likewise it takes two 6-LUTs to look up a seven bit value, and four 6-LUTs to look up an 8-bit value. [Ref] Let’s examine the two ends of these possibilities therefore.
If we were to use 5-bit lookup tables, we’d have only 2^5=32
entries to the
sine wave table. A table size of 32 would allow us to divide the unit circle
up into steps separated by 11 degrees
.
This means that your sinewave would jump by at most 0.195
in value from one
phase to the next. Representing something with this level of precision only
takes about 4 bits, so this lookup would cost two 6-LUTs total.
That’s pretty cheap. The 32-bit phase update logic would likely cost more LUTs (16) than that.
At the other end of the spectrum, suppose we wanted to use 8-bits of phase.
We’d then be able to represent things at 360/2^8=1.4 degree
intervals. The
biggest jump in the sine wave would be about 0.024
units. Representing such
a number with that level of precision could easily be done with 7 bits.
Hence, this approach would cost 28 6-LUTs
. That’s still pretty cheap,
although now it costs more than phase calculation.
Better Approaches are Available
Our focus today has been on what it takes to generate a really cheap and
simple sine wave within an
FPGA.
At 28 LUTs
for the synthesizer and 16 LUTs
to track phase, I think we did
just that.
However, if you want to generate a higher quality sine wave, then you might wish either switch to a larger table, use a quarter wave table, or even switch from a simple table look up to a full CORDIC approach.
Perhaps we should come back and discuss that approach later? CORDIC’s aren’t that hard to build, and they make an excellent lesson for the beginner in how to design FPGA based algorithms.
All the rivers run into the sea; yet the sea is not full; unto the place from whence the rivers come, thither they return again. (Eccl 1:7)