User Tools

Site Tools


projects:fpga_note_generator

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
projects:fpga_note_generator [2013/12/22 15:40]
criley1
projects:fpga_note_generator [2013/12/30 18:27] (current)
criley1
Line 1: Line 1:
 +======FPGA Note Generator======
 +by Caitlin Riley
 +
 =====What I Did===== =====What I Did=====
  
-I turned my FPGA into an instrument capable of playing eight notes. The eight switches on the FPGA are set to correspond to a note in an A natural minor scale. When a switch is on, the FPGA outputs an 8-bit quantized sine wave corresponding to that note. The sine wave is then converted into an analog signal that drives a speaker. ​+{{projects:​p1020661.jpg?​550|Note Generator}} 
 + 
 +I turned my FPGA into an instrument capable of playing eight notes. The eight switches on the FPGA are set to correspond to a note in an A natural minor scale. When a switch is on, the FPGA outputs an 8-bit quantized sine wave corresponding to that note. The sine wave is then converted into an analog signal that drives a speaker. A video of it working can be downloaded [[fpga_note_generator#​files|below]].
  
 ====Why I Did It==== ====Why I Did It====
Line 18: Line 23:
 ====Phase Accumulator===== ====Phase Accumulator=====
  
-The phase accumulator takes in the phase increment value and increments the phase angle by that much every cycle. For example, if the phase angle is n-bits and the phase increment value is 1, then it will increase the phase angle by 1*360<​sup>​o</​sup>​/​2<​sup>​n</​sup>​ degrees every cycle. This means that the frequency of the outputted sine wave is determined by phase increment*f<​sub>​clk</​sub>/​2<​sup>​n</​sup>​ and the frequency resolution is determined by f<​sub>​clk</​sub>/​2<​sup>​n</​sup>​.+The phase accumulator takes in the phase increment value and increments the phase angle by that much every cycle. For example, if the phase angle is n-bits and the phase increment value is 1, then it will increase the phase angle by 1*360°/​2<​sup>​n</​sup>​ degrees every cycle. This means that the frequency of the outputted sine wave is determined by Δθ*f<​sub>​clk</​sub>/​2<​sup>​n</​sup>​ and the frequency resolution is determined by f<​sub>​clk</​sub>/​2<​sup>​n</​sup>​.
  
 A phase accumulator is included in the drop-in Sine LUT module provided by Xilinx, so I chose to use that rather than implementing my own. A phase accumulator is included in the drop-in Sine LUT module provided by Xilinx, so I chose to use that rather than implementing my own.
Line 26: Line 31:
 The sine LUT is simply a lookup table that stores uniformly spaced samples of a sine wave. It takes in the phase angle from the phase accumulator as the address and outputs the sine.  The sine LUT is simply a lookup table that stores uniformly spaced samples of a sine wave. It takes in the phase angle from the phase accumulator as the address and outputs the sine. 
  
-In order to shorten the table and make it more space efficient, quarter and half wave symmetry can be exploited. This works because sin(a) = sin(pi-a) and sin(-a) = -sin(a). The two most significant bits of the angle are used for quadrant mapping, so it is not necessary to store values for all four quadrants in the LUT.+In order to shorten the table and make it more space efficient, quarter and half wave symmetry can be exploited. This works because sin(θ) = sin(π-θ) and sin(-θ) = -sin(θ). The two most significant bits of the angle are used for quadrant mapping, so it is not necessary to store values for all four quadrants in the LUT.
  
 I used the sine lookup table provided by Xilinx in the CORE generator system. This automatically utilizes half or quarter wave symmetry based on what it determines is most appropriate. I used the sine lookup table provided by Xilinx in the CORE generator system. This automatically utilizes half or quarter wave symmetry based on what it determines is most appropriate.
  
-====DAC====+====Digital-to-Analog Converter==== 
 + 
 +{{projects:​p1020662.jpg?​350|R-2R Ladder}}
  
 I ended up using an R-2R resistor ladder as the DAC for my system. Using an R-2R resistor ladder is a simple way to convert from digital to analog. It works by weighting the contribution of each bit to the final output voltage. The most significant bit contributes the most to the output voltage and the least significant bit contributes the least. An op amp buffer was placed between the resistor ladder and the speaker to prevent the speaker from acting as another resistor and distorting the output of the DAC. Although an R-2R ladder is not as accurate as other methods of digital to analog conversion, it was good enough for my purposes. I ended up using an R-2R resistor ladder as the DAC for my system. Using an R-2R resistor ladder is a simple way to convert from digital to analog. It works by weighting the contribution of each bit to the final output voltage. The most significant bit contributes the most to the output voltage and the least significant bit contributes the least. An op amp buffer was placed between the resistor ladder and the speaker to prevent the speaker from acting as another resistor and distorting the output of the DAC. Although an R-2R ladder is not as accurate as other methods of digital to analog conversion, it was good enough for my purposes.
  
-[[http://​en.wikipedia.org/​wiki/​Resistor_ladder#​R-2R_resistor_ladder_network_.28digital_to_analog_conversion.2C_or_DAC.29|{{projects:​420px-R2r-ladder.png |Wikipedia}}]]+|[[http://​en.wikipedia.org/​wiki/​Resistor_ladder#​R-2R_resistor_ladder_network_.28digital_to_analog_conversion.2C_or_DAC.29|{{projects:​420px-R2r-ladder.png |Wikipedia}}]]
 +|An n-bit R-2R resistor ladder.|
  
 =====How Can It Be Built Upon?===== =====How Can It Be Built Upon?=====
  
-====Code, Schematics ​and Build Instructions====+====Code and Schematics====
  
 ===Code=== ===Code===
Line 85: Line 93:
 </​file>​ </​file>​
  
-The phase accumulator and sine LUT were included in one module generated by the Xilinx CORE generator. ​This was called and then the output to the DAC was assigned using a ternary operator that only supplied an output sine wave if a switch was set high, as shown below.+The phase accumulator and sine LUT were included in one module generated by the Xilinx CORE generator. ​I chose to have the phase increment value be 26 bits so that the DDS had a frequency resolution of .745. I chose the output of the sine LUT to be 8-bits because I initially planned on using an 8-bit DAC IC. The DDS module ​was called and then the output to the DAC was assigned using a ternary operator that only supplied an output sine wave if a switch was set high, as shown below.
  
 <file verilog> <file verilog>
Line 94: Line 102:
  );  );
   
-assign sine_sig = (switch[0] == 1) ? sine: (switch[1] == 1) ? sine: (switch[2] == 1) ? sine: (switch[3] == 1) ? sine: (switch[4] == 1) ? sine: (switch[5] == 1) ? sine: (switch[6] == 1) ? sine: (switch[7] == 1) ? sine: 8'b0;+assign sine_sig = (switch[0] == 1) ? sine: (switch[1] == 1) ? sine: (switch[2] == 1) ? sine: 
 +          ​(switch[3] == 1) ? sine: (switch[4] == 1) ? sine: (switch[5] == 1) ? sine: (switch[6] == 1) ? sine:  
 +          ​(switch[7] == 1) ? sine: 8'b0;
 </​file>​ </​file>​
  
-The complete code used in the project can be downloaded below. ​+The complete code used in the project can be downloaded ​[[fpga_note_generator#​files|below]]
  
 ===Schematics=== ===Schematics===
 +Because the switches on the FPGA board are connected to the same FPGA pins as the 16-pin header connector, I used two sets of the 6-pin header connectors to connect the 8-bit sine wave output to the DAC. I powered the op amp from the ground and V<​sub>​DD</​sub>​ pins on the first header connector. The diagram for the DAC and speaker connection can be seen below.
  
-===Build Instructions===+{{projects:​Schematic.png|Circuit diagram}}
  
 ====Gotchas==== ====Gotchas====
 +===It'​s not you, it's the FPGA===
 +The problem that I spent the most time trying to debug ended up not being a problem I could fix. When I tried to connect the FPGA to my computer, my computer did not recognize it. Initially, when I tried to connect to a different FPGA I got the same error and assumed that it was some sort of driver or settings problem, not a problem with the FPGA. After several days of attempting many different things to get the FPGA to connect, I tried another FPGA again and it worked fine. If I had spent a little more time trying a different FPGA rather than trying to work with the one I had, I would have been able to spend a lot more time on my actual project rather than on debugging things that were not actually a problem.
 +
 +===Compilable code isn't necessarily synthesizable===
 +The other major problem I encountered was that code that compiled and simulated fine did not necessarily synthesize properly. I had problems with, for example, the program deciding that the first bit of the switch input was the clock and that the actual clock input was not necessary at all. Once this was fixed, I continued to have problems with the program not being able to route all paths. I had to make several rounds of revisions to my code before it would all synthesize and route as it should.
  
 ====Work Plan Reflection==== ====Work Plan Reflection====
 +I did not end up sticking to my work plan as much as I had hoped to. However, I scoped my project in such a way that despite this I was able to complete my minimum deliverable successfully.
 +
 +Overall I did not have as much time to work on this project as I had thought I would. Because scheduling meetings with myself is easier than scheduling meetings with other people, at the start of the project I kept rescheduling time I had planned to work on this project in order to meet with one of the three teams I was on. In the end, though, this often resulted in me planning to work on this project sometime well after midnight, which often didn't happen because I needed to sleep. After I realized that this was putting ​ me behind schedule, I became more firm about working when I was planning to despite other obligations. This will be an important lesson to keep in mind when I have to schedule multiple projects in the future.
 +
 +Trying to debug FPGA issues also took a lot more time than I had thought it would. However, my experience seems to be an outlier, so while it's something I will consider in the future, I doubt I'll plan to spend as much time debugging as I spent in this project when scheduling future projects.
  
 ====To Do==== ====To Do====
 +There were many things that I was hoping to do with this project beyond the minimum deliverable.
 +
 +One easy thing that could be done would be to increase the number of notes that the FPGA can output. Right now, if multiple switches are high, the lowest note is the one that gets played. However, it would be easy to change the code so that different combinations of switches being high resulted in different notes.
 +
 +Making changes to the DAC is also something that could be done. I used 30 and 60 kΩ resistors, which is probably higher than necessary. Also the resistors had a 5% tolerance, which given the large resistances means that the actual values of the resistors varied a not insignificant amount and the DAC was not as accurate as it could be. However, changing this might not make any appreciable difference in sound quality.
 +
 +Additive synthesis is also something that could be experimented with to change and improve the way that the output sounds. This involves adding sine waves of different amplitudes and frequencies together to produce different sounds.
 +
 +=====Files=====
 +{{projects:​note_generator_demo_video.zip}}:​ Video demonstrating the FPGA outputting an A natural minor scale.
  
 +{{projects:​notegeneratorproject.zip}}:​ Contains all of the project files.
projects/fpga_note_generator.1387744820.txt.gz · Last modified: 2013/12/22 15:40 by criley1