# dac dithering

Started by November 29, 2013
```
OK, I'm sort of thinking this through.

Suppose I have a stream of parallel digital words that represent a
waveform. Assume it's audio or something similar. Further assume that
it has an arbitrary number of bits available at an arbitrarily high
rate; we can fake the rate by digital interpolation if the raw data
stream isn't fast enough.

Assume that I want to use a 16 bit DAC but I need close to 120 dB (a
few parts per million) dynamic range. The 16 bit DAC quantizes the
signal to 15 PPM, and even worse, the DAC that we have in stock is
only guaranteed monotonic to 14 bits.

We can clock this DAC really fast and lowpass filter the output.

If the data is, say, 24 bits wide, we can call the first 16 bits H and
the low 8 bits L.

If we just stuff H into the DAC, we're quantized to 16 bits, 15 PPM.

We could take the L bits and turn them into a PWM waveform, and when
the PWM was high, add one LSB to the 16 bit DAC. The averaged value of
the DAC now has 24 bit resolution. But the PWM signal winds up as a
spurious signal in the DAC output, at 1/256 the clock rate, and we'd
have to filter that out. That could be inconvenient.

A better way to do this is to add the LSB correction at the same duty
cycle but splatter the highs and lows in time. That is, basically, a
first-order delta-sigma algorithm. The wiggled LSB is no longer a low
frequency whine, but it becomes wideband noise.

One problem is that we can't be sure that the LSB that we dither is
exactly 1/65536 of the DAC full-scale amplitude. The dac is monotonic
to 14 bits, so bad luck would have the dithered bit be 4x as big as
expected. Or negative.

Assuming the DAC has the biggest nasties at major transitions, like
0x7FFF to 0x8000, we could add some DC offset to avoid that step when
we're making small signals. Add 64 or 293 or something maybe, to get
in a zone where it's probably pretty linear.

One could accomplish the PWM by adding a sawtooth or triangle waveform
to L before quantizing to 16 bits. Or splatter the triangle samples
randomly, to get the delta-sigma noise shaping.

If you added a bigger triangle than 1 LSB of H, the DAC output would
splatter over more than one bit. That reduces the probability that we
are using a "bad bit" transition, an non-monotic step, for the dither
interpolation.

So it looks like I could have a lookup table of 24-bit numbers in the
ballpark of 293*256 or whatever, randomized with a flat probability
distribution (scrambled triangle) some modest number of H LSBs in p-p
amplitude. Every DAC clock, add the next one to the 24-bit data before
truncating to 16 bits for the DAC. That's sort of like a higher-order
"noise shaped" delta-sigma, but there's no feedback loop. The bigger
the spread of the random numbers, the more noise we make but the
better we cope with DAC monoticity errors.

```
```Den l=F8rdag den 30. november 2013 03.37.01 UTC+1 skrev John Larkin:
> OK, I'm sort of thinking this through.
>=20
>=20
>=20
> Suppose I have a stream of parallel digital words that represent a
>=20
> waveform. Assume it's audio or something similar. Further assume that
>=20
> it has an arbitrary number of bits available at an arbitrarily high
>=20
> rate; we can fake the rate by digital interpolation if the raw data
>=20
> stream isn't fast enough.
>=20
>=20
>=20
> Assume that I want to use a 16 bit DAC but I need close to 120 dB (a
>=20
> few parts per million) dynamic range. The 16 bit DAC quantizes the
>=20
> signal to 15 PPM, and even worse, the DAC that we have in stock is
>=20
> only guaranteed monotonic to 14 bits.
>=20
>=20
>=20
> We can clock this DAC really fast and lowpass filter the output.
>=20
>=20
>=20
> If the data is, say, 24 bits wide, we can call the first 16 bits H and
>=20
> the low 8 bits L.
>=20
>=20
>=20
> If we just stuff H into the DAC, we're quantized to 16 bits, 15 PPM.
>=20
>=20
>=20
> We could take the L bits and turn them into a PWM waveform, and when
>=20
> the PWM was high, add one LSB to the 16 bit DAC. The averaged value of
>=20
> the DAC now has 24 bit resolution. But the PWM signal winds up as a
>=20
> spurious signal in the DAC output, at 1/256 the clock rate, and we'd
>=20
> have to filter that out. That could be inconvenient.
>=20
>=20
>=20
> A better way to do this is to add the LSB correction at the same duty
>=20
> cycle but splatter the highs and lows in time. That is, basically, a
>=20
> first-order delta-sigma algorithm. The wiggled LSB is no longer a low
>=20
> frequency whine, but it becomes wideband noise.=20
>=20
>=20
>=20
> One problem is that we can't be sure that the LSB that we dither is
>=20
> exactly 1/65536 of the DAC full-scale amplitude. The dac is monotonic
>=20
> to 14 bits, so bad luck would have the dithered bit be 4x as big as
>=20
> expected. Or negative.
>=20
>=20
>=20
> Assuming the DAC has the biggest nasties at major transitions, like
>=20
> 0x7FFF to 0x8000, we could add some DC offset to avoid that step when
>=20
> we're making small signals. Add 64 or 293 or something maybe, to get
>=20
> in a zone where it's probably pretty linear.
>=20
>=20
>=20
> One could accomplish the PWM by adding a sawtooth or triangle waveform
>=20
> to L before quantizing to 16 bits. Or splatter the triangle samples
>=20
> randomly, to get the delta-sigma noise shaping.
>=20
>=20
>=20
> If you added a bigger triangle than 1 LSB of H, the DAC output would
>=20
> splatter over more than one bit. That reduces the probability that we
>=20
> are using a "bad bit" transition, an non-monotic step, for the dither
>=20
> interpolation.
>=20
>=20
>=20
> So it looks like I could have a lookup table of 24-bit numbers in the
>=20
> ballpark of 293*256 or whatever, randomized with a flat probability
>=20
> distribution (scrambled triangle) some modest number of H LSBs in p-p
>=20
> amplitude. Every DAC clock, add the next one to the 24-bit data before
>=20
> truncating to 16 bits for the DAC. That's sort of like a higher-order
>=20
> "noise shaped" delta-sigma, but there's no feedback loop. The bigger
>=20
> the spread of the random numbers, the more noise we make but the
>=20
> better we cope with DAC monoticity errors.

I'd try the delta-sigma, maybe skip the "bad bit"

Analog Devices uses something called "data directed scrambling" I think the=
re is some patents explaining it if you google=20

-Lasse
```
```On 11/29/2013 8:37 PM, John Larkin wrote:

> Assume that I want to use a 16 bit DAC but I need close to 120 dB (a
> few parts per million) dynamic range. The 16 bit DAC quantizes the
> signal to 15 PPM, and even worse, the DAC that we have in stock is
> only guaranteed monotonic to 14 bits.

Making 20 bits out of 14 bits = oversampling of factor 4096 ballpark.

> We can clock this DAC really fast and lowpass filter the output.

Really really fast.

DSP and Mixed Signal Designs
www.abvolt.com

```
```Den l=F8rdag den 30. november 2013 04.44.24 UTC+1 skrev Vladimir Vassilevsk=
y:
> On 11/29/2013 8:37 PM, John Larkin wrote:
>=20
>=20
>=20
> > Assume that I want to use a 16 bit DAC but I need close to 120 dB (a
>=20
> > few parts per million) dynamic range. The 16 bit DAC quantizes the
>=20
> > signal to 15 PPM, and even worse, the DAC that we have in stock is
>=20
> > only guaranteed monotonic to 14 bits.
>=20
>=20
>=20
> Making 20 bits out of 14 bits =3D oversampling of factor 4096 ballpark.
>=20
>=20
>=20
> > We can clock this DAC really fast and lowpass filter the output.
>=20
>=20
>=20
> Really really fast.
>=20

a few hundred MHz is not such a big problem

-Lasse
```
```In article <e7ii9952f71b1gh01rfrvv8l0o701qrmln@4ax.com>,
John Larkin <jjlarkin@highNOTlandTHIStechnologyPART.com> wrote:

> OK, I'm sort of thinking this through.
>
> Suppose I have a stream of parallel digital words that represent a
> waveform. Assume it's audio or something similar. Further assume that
> it has an arbitrary number of bits available at an arbitrarily high
> rate; we can fake the rate by digital interpolation if the raw data
> stream isn't fast enough.
>
> Assume that I want to use a 16 bit DAC but I need close to 120 dB (a
> few parts per million) dynamic range. The 16 bit DAC quantizes the
> signal to 15 PPM, and even worse, the DAC that we have in stock is
> only guaranteed monotonic to 14 bits.
>
> We can clock this DAC really fast and lowpass filter the output.
>
> If the data is, say, 24 bits wide, we can call the first 16 bits H and
> the low 8 bits L.
>
> If we just stuff H into the DAC, we're quantized to 16 bits, 15 PPM.
>
> We could take the L bits and turn them into a PWM waveform, and when
> the PWM was high, add one LSB to the 16 bit DAC. The averaged value of
> the DAC now has 24 bit resolution. But the PWM signal winds up as a
> spurious signal in the DAC output, at 1/256 the clock rate, and we'd
> have to filter that out. That could be inconvenient.
>
> A better way to do this is to add the LSB correction at the same duty
> cycle but splatter the highs and lows in time. That is, basically, a
> first-order delta-sigma algorithm. The wiggled LSB is no longer a low
> frequency whine, but it becomes wideband noise.
>
> One problem is that we can't be sure that the LSB that we dither is
> exactly 1/65536 of the DAC full-scale amplitude. The dac is monotonic
> to 14 bits, so bad luck would have the dithered bit be 4x as big as
> expected. Or negative.
>
> Assuming the DAC has the biggest nasties at major transitions, like
> 0x7FFF to 0x8000, we could add some DC offset to avoid that step when
> we're making small signals. Add 64 or 293 or something maybe, to get
> in a zone where it's probably pretty linear.
>
> One could accomplish the PWM by adding a sawtooth or triangle waveform
> to L before quantizing to 16 bits. Or splatter the triangle samples
> randomly, to get the delta-sigma noise shaping.
>
> If you added a bigger triangle than 1 LSB of H, the DAC output would
> splatter over more than one bit. That reduces the probability that we
> are using a "bad bit" transition, an non-monotic step, for the dither
> interpolation.
>
> So it looks like I could have a lookup table of 24-bit numbers in the
> ballpark of 293*256 or whatever, randomized with a flat probability
> distribution (scrambled triangle) some modest number of H LSBs in p-p
> amplitude. Every DAC clock, add the next one to the 24-bit data before
> truncating to 16 bits for the DAC. That's sort of like a higher-order
> "noise shaped" delta-sigma, but there's no feedback loop. The bigger
> the spread of the random numbers, the more noise we make but the
> better we cope with DAC monoticity errors.

If you have a CPU generating the bits, it could run a linear
congruential generator with little cost.  I recommend initializing with
a constant seed so that you can guarantee the results.  The result is
hardly random but it looks and sounds random when used for dithering.
I've used it in photo processing algorithms to prevent blue sky and
greyscale banding when generating ARGB packed in 32 bits.

LCGs can be done with feedback loops in shift registers too.
```
```On Fri, 29 Nov 2013 20:17:23 -0800, Kevin McMurtrie
<mcmurtrie@pixelmemory.us> wrote:

>In article <e7ii9952f71b1gh01rfrvv8l0o701qrmln@4ax.com>,
> John Larkin <jjlarkin@highNOTlandTHIStechnologyPART.com> wrote:
>
>> OK, I'm sort of thinking this through.
>>
>> Suppose I have a stream of parallel digital words that represent a
>> waveform. Assume it's audio or something similar. Further assume that
>> it has an arbitrary number of bits available at an arbitrarily high
>> rate; we can fake the rate by digital interpolation if the raw data
>> stream isn't fast enough.
>>
>> Assume that I want to use a 16 bit DAC but I need close to 120 dB (a
>> few parts per million) dynamic range. The 16 bit DAC quantizes the
>> signal to 15 PPM, and even worse, the DAC that we have in stock is
>> only guaranteed monotonic to 14 bits.
>>
>> We can clock this DAC really fast and lowpass filter the output.
>>
>> If the data is, say, 24 bits wide, we can call the first 16 bits H and
>> the low 8 bits L.
>>
>> If we just stuff H into the DAC, we're quantized to 16 bits, 15 PPM.
>>
>> We could take the L bits and turn them into a PWM waveform, and when
>> the PWM was high, add one LSB to the 16 bit DAC. The averaged value of
>> the DAC now has 24 bit resolution. But the PWM signal winds up as a
>> spurious signal in the DAC output, at 1/256 the clock rate, and we'd
>> have to filter that out. That could be inconvenient.
>>
>> A better way to do this is to add the LSB correction at the same duty
>> cycle but splatter the highs and lows in time. That is, basically, a
>> first-order delta-sigma algorithm. The wiggled LSB is no longer a low
>> frequency whine, but it becomes wideband noise.
>>
>> One problem is that we can't be sure that the LSB that we dither is
>> exactly 1/65536 of the DAC full-scale amplitude. The dac is monotonic
>> to 14 bits, so bad luck would have the dithered bit be 4x as big as
>> expected. Or negative.
>>
>> Assuming the DAC has the biggest nasties at major transitions, like
>> 0x7FFF to 0x8000, we could add some DC offset to avoid that step when
>> we're making small signals. Add 64 or 293 or something maybe, to get
>> in a zone where it's probably pretty linear.
>>
>> One could accomplish the PWM by adding a sawtooth or triangle waveform
>> to L before quantizing to 16 bits. Or splatter the triangle samples
>> randomly, to get the delta-sigma noise shaping.
>>
>> If you added a bigger triangle than 1 LSB of H, the DAC output would
>> splatter over more than one bit. That reduces the probability that we
>> are using a "bad bit" transition, an non-monotic step, for the dither
>> interpolation.
>>
>> So it looks like I could have a lookup table of 24-bit numbers in the
>> ballpark of 293*256 or whatever, randomized with a flat probability
>> distribution (scrambled triangle) some modest number of H LSBs in p-p
>> amplitude. Every DAC clock, add the next one to the 24-bit data before
>> truncating to 16 bits for the DAC. That's sort of like a higher-order
>> "noise shaped" delta-sigma, but there's no feedback loop. The bigger
>> the spread of the random numbers, the more noise we make but the
>> better we cope with DAC monoticity errors.
>
>If you have a CPU generating the bits, it could run a linear
>congruential generator with little cost.  I recommend initializing with
>a constant seed so that you can guarantee the results.  The result is
>hardly random but it looks and sounds random when used for dithering.
>I've used it in photo processing algorithms to prevent blue sky and
>greyscale banding when generating ARGB packed in 32 bits.
>
>LCGs can be done with feedback loops in shift registers too.

It's all in an FPGA, so a pseudo-random shift register, plus the DC
offset, could all be done in hardware. The low N bits of the random
number could be added to the 24-bit stuff, where N is, say, 11 or
thereabouts, to dither the DAC maybe 3 bits.

I guess I could simulate this to tune it.

```
```I mean seriously, this was so much already invented that I gave up after
the first paragraph.

```
```On Fri, 29 Nov 2013 21:19:05 -0800, miso <miso@sushi.com> wrote:

>
>I mean seriously, this was so much already invented that I gave up after
>the first paragraph.

Then you didn't read the interesting stuff.

```
```On Fri, 29 Nov 2013 21:44:24 -0600, Vladimir Vassilevsky wrote:

> On 11/29/2013 8:37 PM, John Larkin wrote:
>
>> Assume that I want to use a 16 bit DAC but I need close to 120 dB (a
>> few parts per million) dynamic range. The 16 bit DAC quantizes the
>> signal to 15 PPM, and even worse, the DAC that we have in stock is only
>> guaranteed monotonic to 14 bits.
>
> Making 20 bits out of 14 bits = oversampling of factor 4096 ballpark.

For uncorrelated, unshaped noise, yes.  For a first-order sigma delta,
the minimum oversampling is more like 64 (and you wouldn't want to get
that close -- but 200x would probably be OK).

>> We can clock this DAC really fast and lowpass filter the output.
>
> Really really fast.
>
>
> Vladimir Vassilevsky DSP and Mixed Signal Designs www.abvolt.com

--

Tim Wescott
Wescott Design Services
http://www.wescottdesign.com

```
```On Fri, 29 Nov 2013 18:37:01 -0800, John Larkin wrote:

> OK, I'm sort of thinking this through.
>
> Suppose I have a stream of parallel digital words that represent a
> waveform. Assume it's audio or something similar. Further assume that it
> has an arbitrary number of bits available at an arbitrarily high rate;
> we can fake the rate by digital interpolation if the raw data stream
> isn't fast enough.
>
> Assume that I want to use a 16 bit DAC but I need close to 120 dB (a few
> parts per million) dynamic range. The 16 bit DAC quantizes the signal to
> 15 PPM, and even worse, the DAC that we have in stock is only guaranteed
> monotonic to 14 bits.
>
> We can clock this DAC really fast and lowpass filter the output.
>
> If the data is, say, 24 bits wide, we can call the first 16 bits H and
> the low 8 bits L.
>
> If we just stuff H into the DAC, we're quantized to 16 bits, 15 PPM.
>
> We could take the L bits and turn them into a PWM waveform, and when the
> PWM was high, add one LSB to the 16 bit DAC. The averaged value of the
> DAC now has 24 bit resolution. But the PWM signal winds up as a spurious
> signal in the DAC output, at 1/256 the clock rate, and we'd have to
> filter that out. That could be inconvenient.
>
> A better way to do this is to add the LSB correction at the same duty
> cycle but splatter the highs and lows in time. That is, basically, a
> first-order delta-sigma algorithm. The wiggled LSB is no longer a low
> frequency whine, but it becomes wideband noise.
>
> One problem is that we can't be sure that the LSB that we dither is
> exactly 1/65536 of the DAC full-scale amplitude. The dac is monotonic to
> 14 bits, so bad luck would have the dithered bit be 4x as big as
> expected. Or negative.
>
> Assuming the DAC has the biggest nasties at major transitions, like
> 0x7FFF to 0x8000, we could add some DC offset to avoid that step when
> we're making small signals. Add 64 or 293 or something maybe, to get in
> a zone where it's probably pretty linear.
>
> One could accomplish the PWM by adding a sawtooth or triangle waveform
> to L before quantizing to 16 bits. Or splatter the triangle samples
> randomly, to get the delta-sigma noise shaping.
>
> If you added a bigger triangle than 1 LSB of H, the DAC output would
> splatter over more than one bit. That reduces the probability that we
> are using a "bad bit" transition, an non-monotic step, for the dither
> interpolation.
>
> So it looks like I could have a lookup table of 24-bit numbers in the
> ballpark of 293*256 or whatever, randomized with a flat probability
> distribution (scrambled triangle) some modest number of H LSBs in p-p
> amplitude. Every DAC clock, add the next one to the 24-bit data before
> truncating to 16 bits for the DAC. That's sort of like a higher-order
> "noise shaped" delta-sigma, but there's no feedback loop. The bigger the
> spread of the random numbers, the more noise we make but the better we
> cope with DAC monoticity errors.

You probably want to noise-shape the dithering, which means sigma-delta,
which means some arithmetic.  But it means a much lower oversampling
ratio.

The non-monotonicity comes from the DAC's differential nonlinearity,
which will be with you no matter what.  So you're hardly going to be able
to get an accuracy of 120dB down from full scale, and you probably won't
be able to achieve a 120dB dynamic range by any but a very forgiving
specification of dynamic range.

If all you're looking for is single-tone reproduction, and you don't mind
some considerable gain errors when you're down in that -120dB range,
well, maybe you can achieve it.

--

Tim Wescott
Wescott Design Services
http://www.wescottdesign.com

```