• 0

# designing a waveform array generator

## Question

in my design i need to calculate an array containing a waveform, (a sine for this example)

inputs of the block would be a memory containing an index of 1024 samples and a user-related period value.

output would be an array of 1024 samples written on ram

being amplitude and phase fixed the expression to calculate the single sample of the waveform would be

x = sin ( period * index (0-1023))

Could I instantiate 1024 blocks  so that the samples of the resulting array could be calculated concurrently?

## Recommended Posts

• 0

>> Could I instantiate 1024 blocks  so that the samples of the resulting array could be calculated concurrently?

It does not seem a likely design pattern. Before you try, sketch out the the resource usage.

More likely, you'd implement a single block that gives one sample per clock cycle and run it at 1024 times the frequency, then mux the outputs.

For example, assume the samples are for audio at 48 kHz, you'd need 48000*1024 = 49.152 MHz minimum, which is not much for an FPGA

##### Share on other sites
• 0

Here is a link to a good article on sine tone generation which talks about doing it without a table.  I have done this myself in a DSP.  Should be simple enough in an FPGA.

HTH

Clyde

##### Share on other sites
• 0

There are a number of ways to create a sine wave. It's important to know how you are going to use it, and if it's fixed or has to change, and other things like frequency, precision, how much phase noise can be tolerated etc. Then you are in a better position to select a method.

Implementing algorithms in a DSP like the DSP56002 can be informative or lead you in the wrong direction for logic implementation. You will need to take responsibility for a lot of features that the DSP does behind the assembly code as well as understand fixed point binary numbers.

The phase accumulator approach is pretty easy and flexible where appropriate. Have you looked at this ?

##### Share on other sites
• 0

Hi,

11 hours ago, zygot said:

The phase accumulator approach is pretty easy and flexible where appropriate. Have you looked at this ?

and here is an option to transform sawtooth-to-sine.

It's spline-based, which is essentially no different from linear interpolation but uses third-order polynomials instead of first-order lines. The code is heavily optimized, I think you can run it at 200+ MHz (can't remember, might be even 300) on speed grade 1 Artix.

##### Share on other sites
• 0

Can I interest you in a polynomial expansion using Taylor series? If depends on your application.

Back to your original thought. One idea, if you want to use waveform tables is to borrow from old PC video strategies and use ping-pong buffers. You read from one while alculating and writing to the other. It can be like, or at least good enough like, calculating all of the values concurrently. Depends on the timing. I think that this could go on for a while...

##### Share on other sites
• 0

Hi everybody , and thanks for all your inputs...

I know what i stated at first sounds crazy, but the  design  i'm working on implies to be able to update the wavetable array at least at every playback cycle.

In this sense i could use dds to be just a phase acc output that would be the reading index of the wavetable array..

