You are here

Direct Digital Synthesis (DDS) - Part III of III

May 10, 2018

Modifying the DDS Engine

Time-Variant DDS

The aforementioned design of a DDS engine relies on modifying the Tuning Word to achieve a wide variety of output waveforms. However, that particular design loses waveform sample precision as the represented frequency increases above the sampling capabilities of the Sample Table and the Source Clock. This occurs whenever the Tuning Word becomes larger than 1, since that indicates that a sample is eventually skipped to maintain synchronization with the desired output frequency. In some systems, this behavior is undesirable. To combat this, a Time-Variant DDS engine exists. The Tuning Word is always set to 1, and the effective Source Clock is instead adjusted to change the amount of time between each sample selection in the DDS engine. To calculate the required delta time for each sample selection, the base FPGA clock frequency (assume 40MHz), the target output frequency, and the Sample Table need to be considered. The Accumulator will no longer track the position in the Sample Table, but instead manage clock drift from non-integer Source Clock periods. The decimal will be stored, accumulated, and will occasionally generate addition clock tick(s) of wait time in between each execution of the DDS engine.

Example: Basic Sinusoid Output

Target Output Frequency: 2500.25 Hz

Base FPGA Clock: 40MHz

Sample Table: 360 Samples

Effective Source Clock Period: 44.44 Ticks/Sample

Math: SourceClockPeriod = FPGAClockFreq / (TargetFrequency * SampleTableSize)

Rationale: In this case, the DDS engine is controlled by a dynamically changing period. Each execution of the DDS engine will take 44 ticks of the base FPGA clock, with the Accumulator tracking the 0.44 partial ticks of drift on each execution. Upon the Accumulator growing above a value of 1, the integer component of that value is removed from the Accumulator and added to the period of the next DDS engine execution. The non-integer component is stored back in the Accumulator to continue tracking drift correctly.

Non-Sinusoidal Data

A DDS engine (assume the normal DDS engine for this discussion, not the Time-Variant version) can be leveraged to output non-waveform values, given that the behavior is fundamentally cyclic. That is to say, as long as the output can be represented by iterating through the Sample Table it is possible to produce that value for output reliably. As a point of warning, don't build a DDS engine when you know you only need to output slow DC values. These examples are only meant to show that such behavior is possible with minimal/no changes to a pre-existing DDS engine.

Example: Simple DC Output

Target Output Frequency: 0 Hz (DC)

Target DC Value: 2.5V

Source Clock: 10MHz

Sample Table: 100 Samples

Tuning Word: 1-100 (Doesn't really matter)

Rationale: In this particular instance, we fill the Sample Table completely with the target output value. Since the sample table is all the same value, it doesn't matter what value the tuning word is. Accessing any index in the Sample Table will produce a 2.5 output. This is a very simple and reliable mechanism to produce a DC output.

Example 1 will reliably utilize the existing DDS engine to produce a DC value output. It's somewhat non-ideal though, since we always need to write to the entire Sample Table to make a new output. It's possible that we can do better with a minor update to the DDS engine. With this slight addition, we add in a non-accumulated offset that allows the controller software to influence the accessed Sample Table index directly. Since it is a non-accumulated value, this offset must occur after the floor/truncation operation and cannot effect the normal behavior of the Accumulator.

Example: More Efficient DC Updates

Target Output Frequency: 0 Hz (DC)

Target DC Values: 0-9.9V (0.1V Increments)

Source Clock: 10MHz

Sample Table: 100 Samples

Tuning Word: 100

Offset Index: 0-99

Rationale: In this example, we've added the Offset Index. This is simply a U32 that gets added directly to the output of the accumulation logic after the floor/truncation operation. With the tuning word set to 100, we're simply telling the DDS engine to access a particular index in the Sample Table directly. From that, we fill the Sample Table with the complete range of values we want to output.

Online Resources

NI White Paper on DDS

Related Links

Part I of III on Direct Digital Synthesis

Part II of III on Direct Digital Synthesis