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.

reg [31:0]	phase;
// The initial value is usually irrelevant
always @(posedge clock)
	// Allow for an D/A running at a lower speed from your FPGA
	if (sample_clock_ce)
		phase <= phase + frequency_step;

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.

frequency_step = 2^N * frequency_hz / sample_clock_rate_hz

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:

frequency_precision_hz = sample_clock_rate_hz / 2^N

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 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.

assign	sinewave = phase[31];

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.

always @(posedge clock)
	if (sample_clock_ce)
		sinewave <= sinewave_table[phase[31:24];

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:

always @(posedge clock)
if (sample_clock_ce)
	8'h00:  sinewave <= 7'h00;
	8'h01:  sinewave <= 7'h01;
	8'h02:  sinewave <= 7'h03;
	8'h40:  sinewave <= 7'h3f;
	8'h80:  sinewave <= 7'h00;
	8'hc0:  sinewave <= 7'h41;
	8'hfe:  sinewave <= 7'h7d;
	8'hff:  sinewave <= 7'h7f;

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.

reg	[6:0]	table [0:255];

initial table[0] = 7'h00;
initial table[1] = 7'h01;
initial table[2] = 7'h03;
initial table[3] = 7'h04;
initial table[4] = 7'h06;
// etc.

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:

@00000000 00 01 03 04 06 07 09 0a 0c 0d 0f 10 12 13 15 16 
@00000010 18 19 1a 1c 1d 1f 20 21 23 24 25 26 27 29 2a 2b 
@00000020 2c 2d 2e 2f 30 31 32 33 34 35 36 36 37 38 38 39 
@00000030 3a 3a 3b 3b 3c 3c 3d 3d 3d 3e 3e 3e 3e 3e 3e 3e 
@00000040 3f 3e 3e 3e 3e 3e 3e 3e 3d 3d 3d 3c 3c 3b 3b 3a 
@00000050 3a 39 38 38 37 36 36 35 34 33 32 31 30 2f 2e 2d 
@00000060 2c 2b 2a 29 27 26 25 24 23 21 20 1f 1d 1c 1a 19 
@00000070 18 16 15 13 12 10 0f 0d 0c 0a 09 07 06 04 03 01 
@00000080 00 7f 7d 7c 7a 79 77 76 74 73 71 70 6e 6d 6b 6a 
@00000090 68 67 66 64 63 61 60 5f 5d 5c 5b 5a 59 57 56 55 
@000000a0 54 53 52 51 50 4f 4e 4d 4c 4b 4a 4a 49 48 48 47 
@000000b0 46 46 45 45 44 44 43 43 43 42 42 42 42 42 42 42 
@000000c0 41 42 42 42 42 42 42 42 43 43 43 44 44 45 45 46 
@000000d0 46 47 48 48 49 4a 4a 4b 4c 4d 4e 4f 50 51 52 53 
@000000e0 54 55 56 57 59 5a 5b 5c 5d 5f 60 61 63 64 66 67 
@000000f0 68 6a 6b 6d 6e 70 71 73 74 76 77 79 7a 7c 7d 7f 

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:

initial $readmemh("table.hex", table);

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 to switch from a simple table look up to a 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.