April 24, 2013

Fun with an MSP430 Launchpad and a Digilent Nexys3 FPGA demo board

At my office we had an internal class for studying VHDL, using Digilent Nexys3 as our experimentation board  [1]. As an end of class project, my partner and I opted to try and create a simple digital theremin.

The plan was to take an input from an IR sensor (like the Sharp IR proximity sensor [2]) and feed it through an ADC to generate a digital word. This word could then be manipulated to generate a frequency tuning word used for direct digital synthesis [3]. This would generate an output digital word corresponding to a variable frequency sine wave, which was then fed through a DAC and feed into a speaker for output.

The Nexys3 has a Xilinx chip, and we used the ISE Webpack development tools, which gave us the option of using Xilinx's DDS IP core. However, as part of our learning experience, we opted to use an open source core and incorporate that into our design. Martin Kumm developed a handy DDS core that we found on opencores.org [4], and this was the starting point for our project. Martin kindly provided a working test bench that we could simulate and understand the outputs of the core. Since we were only generating a sinewave to drive a speaker, we weren't interested in modifying input phase or capturing output phase.

As the Nexys3 board provided some useful peripherals, we adapted our original design to implement useful features, including an ability to set a specific frequency based upon the bank of switches, as well as displaying the generated frequency on the seven segment display.  As for limitations, since we were interested in simple testing, we fixed our output to be capped at 20kHz.

As seen in the following picture, we used the PMOD adaptors directly as pin inputs, with the JA bank used for the DDS output and the JB bank used for the digital word input. Originally we were going to use an ADC PMOD, but since it used an I2C interface we opted to go for a simpler direct GPIO approach. We used the seven rightmost switches to act as a seven-bit digital word, with each bit representing 190 Hz to give us our spread in spectrum. The final switch acted as a relay, using either the switch bank or the seven LSB pins of JB as the source for generating the frequency tuning word.
The following block diagram, while not 100% exactly correct, provides a coarse overview of how top-level design was mapped out. The dds_synthesizer is the DDS core we found on opencores.org. The clkdiv is a simple clock divider to provide useful sub-interval clocks from the master 100 MHz clock.
Our DAC was a simple 8 bit R2R laddder [5] soldered on a protoboard, again for the simplicity of not trying to have to use an intermediate communication protocol like I2C or UART. As shown in the image below, you can actually observe the discrete steps of the ladder as each bit became active on word transitions.
The addhalf block shown in the top-level design shifted the output of the dds_synthesizer since we were expecting a unsigned output for a DAC functionality, and it pushed out a signed word. That was a particularly fun thing to figure out; our output basically was a chopped sinewave with the peak and base at median value (as shown below), with discrete jumps at the transition boundaries

Once we had the switch bank working and the output generating a tone, we moved to the ADC side. Ruling out the PMODAD* series from Digilent, we elected to use a simple microprocessor's ADC and push out the digital word on pins configured for GPIO. As this was a really quick hack, I grabbed an MSP430 Launchpad, used the Energia IDE and read an analog signal on one pin and pushed it out digitally on 7 pins. Its wiring diagram is shown below.
Lo and behold, it worked quite well; the audio was pretty weak on the reclaimed PC speaker I stuck in there, but it was very effective.
The source code for the FPGA and the microprocessor can be found here [6].

There were some other cool projects that were ginned up by the class, including an IR edge detector via the ADC PMOD thrown on top of a simple two wheel autonomous vehicle, a spoofing of the WWVB clock setting signal, the groundwork for a couple of different games including a simple tower defense game as well as a version of Simon, and some integration of accelerometers (for the makings of a simple IMU) among others.

---
[1] - http://www.digilentinc.com/Products/Detail.cfm?NavPath=2,400,897&Prod=NEXYS3
[2] - https://www.sparkfun.com/products/242
[3] - http://en.wikipedia.org/wiki/Direct_digital_synthesizer
[4] - http://opencores.org/project,dds_synthesizer
[5] - http://en.wikipedia.org/wiki/Resistor_ladder
[6] - https://github.com/kpimmel/digital_theremin_fpga

No comments:

Post a Comment