asic_designer

CD Quality Audio 44.1kHz Delta Sigma DAC Spartan 6

32 posts in this topic

  Hello Everyone

 

    Has anyone here every tried this successfully?   I'm trying to stream CD quality audio through an I2S interface directly to a Delta Sigma DAC, and out to the headphone jack.  I can hear the audio through the head phones connected to the jack on the board but the audio sounds HORRIBLE.  I've been told that I need to implement an interpolation filter in between the delta sigma dac and the I2S receiver and that I can't send the audio directly to the DAC?  I noticed that there was a wave file project given away with the Pipistrello board, so I'm assuming that someone has tried this and gotten it to work?  So here is my set up

 

FPGA: Spartan 6 lx45 Pipistrello board

External Bluetooth Chip Connected via an I2S interface

CD Quality Audio Streaming at 44.1kHz

24bit data cropped to 16 bits ( LSB cropped )

16bit data feed to the Delta Sigma DAC running at 75Mhz

 

  So, I need an interpolation filter, or so I'm told, so do we have any laying around here?  Any other suggestions or solutions to this problem?  Thanks in advance for all of your help.

 

Share this post


Link to post
Share on other sites

The board I have already has an audio jack, so the filter that I need is an embedded one, not an additional external jack. I really can't use that in my current application. Thanks for letting me know about it though. Here is my question, how did the "wave project" ever work without this embedded filter? Was the filter implemented in software or something?

Any one know where I can get one? An interpolation filter for this type of application?

Share this post


Link to post
Share on other sites

The filter is built into the Audio Wing circuit board, take a look at the schematic.

Share this post


Link to post
Share on other sites

I just saw you say you are using the Pipistrello board, it should have the filter built in. If your project sounds bad then you probably need to increase the frequency of the clock running the Delta-sigma DAC.

 

Jack.

Share this post


Link to post
Share on other sites

Yep, just saw that your DAC is 16 bits at 75Mhz, you need to be much higher speed then 75Mhz for 16 bits. Try 300Mhz.

Jack.

.

OK so you are saying I don't need the filter, just simply up the clock frequency to about 300Mhz? OK do I have to insert zeros in between samples, or simple enable the dac for a single clock cycle when a new sample arrives?

Share this post


Link to post
Share on other sites

Yep, just saw that your DAC is 16 bits at 75Mhz, you need to be much higher speed then 75Mhz for 16 bits. Try 300Mhz or look at the Xapp154 for the formulas to find the correct speed you need. The more bits you have the faster the DAC needs to run at.

http://www.xilinx.com/support/documentation/application_notes/xapp154.pdf

 

Jack.

BTW I saw that app note, for 16 bits it suggests a frequency of 4.9Ghz or something like that. It then goes on to say that that high frequency is not necessary that a much lower frequency can be used. The formula will produce a outrageously high frequency so I can't use that.

Share this post


Link to post
Share on other sites

You'll want to use the highest frequency you can in most cases. Delta-sigma DACs are great for a lot of things and I've gotten pretty good sound out of one, but you're probably not going to get audiophile quality high bitrate sound. There is a trick I've seen done to implement vector games using delta-sigma DACs though. He used a pair of 5-bit DACs externally summed by resistors so you might try a similar approach. Maybe a pair of 8 bit DACs to handle the upper and lower half of a 16 bit stream.

 

See this for information http://spritesmods.com/?art=bwidow_fpga&page=7

Share this post


Link to post
Share on other sites

The Spartan 6 can generate clocks up to 900Mhz if I remember correctly. In my experiments though I think 300MHz was the sweet spot. You can try with 300Mhz and 900Mhz and see if you hear a difference. You don't need to do anything to the data stream, just increase the clock speed.

 

Jack.

Share this post


Link to post
Share on other sites

