SMALL EXPERIMENT · FPGA & VHDL
Making an FPGA play music
Nishant and I first got an FPGA to play notes selected with switches and buttons. We worked through the clock dividers, pitch selection, display, and simulations that made the tone player work. Then we gave it a memory for notes and timing so it could play “Ode to Joy” on its own.

Playing a note by hand
The first version was a digital piano. Each of seven slide switches selected a natural note, from C through B. Buttons could shift that selection one semitone flat or sharp, choose an octave, or reset the circuit. The controls produced a five-bit note code. A zero code meant silence.
Those bits were a compact way to describe a note, not an audio recording. The note decoder translated the code into a clock-divider value. The divider then toggled a digital output to make a square wave for the speaker. Changing the code changed the wave’s frequency, which is what changed the pitch.
Getting the pitch right
We worked from the board’s 100 MHz clock, dividing it down to a 1 MHz timing signal for the audio path. The output flips state after each programmed count, so a complete high-low cycle takes twice that count. That makes the tone frequency 1,000,000 / (2 × divider) Hz.
For C3, the divider value was 3,822. The calculation gives 130.82 Hz against a target of 130.81 Hz. In our simulation, the speaker output had a period of about 7.64 ms, or roughly 130.9 Hz. Checking a measured period was more convincing than just trusting the note name in the code.
Showing and testing the note
The board’s seven-segment display showed the selected letter and octave. It lights one digit at a time and scans them quickly enough to look steady; the sharp sign uses the decimal point. That display made the pitch selection visible while we checked the speaker output.
We also drove the controls through a VHDL testbench before running the design on the board. Stepping through C3, D3, E3, and G3 let us see the note code, divider value, and sound output change together. The simulated waveforms helped separate an input-mapping mistake from a timing mistake.
Giving the piano a melody
Once the manual tone player worked, we replaced its switch-driven note selection with a sequencer. Our “Ode to Joy” arrangement contains 65 events, including rests. Two VHDL constant arrays hold matching note codes and durations; reading one position from each says what to play and how long to hold it.
Durations are counted in 50 ms steps. Ten ticks make a 500 ms note, while a zero note code mutes the speaker for a rest. The sequencer feeds the same note decoder, audio divider, and display used by the manual player. The song data changed how notes were selected, not how the circuit generated them.
Keeping pitch and tempo separate
The audio divider sets pitch; a second timing path decides when to move to the next event. We reused the divider to make a 20 Hz pulse from the 1 MHz signal, giving one tempo tick every 50 ms. A half-second note uses ten ticks, or about 120 beats per minute.
The sequencer tracks the current event and its elapsed ticks. When an event’s duration runs out, it clears the tick count and advances; after the final event, it returns to the start. A single-cycle tick pulse prevents the much faster main clock from advancing the melody more than once per beat. Adjacent events with the same pitch can still sound continuous without a rest between them, even though the stored notes are separate.
What I took from it
The switch-controlled piano made the relationship between a number and a pitch tangible. Adding the sequencer turned it into something that could perform on its own. There is no recording being played back: the FPGA generates each tone, counts its duration, and chooses the next note.

