DSP examples
ECE 576 Cornell University

Most of the projects are audio, although one generates modulated RF.
List of projects included on this page:

  1. Soft Radio Transmitters: AM, FM
  2. Karplus-Strong String synthesis
  3. Adaptive noise cancellation
  4. IIR Audio filters:
    1. 18-bit, 2, 4, and 6-pole, 47 kHz sample rate
    2. 27-bit, 2, 4, and 6-pole, 47 kHz sample rate
    3. 8 kHz sample rate modifications

  1. Soft Radio Transmitters
    Note that it is illegal in the USA to operate an unlicensed transmitter on the AM or FM band (except under very limited conditions) or to cause radio interference in any way to someone else's reception. The following transmitter designs should be considered only as examples of modulation techniques and not used for any purpose.

    AM transmitter:
    Since the VGA DAC can sample above 50 MSamples/sec, it is possible to directly generate an amplitude-modulated radio signal in the standard AM band (530 KHz to 1700 KHz). The top-level module uses direct digital synthesis (DDS) to generate a 1.0 MHz sine wave for a carrier, then multiplies the carrier by an audio signal consisting of either a 400 Hz DDS unit or audio from the audio codec module . The design implements:

    y(t) = (C + a(t))*sine(2*π*F*t),

    where F=1.0 MHz, a(t) is the audio signal, and y(t) is the transmitted waveform. The audio signal originates in the audio codec ADC described in example 5 above. The audio signal has to be manipulated slightly to change the format from signed, 2's complement (produed by the audio codec ADC) to offset binary (required for the VGA DAC). The line below checks the sign bit and adds the appropriate offset to convert the modulation variable (from the audio codec) to offset binary. The product of the carrier (sine_out) and modulation are then shifted 10 bits to make a 10 bit number to send to the VGA DAC.

    VGA_R=((512+((modulation[15]==0)?modulation[15:6]+512:modulation[15:6]-512))*sine_out)>>10

    The transmitted signal can be received by placing an AM radio within a few inches of the VGA connector. Do not connect an antenna to the VGA connector. The image below is a photo of the oscilloscope showing the 1 MHz carrier (note CH1 Freq on right) and varying amplitudes from an audio signal modulation. The whole project is zipped here.

    FM Transmitter:
    The FPGA and DAC are not fast enough to generate a 100 MHz sine wave, but the 19th harmonic of a 4.5 MHz square wave falls in the FM band. Note that this design can cause strong radio interference at many frequencies and should never be used to actually transmit anything. The top-level module uses direct digital synthesis (DDS) to generate a 4.5 MHz FM modulated square wave using an audio signal consisting of either a 400 Hz DDS unit or audio from the audio codec module for modulation. The design implements:

    y(t) = 0<sine((2*π*F+δf*a(t))*t),

    where F=4.5 MHz, a(t) is the audio signal, δf is the conversion factor from audio input amplitude to frequency range, and y(t) is the transmitted, variable frequency, squarewave. The audio signal originates in the audio codec ADC described in example 5 above. The audio signal has to be manipulated slightly to change the format from signed, 2's complement (produed by the audio codec ADC) to offset binary. The verilog code below implements the DDS for carrier and audio tone generation, and modifies the DDS increment to FM modulate the signal. The δf scaling factor is the left-shift of 15 bits. SW0 is used to select between two tones. SW1 is used to select tone or ADC audio input.

    always @ (posedge CLOCK_50) begin
    		//generate 4.5 Mhz square wave carrier with FM modulation
    		DDS_accum <= DDS_accum + 32'h16FC7BBC + 
    				((SW[1])?  //Choose: sine wave/audio input
    				(mod_out<<15) : 
    				(256+((modulation[15]==0)? modulation[15:7]+256 : modulation[15:7]-256))<<15) ;
    		// generate 400/800 Hz
    		DDS_accum_mod = DDS_accum_mod + ((SW[0])? 32'hF5E7 : 32'h85E7) ;
    	end
    	//hook up the ROM table for carrier
    	sqwave sqTable(CLOCK_50, DDS_accum[31:24], sq_out);
    	//hook up the ROM table for 400 Hz modulation
    	sync_rom modTable(CLOCK_50, DDS_accum_mod[31:24], mod_out);
    	//use the VGA DAC for an FM modulated RF signal 
    	assign VGA_R = sq_out;
    	assign VGA_SYNC = 1 ;
    	assign VGA_BLANK = 1 ;
    	assign VGA_CLK = CLOCK_50 ; 
    The transmitted signal can be received by placing an FM radio within a few inches of the VGA connector. Do not connect an antenna to the VGA connector. The whole project is zipped here.


  2. Karplus-Strong Audio Synthesis
    The Karplus-Strong algorithm is a scheme for synthesizing the sound of a plucked string using physical synthesis techniques. The basic algorithm is simple enough to run in realtime on a microcontroller, but various extensions can be added which eat up processing. I implemented the basic algorithm in Verilog with the idea that multiple strings can be synthesized on the same FPGA. The top level module uses M4K block memory, hardware multipilers, and the audio codec. A state machine runs through five states once per audio sample (48KHz) using the left/right channel clock for sync. When a button is pushed, a burst of random numbers is injected into the model string to simulate a pluck. An example tuned to approximately 110 Hz (2 octaves below 440 A) is here. A scope screen shot below shows the waveform. The zipped project is here. A slight change in the top module allows you to chose the string frequency using the swithces. The interface is not very handy to use because the frequency and switch setting are inversely related. String damping is set by a gain factor which can take on values between about 0.47 and 0.50 (minimum damping). The default value used here is 0.495 (18'h0_7EB8 in 18-bit 2's complement)), which is appropriate for lower frequency strings, but too low for higher frequencies.


    Here I added a low pass filter to the string pluck function. The cutoff is set very coarsely by switches [17:15]. All three switches in the up-position is minimum bandwidth, all switches in the down-position is unfiltered white noise. Compare unfiltered and heavily filtered for the same fundamental frequency. Switches [11:0] still set the period of the simulated string so that string frequency=48000/SW[11:0]. The top module and the AUDIO_DAC_ADC module were modified. The AUDIO_DAC_ADC module is considerably simplified by eliminating all inputs except audio generated by the top level module. The whole project is zipped here.

  3. Adaptive Noise Cancellation
    Noise cancellation techniques attempt to dynamically find a filter which will remove a source of noise given two inputs: (1) A noise-contaminated input and (2) a noise reference. The two inputs might be (1) a 60 Hz contaminated electrophysiolgical recording and (2) input from the 60 Hz power line for reference. The filter needs to change in realtime because the nominal 60 Hz line actually varies by a few tenths of a cycle/sec over a period of a few minutes, so that a fixed, narrow-band notch filter will fail. The least-mean-squares (LMS) algorithm (see De Stefano reference below) can easily be implemented at audio rate on an FPGA.

    Two tap 60 Hz noise reduction
    The algorthms used here were tested first in Matlab. The first algorithm I implemented was from Ramos (see below), but modified for 60 Hz. The matlab program generates some fake action potentials and 60 Hz noise, adds them, then adaptive filters them by adjusting the phase and amplitude of a signal derived from the reference 60 Hz signal. The image below shows two panels. The top panel is the AP signal (spikes) contaminated by 60 Hz noise of the same amplitude. The bottom panel shows two traces. The red trace is the noise free input and the blue trace is the adaptively filtered output. You can see that the 60 Hz noise dies away over a few tenths of a second.

    The Verilog version of this algorithm (summarized in the image below) is contained in the top-level module. The delay is implemented as a 200 entry circular buffer (at 48KHz audio sample rate, one cycle of 60 Hz is 800 sample times, so 200 samples is a phase shift of π/2). The spurious coupling lightning bolt refers to undesirable and unplanned electrostatic and magnetic interactions between equipment and the biological system resulting in 60 Hz noise in the recorded data. Some care is required to properly sequence the M4K block memory as a ring buffer. The state machine runs on the positive edge of the clock, the memory is updated on the negative edge. In addition, the write-address and write-data have to be set up before the write-enable is activated. The value of μ was set at a constant 2-10 implemented by a right-shift.



    The Audio_DAC.ADC input/output was again modified and simplified. A matlab program generated the reference noise and simulated biological signal. The whole project is zipped here. Three scope images show the whole adaption sequence, the first few milliseconds, and the last few milliseconds. The top trace in all images is the adaptive output, while the bottom trace is the noise-corrupted input. The 60 Hz noise level was set at 100% of the biological spike amplitude. The weight modification factor μ was set to 2-10.



    Four tap 60 Hz and 180 Hz noise reduction
    The adaptive filter described above can be extended to filter 60 Hz plus the third harmonic at 180 Hz. Quite often there is significant 3rd harmonic distortion on the 110 volt power line, which would end up as experimental noise to be filtered. A matlab program simulates the filter. Extending the filter to two frequencies requires more data in the form of memory of the input waveform. The top level module for this filter has four adjustable filter weights and four different length ring buffers set to phase shifts of π/2, π/3, and π/6 of a 60 Hz cycle. This matlab program acted as input to the FPGA with 3rd harmonic distortion similar to a square wave (30%). The resulting adaption is shown in the mpeg. The top trace is the adaptively filtered signal, and the bottom trace is the noisy input. Over 10 seconds you can see the signal emerge from the noise. The two folowing images show scope traces. The first shows the 60 Hz rapidly decreasing. The second shows the convergence after about 5 seconds.



    Eight tap noise reduction
    Extending the filter to eight taps causes some instabilities to occur, apparently caused by overflow/underflow of the variable fixed point coefficients. The top level module implements the filter with seven delay line lengths from 200 samples down to 40 samples, equally spaced. A matlab code supplied a test signal with fairly large second and third harmonic noise contribution. Not all phase shifts or amplitudes could be canceled, for reasons still to be determined.

  4. Audio filter implementations

    General second order IIR (18-bit) .
    This example uses a serial multiply-and-accumulate (MAC) scheme to compute two second-order IIR filters in 6 cycles. Input is from the audio codec and output is back to the audio codec. The top-level module implements a state machine clocked by the audio control clock (18 MHz) and synched to run once/audio sample (about 47 KHz). If the state machine was clocked from clock_50 there were synch problems resulting in audio glitches. Each filter runs in parallel with all the other filters and each filter uses one 18-bit multiplier, so that you could implement up to about 35 filters. The filters use 18-bit, 2's complement notation with 16 bits of fraction for both the signal and the coefficients. This means that all filter coefficients have to be scaled to the range -1<coefficient<1. The matlab code to do the scaling and conversion to hex constants is at the end of the Verilog file as a comment. The matlab code to generate a frequency sweeping sine wave is also included at the end of the file. The whole project is zipped here. The actual filter form implemented was the Direct Form Type I transposed similar to what Matlab uses for its filter function. This means that the Matlab filter design funcitons (which yield the a's and b's) can be used to design filters. The form is shown below. The serial MAC operation steps through each of the terms on the right side of the equation, then divides by a(1), if necessary.
    a(1)*y(n) = b(1)*x(n) + b(2)*x(n-1) + ... + b(nb+1)*x(n-nb) 
                          - a(2)*y(n-1) - ... - a(na+1)*y(n-na)
    If a(1) is not equal to 1, you must divide the right side by a(1).
    The example has a Butterworth low pass filter with a normalized cutoff of 0.1 and an Butterworth bandpass filter with normalized cutoffs of [0.1 0.15]. The bandpass filter uses coefficients scaled by 0.5, so that the final MAC output has to be multiplied by two using a shift. Minor extensions to the state machine would allow higher order filters, but going too high causes numerical problems. Fourth order filters are probably safe, but sixth and higher should be carefully verified.

    General fourth order IIR (18-bit) .
    This example synthesizes a general 4th order IIR filter using the same serial scheme as above. The top-level module has a few more states. The matlab programs to generate the coefficients is improved to generate Verilog directly and to plot the filter response. The matlab programs are included as comments at the end of the Verilog. In the image below, the blue line is the filter response calculated by matlab and the red dots are measured from a scope attached to the DE2 audio output. The logic used on the CycloneII FPGA for one filter is about 1.3% of the total available. The book Digital Signal Processing and the microcontroller was very useful for this code (see reference below).

    Modularized IIR Filter version (18-bit) .
    This example modularizes the IIR filters and simplifies the generation of filters by creating the filter Verilog code in Matlab. The current version of the top-level module has modules for 2, 4, and 6th-order IIRs. The matlab program is at the end of the Verilog file as a comment. This example also builds a pulse-width modulator (PWM) so that the LEDs on the DE2 can be used to indicate filter output. Typical Verilog filter code generated by the Matlab program is shown below. You must rename the module, and substitute in appropriate input and output variable names. The matlab program computes the a and b values, scales them to avoid overflow, and converts them to hex. The matlab program also plots the exact filter solution as well as the scaled 16-bit approximation. An example is shown below for normalized cutoffs (frequency/(Fs/2)) of [0.1 0.2], 2nd order, and scaled by >>>2. Always check the approximation to verify filter quality.
    //Filter: cutoff=0.100000 
    //Filter: cutoff=0.200000 
    IIR4 filter( 
         .audio_out (your_out), 
         .audio_in (your_in), 
         .scale (3'd2), 
         .b1 (18'h149), 
         .b2 (18'h0), 
         .b3 (18'h3FD6E), 
         .b4 (18'h0), 
         .b5 (18'h149), 
         .a2 (18'hCD98), 
         .a3 (18'h2F54E), 
         .a4 (18'hA42E), 
         .a5 (18'h3D6F5), 
         .state_clk(AUD_CTRL_CLK), 
         .lr_clk(AUD_DACLRCK), 
         .reset(reset) 
    ) ; //end filter 


    Modularized IIR Filter version (27-bit) .
    This example extends the precision of the filters to allow accurate, lower bandwidth filters. As before the code modularizes the IIR filters and simplifies the generation of filters by creating the filter Verilog code in Matlab. The current version of the top-level module has modules for 2, 4, and 6th-order IIRs and a modified signed_mult routine. The matlab program is at the end of the Verilog file as a comment. This example also builds a pulse-width modulator (PWM) so that the LEDs on the DE2 can be used to indicate filter output. The matlab program computes the a and b values, scales them to avoid overflow, and converts them to hex. As in the last example, you must rename the module, and substitute in appropriate input and output variable names. The matlab program also plots the exact filter solution as well as the scaled 24-bit approximation. Always check the approximation to verify filter quality. The whole project is zipped here. Note that each filter uses 7 multipliers, so the maximum number of filters is 10. You could use these more expensive filters for narrow bandwidth fiters, which require more numerical accuracy, and 18-bit filters for higher bandwidth filters. A fairly narrow band filter ([0.1 0.13] at 47kHz sampling rate), six-pole filter is shown below.


    Filtering at 8 KHz sampling rate (18-bit).
    A sampling rate of 8 KHz is more appropriate for voice analysis. Three modifications are necessary to make the audio codec run at 8 KHz: (1) Change one status word in the codec initialization table in the I2C_AV_Config.v module; (2) Change the sample rate constant in AUDIO_DAC_ADC.v and change the lengths of the clock divider registers (BCK_DIV, LRCK_1X_DIV, LRCK_2X_DIV, LRCK_4X_DIV) so that they don't overflow because of the lower sample rate; (3) Change the audio clock PLL megawizard module (use the megawizard to edit VGA_Audio_PLL.v) to use CLOCK_50 and modify the input clock specification in the top_level module. The whole project is zipped here. Using the same audio filters as above, the band pass normalized frequency [0.1 0.2] is now at 400 to 800 Hz.

    To do: second order sections, FIR, multiple filters in one state machine

References

JO Hamblen, TS Hall and MD Furman, Rapid protoyping of digital systems, Springer 2005

Antonio Di Stefano, Alessandro Scaglione, Costantino Giaconia, Efficient FPGA Implementation of an Adaptive Noise Canceller, IEEE Proceedings of the Seventh International Workshop on Computer Architecture for Machine Perception 2005

R. Ramos, A. MBnuel, G. Olivar, E. Trullols and J. Del Rio, Application by means of FPGA of an adaptive caiiceller 50 Hz interference in electrocardiography, IEEE Instrumentation and Measurement Technology Conference, Budapest, Hungary, May 21-23.2001.

Dale Grover and John R. Deller, Digital Signal Processing and the microcontroller , Prentice-Hall/Motorola University Press 1999.