The Spartan 6 can generate clocks up to 900Mhz if I remember correctly. In my experiments though I think 300MHz was the sweet spot. You can try with 300Mhz and 900Mhz and see if you hear a difference. You don't need to do anything to the data stream, just increase the clock speed.

 

Jack.

 

OK I changed the clock rate to 300Mhz and it still sounds the same, horrible. :)  So can you describe the data flow you used in your projects?

 

A. Were the DACs constantly enabled (constantly summing) and you just simply feed them the new data as it came into the block?  If so, did you insert zeros in between samples or just leave the last sample there while the DAC continued to sum until new data came in?

 

B. Were the DACS only enabled for a single clock cycle at the sample rate on the arrival of new data?

 

C. None of the above?

 

BTW, thanks for your help so far!

Share this post


Link to post
Share on other sites

I get the feeling this problem isn't about the clock rate being too low, or the interpolation filter.

 

asic_designer: You say it sounds horrible.  How bad?

(i) Not hi-fi, not very good for music, but good enough for talk.

(ii) Not even good enough for normal talk on the phone/radio.

(iii) Not even recognizable.

 

Problems with the clock rate would be (i).  If it's (ii) or (iii) then that's not it.  The sound quality of a sigma-delta DAC should degrade gracefully, as the clock rate goes lower.  I did synthesizer projects running at 32MHz and 128MHz and the sound was good enough to my ear.

 

As for the latest question: It's A.  The DAC is continuously summing.  And it should sum, not zero, but the latest sample value.

 

The way a sigma-delta DAC works is that it generates a waveform that has only highs and lows, nothing in between.  The interpolation filter averages it into a much slower waveform, but also one that's more gradual.  So, say your desired wave is a sine wave at 1kHz and you've got a sigma-delta DAC running at 32MHz.  Then in the middle of the wave, if it's 50% between high and low, you'd expect to see a fast 16MHz square wave coming out of the FPGA (high low high low ...).  And if it's down to 25%, you'd expect to see an 8MHz, 25% duty cycle wave (high low low low high low low low ...).

 

So, here are my suggestions:

  • Sum at the full clock rate, adding the current sample value.  If that fixes the problem, great.  Otherwise, the rest of these tips are for debugging.
  • Save a few thousand samples in memory and send them back to your computer.  Examine them to make sure the sample values are right.  If the samples you're trying to play aren't right, then no DAC can make them sound right.
  • Make sure the sample width (in bits) and signedness are what you think they are.  Playing a signed sample as unsigned is going to sound horrible.  And the adder you build the sigma-delta DAC around, needs to handle whichever it is you're giving it.

Share this post


Link to post
Share on other sites

There is a waveplayer project for Pipistrello that you can use to verify the quality of the audio output, it plays uncompressed wave files stored on an sd-card. 

 

It will play 44.1 KHz stero wave files using 12-bit DACs clocked at 120 MHz.

 

Here is a link to a zip file with just the bit file and two songs (80 MB file size): http://www.saanlima.com/download/pipistrello-v2.0/waveplayer.zip

Flash or load the bit file to Pipistrello.  It will play all the .wav files on the root directory of the sd-card.

Just copy the files in the wave directory to the root of the sd-card used.

 

Magnus

Share this post


Link to post
Share on other sites

One other thing to check is whether this is a matter of signed and unsigned values. When I was playing with a SPDIF decoder the output sounded terrible until I realized I was feeding a signed value into a DAC expecting an unsigned value. It was necessary to invert the MSB and then it sounded good.

Share this post


Link to post
Share on other sites

 

I get the feeling this problem isn't about the clock rate being too low, or the interpolation filter.

 

asic_designer: You say it sounds horrible.  How bad?

(i) Not hi-fi, not very good for music, but good enough for talk.

(ii) Not even good enough for normal talk on the phone/radio.

(iii) Not even recognizable.

 

