Archive - April 2016

1
Cirrus Logic CS4335 DAC problems finally identified and fixed.
2
left-justified DAC problems continue
3
Trying to debug my design for an Audio DAC Cirrus Logic CS4334

Cirrus Logic CS4335 DAC problems finally identified and fixed.

I had some assistance in fixing this problem. My always helpful friend Brian from Canada as well as some help from Steve @ the Audacity forums contributed to solving the problem. They filled in some blanks for me, and encouraged me to LOOK at the data to see the problem.

This is the “Quit thinking and look” solution found in this book called “Debugging Rules”. Absolutely love this book!! Amazon link.

  • I used Signal Tap II on the Altera FPGA as an internal logic analyzer to see both address values and ROM data values, so that I could correlate them with the serial data going outbound. This was an invaluable tool. There are also tutorials on youtube. Here’s an example of the data I was able to get: (CLICK FOR FULL SIZE)

signaltap_dac

  • I was also able to use my new mixed signal scope to capture the waveforms. The data is 8khz sample rate and 16-bit audio. Check out how nicely spaced these samples are — exactly 125ms apart!

serial_audio_data_scopeshot

  • The data coming out of Audacity’s Export Audio (Header: RAW, Encoding: Signed 16-bit PCM) was the opposite endianness that the DAC was expecting. I switched the bytes from 0xABCD to 0xCDAB and that fixed it.
  • My overall electronic design in Verilog for this was just ugly. And initially did not work — I wasn’t putting the right data on the serial pin at the right time. The right Verilog was ridiculously simple once I distilled it down properly.
  • I’ll post the Verilog with data files once I clean them up a bit. Feel free to email me (contact info above at menu) to nudge me if I haven’t done this yet.
  • I used SRECORD to convert the output of Audacity into a .MIF to load into a virtual ROM on the altera. I could have byte-swapped during the conversion, but currently do it on the FPGA. Either way is easy enough.
  • The initial 700hz tone that I have been fighting with for awhile finally came out alright tonight. It really was music to my ears.

Voice_011 (as a .wav file download or use Embedded Player below)

 

Voice_012 (as an .wav file download, or use Embedded Player below)

  • I added a little more interesting sound below:

left-justified DAC problems continue

Here you see the analog sound waveform coming out of the DAC at the top in yellow.

I think I’m getting closer……I switched from the I2S DAC to a left-justified DAC just because the LJ one is a little simpler to design around….the MSB for the DATA is lined up with the LRCLK transition……

The digital channels below are the input to the DAC:

D3 is the serial data

D2 is SCLK

D1 is LRCLK

D0 is the MCLK

dac_troubleshoot

Latest audio clip:

Trying to debug my design for an Audio DAC Cirrus Logic CS4334

I purchased a CS4334 to eventually use as an Audio DAC for the badge computer. I’ve never worked with DACs before, and my knowledge of audio is somewhat limited.

This audio DAC is a Cirrus Logic CS4334 with datasheet available here.

This chip is the I2S variant, specifically not the LEFT justified or RIGHT justified one. Each variant has slightly different timing requirements. The I2S specification is located here.

The audio data is a simple 700hz tone for 4 seconds with sample rate of 8000hz, and using signed 8-bit export. The audio file is here. 8k_signed8bit_straight700hz4s <— rename the .txt to .aiff. Use “Import Raw” feature of audacity, specify 8000 sample rate, signed 8-bit pcm. I generate an altera .mif using srecord, and here’s the resulting .MIF —–> 8ksigned_700_4s.

Here’s the output that I’m hearing. There are (8) chunks of sound as far as I can tell.

There IS my 700hz sample found in one of those eight chunks. It’s the “purest” sounding chunk of sound. You’ll know it as soon as you hear. LINK if the player below doesn’t work for you.

Any help to what the heck I’m doing wrong here would be appreciated!!

Here’s my verilog:

dac_clocks dac_clocks_inst (
.areset ( 1'b0 ),
.inclk0 ( SYS_CLK ),
.c0 ( SCLK ),
.c1 ( LRCLK ),
.c2 ( MCLK ),
.locked ( USER_LED[1] )
);

reg [7:0] sendbyte;
wire [7:0] romout;
reg [13:0] address;

reg SDATA;
wire SCLK; //128khz
wire MCLK; //1.024mhz
wire LRCLK; //8000hz to match the sample rate

assign PMOD_B[0] = SDATA;
assign PMOD_B[1] = SCLK;
assign PMOD_B[2] = LRCLK;
assign PMOD_B[3] = MCLK;

//setup the edge detection for LRCLK
reg LRCLK_OLD;

always @(posedge MCLK)
begin
LRCLK_OLD &lt;= LRCLK;
end

assign LRCLKfalledge=LRCLK_OLD & !LRCLK;
assign LRCLKriseedge=!LRCLK_OLD & LRCLK;

dacrom dacrom_inst (
.address ( address ),
.clock ( MCLK ),
.q ( romout )
);

/*this is to satisfy "In I2S mode, the MSB of the left channel is valid on the second rising
edge of BCLK[my SCLK] after the falling edge of LRCLK. Similarly, the MSB of the right channel is valid on the
second rising edge of BCLK after the rising edge of LRCLK"
*/


reg [7:0] twocycledelay;
always @(posedge LRCLKfalledge or negedge SCLK)
begin
if (LRCLKfalledge) twocycledelay <= 8'b0;

if (!SCLK) begin
twocycledelay <= twocycledelay + 8'b1;

if (twocycledelay == 8'd2) begin

sendbyte <= romout;
//counter <= 3'b0; //reset the bitcounter because we have a new byte

end
//else counter <= counter + 3'b1; //send next bit if we're not resetting

end

end

always@(posedge LRCLKfalledge) //when it's true that there's a falling edge, read the next byte
begin
address <= address + 14'b1;
if (address == 14'd32000) address <= 14'b0; //data in rom is 32000 bytes deep
end

reg [2:0] counter;

//send data MSB first. is it already two's complement from audacity?
always@(negedge SCLK) //put the data on the falling edge so that the receiver can read it on rising.
begin

SDATA <= sendbyte[3'd7-counter];
counter <= counter + 3'b1;
end
[/pre]