As the wavetable cannot be less than 2048 samples (cos otherwise it wouldn't be ok) and considering all the processes this wavetable is serially intended to get, i should go quite fast.

I just want to point out that i have already simulated my design on a different platform, so.. it works, i'm now struggling to set dds compiler to put out 16bit output at these different ranges:

0.25hz-64hz and 27.5hz-7040hz.

Pls, as i'm the super noob in here :-D, could you confirm that to do that with dds (having streaming options available) the only way would be to have a clock as slow as 190Khz ?

Thx so much again for all your inputs , and the ping pong buffer would be a real game changer, of course..

##### Share on other sites
• 0
20 minutes ago, Pier said:

'm now struggling to set dds compiler to put out 16bit output at these different ranges:

0.25hz-64hz and 27.5hz-7040hz.

I don't tend to use the Xilinx IP as it uses more resources than I want to use and I prefer being able to do what I want as opposed to what the IP is set for. I'm also happier with the results and ease of modification and portability

Your idea of using a phase accumulator as a pointer into a sine table is how the NCO in the project that I referenced earlier works. With a 32-bit phase accumulator clocked at 100 MHz I can span .25Hz - 2.5 MHz Fout just by changing how fast I increment the phase accumulator. I use 1 BRAM to get 18 bits of sine data precision plus sign for sine and cosine simultaneously. It takes a whole lot less resources than anything that Xilinx or Intel will give you with their DDS IP. But since I don't use someone else's IP I 've got no answer for your particular question. You certainly don't want to play with slow clocking rates.

My advise is ditch the IP and figure out how to row your own boat.

Edited by zygot
##### Share on other sites
• 0

A few more thoughts. The sine table that my NCO uses is 1/4 cycle 2048 samples for 8192 19-bit samples per cycle. This might not be sufficient for really fast or really slow tones... one more time, it depends on the application requirements. You can always put a filter between the NCO and the application if needed.

For really low frequency high fidelity tones I'd probably calculate points on the fly using polynomial expansion.

Edited by zygot
##### Share on other sites
• 0

Thx Zygot,

i will be looking the resources you linked, your code should fit that kind of operation.  I will try to run your demo on cmod s7

Of course tailor things is much better, which is what i will try slowly to do.. also because there is no other way on many processes.

I tried dds cos appears compelling also beacuse the phasor i need must behave like a LFO

I want to add that in case 27.5hz-7040hz i would need a 0.2 hz resolution, while on the other case (0.25hz-64hz) it goes to 0.001 hz as i have 32768 control steps.

After all dds is not so expensive if used only as phase accumulator. I will follow you guys's advises... 💓

Edited by Pier
##### Share on other sites
• 0
1 minute ago, Pier said:

I will try to run your demo on cmod s7

Sorry, but the demo only runs on the Eclypse-Z7 with a DAC ZMOD. I haven't published my code for the NCO because I'd rather encourage people to figure it out on their own instead of relying on IP that they didn't take the time to understand... also I don't want to deprive anyone of the satisfaction of developing something on their own with perhaps a few hints. Never underestimate the power of pride in accomplishment. You can find alternate but similar code for a DDS from other contributors to this site.

##### Share on other sites
• 0
8 minutes ago, zygot said:

A few more thoughts. The sine table that my NCO uses is 1/4 cycle 2048 samples for 8192 19-bit samples per cycle. This might not be sufficient for really fast or really slow tones... one more time, it depends on the application requirements. You can always put a filter between the NCO and the application if needed.

For really low frequency high fidelity tones I'd probably calculate points on the fly using polynomial expansion.

The cheapest wavetable could be used is 2048 samples , to be able to achieve an acceptable num of harmonics, considering sf. In your NCO you go 4x and that is already pretty good, i can say that without hearing that, it must be really nice sounding if in audible range.

Problem is that my design needs to write the whole wavetable again at each playback cycle. so , bigger the wavetable, higher the clock, until it gets to be impossible.

i was tryin for 16384 samples, but if there isn't a parallel design it is too much. i scaled down to 2048 to start to simulate how many resources it will really eat

##### Share on other sites
• 0
3 minutes ago, zygot said:

Sorry, but the demo only runs on the Eclypse-Z7 with a DAC ZMOD. I haven't published my code for the NCO because I'd rather encourage people to figure it out on their own instead of relying on IP that they didn't take the time to understand... also I don't want to deprive anyone of the satisfaction of developing something on their own with perhaps a few hints. Never underestimate the power of pride in accomplishment. You can find alternate but similar code for a DDS from other contributors to this site.

you know read some code would have been of great help, but i understand your point 😄

thx again

##### Share on other sites
• 0
13 minutes ago, Pier said:

you know read some code would have been of great help

It sounds to me that you already understand the basic concepts of the NCO and DDS. Perhaps it's the HDL standing in your way.

At least on some level you understand the limitation of using look up tables to produce waveforms. You can change the tone out frequency by using fewer samples of the waveform buffer, or use a pre-scaler to change the lookup rate at which you read samples or change the clock rate at which you run your logic. All of these approaches limit the selection of Fout that you can choose unless your waveform table is huge, perhaps in DDR memory. But you can always get exactly n samples per cycle for those limited tone frequencies. Sometimes this isn't reasonable so you have to figure out another approach. The DDS or NCO approach allows for an almost arbitrary selection of Fout but might introduce phase errors and jitter because of how the numbers work out. It's is possible to compensate for such issues at a cost of added complexity.Again, it all depends on the applicatio requirements. Everything in engineering involves trade-offs, but starts with good specifications.

An NCO approach might be fine or not. It'd hard to go wrong with methods that calculate sin(x) on the fly if you're dealing with low frequencies. Very often a hybrid approach is the best option.