Problems with the clock rate would be (i).  If it's (ii) or (iii) then that's not it.  The sound quality of a sigma-delta DAC should degrade gracefully, as the clock rate goes lower.  I did synthesizer projects running at 32MHz and 128MHz and the sound was good enough to my ear.

 

As for the latest question: It's A.  The DAC is continuously summing.  And it should sum, not zero, but the latest sample value.

 

So, here are my suggestions:

  • Sum at the full clock rate, adding the current sample value.  If that fixes the problem, great.  Otherwise, the rest of these tips are for debugging.
  • Save a few thousand samples in memory and send them back to your computer.  Examine them to make sure the sample values are right.  If the samples you're trying to play aren't right, then no DAC can make them sound right.
  • Make sure the sample width (in bits) and signedness are what you think they are.  Playing a signed sample as unsigned is going to sound horrible.  And the adder you build the sigma-delta DAC around, needs to handle whichever it is you're giving it.

 

 

Thanks for you input, and the explanation.  I'm putting some of these suggestions to use now.  I'll have an update in a little while for you guys.

Share this post


Link to post
Share on other sites

There is a waveplayer project for Pipistrello that you can use to verify the quality of the audio output, it plays uncompressed wave files stored on an sd-card. 

 

...

 

Magnus

 

Thanks for the suggestion, however this design is for a completely different SoC and I'm pretty sure that the error must be on my part, (well since I designed the SoC).  :)  BTW I have the wave player project, and I will use it to compare data and see if there are discrepancies, thanks!

Share this post


Link to post
Share on other sites

One other thing to check is whether this is a matter of signed and unsigned values. When I was playing with a SPDIF decoder the output sounded terrible until I realized I was feeding a signed value into a DAC expecting an unsigned value. It was necessary to invert the MSB and then it sounded good.

 

I get the feeling now that this might be the issue Jaxartes mentioned this as well and looking at the verilog code for this DAC, I'm pretty sure it was meant for unsigned numbers and I'm fairly certain that the data coming across the I2S interface is 16 bit twos complement data.  So yes there is a discrepancy here, that has to be corrected. I'll have to update the verilog code.  

 

Thanks!

`timescale  100 ps / 10 ps//`define MSBI  15    // Most Significant Bit of DAC input// This is a Delta-Sigma Digital to Analog Convertermodule delta_segma_dac#(parameter MSBI = 15)(    input  wire               CLK,           input  wire               RST,  input  wire               DAC_EN,        input  wire [MSBI:0]      DAC_IN,                       output wire               DAC_OUT    );  //**********************************************************//==========================================================// variable, constant, and wire declarations//==========================================================//**********************************************************//==========================================================// constant declaration//==========================================================      //==========================================================// wire declaration//==========================================================wire [MSBI+2:0] DeltaB;      // B input of Delta adderwire [MSBI+2:0] DeltaAdder;  // output of Delta adderwire [MSBI+2:0] SigmaAdder;  // output of Sigma adder            //==========================================================//variable declaration -- they are not REGISTERS !!!!!!!!!!//==========================================================reg DACout;reg [MSBI+2:0] SigmaLatch;  // Latches output of Sigma adder//==========================================================// HARDWARE IMPLEMENTATION CODE//==========================================================assign DeltaB     = { SigmaLatch[MSBI+2], SigmaLatch[MSBI+2], {MSBI+1{1'b0}} }; assign DeltaAdder = DAC_IN + DeltaB;assign SigmaAdder = DeltaAdder + SigmaLatch;always @(posedge CLK or posedge RST)begin    if ( RST == 1'b1 ) begin            SigmaLatch <= 1'b1 << (MSBI+1);        DACout     <= 1'b0;    end    else begin            if ( DAC_EN == 1'b1 ) begin                SigmaLatch <= SigmaAdder;            DACout     <= SigmaLatch[MSBI+2];        end     endendassign DAC_OUT = DACout;endmodule

Share this post


