fpga4fun.comwhere FPGAs are fun

PWM DAC 3 - One-bit DAC

Take one pin of an FPGA, connect a speaker and listen to an MP3? Easy. Here, we'll use a PC to decode an MP3, and then send the decoded data to an FPGA that is configured as a one-bit DAC.

Audio output

We require a DAC (digital-to-analog converter) to connect the FPGA (digital) to a speaker (analog).
The conventional approach would be to use a resistor ladder (see here), or use a dedicated DAC IC, like the venerable DAC-08.

Since the frequency at which FPGAs run is so fast compared to the frequencies required in the audio domain (MHZ's compared to KHz's), a one-bit DAC is a better choice.

Basically, to create the analog output, we smooth out the PWM or sigma-delta modulator output pulses using a low-pass filter. A sigma-delta modulator is better because of its higher-frequency output content, with which a single-order low-pass RC filter is usually enough.

Playing an MP3

The first step is to decode the MP3. The decoded MP3 data is called "PCM" data. To keep things simple, we send the PCM data through the serial port of the PC to the FPGA. The maximum rate possible through the serial port is 115200 baud (i.e. about 11.5 KBytes per second), so the music has to be down-sampled to 11KHz 8 bits. All that is easily done by a PC. Here's the software used (with source code).

And for the HDL code, we simply modify the sigma-delta modulator so that the PWM data input comes from the serial port.

module PWM(input clk, input RxD, output PWM_out);
wire RxD_data_ready;
wire [7:0] RxD_data;
async_receiver deserializer(.clk(clk), .RxD(RxD), .RxD_data_ready(RxD_data_ready), .RxD_data(RxD_data));

reg [7:0] RxD_data_reg;
always @(posedge clk) if(RxD_data_ready) RxD_data_reg <= RxD_data;

reg [8:0] PWM_accumulator;
always @(posedge clk) PWM_accumulator <= PWM_accumulator[7:0] + RxD_data_reg;

assign PWM_out = PWM_accumulator[8];

Now is time to connect a speaker to the FPGA. There are 3 basic ways to do it.

That's it! Listen to your favorite MP3 through an FPGA.