FPGA Programming
The final challenge!
In this objective, my goal was to create a sound wave frequency generator, given a target frequency, a clock, and a speaker output, using Verilog. I would design a Field Programmable Gate Array (FPGA), presumably to design an Application Specific Integrated Circuit (ASIC) when this gets mass-produced for the Kurse-em Out Karen doll.
Verilog is the Hardware Description Language (HDL) used to create the FPGA application, and understanding it is to undo everything you've learned about application flow when programming something in C or Python. In Verilog, actions are performed only when a signal is sent across a physical wire. As a result, loops are not made in the conventional sense, only that a "loop" can be relied upon if the system gets a repetitive signal. In this case, that signal would come from a 125Mhz clock, or more specifically a wire that oscillates between 1
and 0
125,000,000 times per second. To that end, knowing how fast the clock oscillates is the key to timing actions within the circuit.
The goal here is to read in a supplied frequency on the freq
input, then output the same frequency as a tone from the speaker. So if the desired frequency comes in at 500 Hz
, I have to write the proper mathematical equation to somehow change the 125 million cycles per second into 500 pulses per second of the speaker. Finding out the proper math would end up not being the hard part, perhaps the hardest was fiddling with the numbers properly to obtain a crystal-clear frequency. But I digress.
The Logic I Followed
Okay, so I know a few things here:
- The clock is 125Mhz fast, so it cycles 125 million times per second.
- We're given the desired frequency through the
freq
input. - The freq is a 6 digit integer that should be read in as a
float
, so basically123456
should be interpreted as1234.56 Hz
. - The first goal is to hit
500 Hz
, so the expected number on thefreq
input should be050000
, or500.00 Hz
. - This means we need to engage the speaker 500 times per second.
The way I thought to do that was to divide 125,000,000
by 500
, which becomes 250,000
. So my logic is to start up a counter that counts up to 250,000
, then resets the counter back to zero and engages the speaker only once. If the board does this sequence of counting up until it hits 250K and then pulses the speaker once 500 times in a second, then I have officially pulsed the speaker at 500 Hz.
To expand upon that, instead of using hard numbers, the logic will be the following. After getting the "cycle frequency," (which, in this case, is 250,000), set the counter to 0
and run the following loop:
This logic worked pretty well for most of the "easy" numbers, like 500
, 1000
, and 2000
. But when numbers got a little more complex, such as 1234.56
, it would not be as accurate. The way to fix this was through the usage of a rounding function. This rounding function would execute on every single positive edge of the clock, and consisted of the following:
1 2 3 4 5 6 7 |
|
To break it down, using the number 1234.56
, we know that since the tens decimal point is greater than or equal to 5, then we need to round up. So given the above example, I'll go through each step.
- First, get the integer value of
(1234.56 * 10)
, which would be12345
. Y'know, the same password I have on my luggage. - Second, get the integer value of
(1234.56) * 10
, which would be12340
. - Third, subtract the two. In this case,
12345 - 12340
, which would be5
. - Finally, is the resulting number greater than
4
? It is, so then add 1 to the total frequency, which is then used to calculate how many times we should iterate before pulsing the speaker.
Ultimately, after a lot of trial and error, the following code is what finally got me to finish the challenge with 99.99% accuracy:
The Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 |
|
The aftermath
Upon successfully completing all of the frequency challenges (500.00Hz, 1000.00Hz, 2000.00Hz, and a random 4-digit-2-decimal-points value), I was given the ability to generate a chip with my frequency generator. Upon doing so, I added the chip to a Texas Instrument Speak & Spell:
Which in turn emitted a cute little tone, and what showed up but...
...Whoa.
This was the final challenge I needed to solve! I was quick to post this to Twitter and soon I received a fair amount of Kudos!
Have I mentioned how much I love the SANS Holiday Hack Challenges?