Link to post
Share on other sites

  So I the cranked up the clock frequency to 300Mhz, and I took absolute value of the input to the DAC ( in other words I took the twos complement of all negative numbers in the input stream).  This did create a dramatic difference in the sound, it is better no doubt about it, but the voices in the music are still bad, the melody it self is much improved but the voices are still robot like, with lots of static.

 

  I'm going to check the PCM input to see if there is a dependency between what is being sent and what I am getting.

Share this post


Link to post
Share on other sites

OK soooo, I found the problem, the solution was ~mentioned here but it got by me, so here is the explanation I got from a DSP guy just to be clear.

 

"You shouldn't be complementing, you should be offsetting all the samples by adding 32768 before feeding your DAC.
This way the zero signal output will be half rail and the audio can swing both ways.

 

I have not looked closely at the code, Verilog is not my thing."

 

Explanation --->

 

 Well your input range is -32768 -> 32767 correct?

Your DAC expects to see 0 -> 65535, the addition of 32768 to your signed value (note +32768 needs 17 bits as a signed integer) will yield a value having a range of 0 -> 65535 (17 bits as a signed value) which you then convert to unsigned (16 bits), with audio silence being somewhere in the middle of that range. 

Audio DACs all have an output corresponding to zero (audio sample value) input of mid scale, you then remove the DC component with a series cap.

If you think about it the process MUST be linear (anything else introduces mixing products), which addition is, but complement only some of the time most certainly is not.
If +1 produces output 20 & zero produces output 15 then -1 should surely produce output 10, not go back up to output 20, generally anytime you find yourself doing different things depending on the sign of a sample you are introducing a non linear element and that is usually not what you want. 

Addition not xor!

Share this post


Link to post
Share on other sites

Good! Glad you got it worked out. Thank you for sharing. :)

 

Jack.

Share this post


Link to post
Share on other sites

 

Addition not xor!

 

Well, it could be.  For a 16-bit value, adding 32768 without carry is the same as xor with 0x8000 ;)

 

Magnus

Share this post


Link to post
Share on other sites

Well, it could be.  For a 16-bit value, adding 32768 without carry is the same as xor with 0x8000 ;)

 

Magnus

Yes that was my thought so I asked but for some reason he was insistent on this point.

Share this post


Link to post
Share on other sites

Hi,

 

after experimenting with several on-board DAC variants, I think it is very unlikely that you'll get anywhere near CD quality

As a test signal, find a single-note piano sample and listen as it decays into the noise floor. If your experience is like mine, you'll hear dirty crunch-and-grind noises when the level gets too low.

Subjectively, I'd give it 10 effective bits and that's it.

 

There are a number of decent I2C DAC modules boards out there. An on-board DAC is nice for debugging but won't cut it for any serious project.

Share this post


Link to post
Share on other sites

I'd be curious to hear what sort of quality one could get from using several smaller delta-sigma DACs externally summed. A pair of 5 bit DACs running at 100MHz is adequate for driving a vector monitor, and the FPGA has no shortage of resources to create perhaps 6 4-bit DACs for a 24 bit audio stream.

Share this post


Link to post
Share on other sites

This reminds me of multi-bit DACs, which are used in commercial products.

For example, have a look at this

http://www.ti.com/lit/ds/symlink/pcm1794.pdf

"Theory of operation" (page 24)

 

Here is an interesting discussion on one-bit sigma delta conversion and its shortcomings:

http://sjeng.org/ftp/SACD.pdf

 

Unfortunately, it's not as easy as simply doing analog averaging between multiple independent DACs: With very simple assumptions, doubling the number of converters would gain only 3 dB SNR improvement (1/2 bit), which isn't much. For comparion, in a R2R DAC, every single bit improves SNR (theoretically) by 6 dB.

I suspect that the nonlinearity of the output drivers is much worse still, and it won't help with that either.

The whole concept of driving an audio signal from a digital supply is questionable if I'm targeting 100+ dB dynamic range.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now