fpga4fun.com - where FPGAs are fun.
Home
Welcome
Information


FPGA projects
Music box
Pong game
R/C servos
Text LCD module
Quadrature decoder
PWM and one-bit DAC
Debouncer
LED displays
Crossing clock domains
External contributions

FPGA interface projects
RS-232
JTAG
I2C
EPP
SPI
CNC steppers

FPGA advanced projects
Graphic LCD panel
Digital oscilloscope
10BASE-T interface
PCI interface
Spoc CPU core

Hands-on
A simple oscilloscope


FPGA introduction
What are FPGAs?
How FPGAs work
FPGA pins
Clocks and global lines
Download cables
Configuration
Learn more

FPGA software
Design software
Pin assignment
Design-entry/HDL
Simulation/HDL
Synthesis and P&R

FPGA electronic
SMD technology
Crystals and oscillators

HDL info
HDL tutorials
Verilog tips
VHDL tips

Quick-start guides
ISE
Quartus

Site
News
FPGA links
HDL tutorials
Forum


Music box - part 3

Playing notes
Now we'd like to play a tune. We need a way to play notes, like on a keyboard.
If we use 6 bits to encode a note, we can get 64 notes. There are 12 notes per octaves, so 64 notes gives us more than 5 octaves, more than enough for a little tune.
Step 1.
To play a range of increasing notes, we instantiate a 28 bits counter, from which we extract the 6 most significant bits, to give us the 6 bits of the note we want to play.

reg [27:0] tone;
always @(posedge clk) tone <= tone+1;

wire [5:0] fullnote = tone[27:22];

With a 25Mhz clock, each note lasts 167ms and it takes 10.6s to play all 64 notes.
Step 2.
We divide the "fullnote" by 12. That gives us the octave (5 octaves, so 3 bits are enough, since it goes from 0 to 4) and the note (from 0 to 11, so 4 bits).

wire [2:0] octave;
wire [3:0] note;
divide_by12 divby12(.numer(fullnote[5:0]), .quotient(octave), .remain(note));

You can see that we instantiate a sub-module called "divide_by12" which takes case of the division. Details are shown later.
Step 3.
To go from one octave to the next, frequency is multiplied by "2". Easy to do in hardware, we do that in step 4.
To go from one note to the next, frequency is multiplied by "1.0594". Not really easy to do in hardware. So we use a look-up table with pre-calculated values.

We divide the main clock by 512 for note A, by 483 for note A#, by 456 for note B... Remember, dividing by a lower value gives us a higher frequency/higher note, that's what we want.

always @(note)
case(note)
  0: clkdivider = 512-1; // A
  1: clkdivider = 483-1; // A#/Bb
  2: clkdivider = 456-1; // B
  3: clkdivider = 431-1; // C
  4: clkdivider = 406-1; // C#/Db
  5: clkdivider = 384-1; // D
  6: clkdivider = 362-1; // D#/Eb
  7: clkdivider = 342-1; // E
  8: clkdivider = 323-1; // F
  9: clkdivider = 304-1; // F#/Gb
  10: clkdivider = 287-1; // G
  11: clkdivider = 271-1; // G#/Ab
  12: clkdivider = 0; // should never happen
  13: clkdivider = 0; // should never happen
  14: clkdivider = 0; // should never happen
  15: clkdivider = 0; // should never happen
endcase

always @(posedge clk) if(counter_note==0) counter_note <= clkdivider; else counter_note <= counter_note-1;

Every time "counter_note" equals 0, that gives us a tick for the next stage: the octave divider.
Step 4.
Ok, we need now to take care of the octave.
For the lowest octave, we divide "counter_note" by 256. For octave 1, we divide by 128... and so on...

reg [7:0] counter_octave;
always @(posedge clk)
if(counter_note==0)
begin
 if(counter_octave==0)
  counter_octave <= (octave==0?255:octave==1?127:octave==2?63:octave==3?31:octave==4?15:7);
 else
  counter_octave <= counter_octave-1;
end

reg speaker;
always @(posedge clk) if(counter_note==0 && counter_octave==0) speaker <= ~speaker;

The full code is here:

module music(clk, speaker);
input clk;
output speaker;

reg [27:0] tone;
always @(posedge clk) tone <= tone+1;

wire [5:0] fullnote = tone[27:22];

wire [2:0] octave;
wire [3:0] note;
divide_by12 divby12(.numer(fullnote[5:0]), .quotient(octave), .remain(note));

reg [8:0] clkdivider;
always @(note)
case(note)
  0: clkdivider = 512-1; // A
  1: clkdivider = 483-1; // A#/Bb
  2: clkdivider = 456-1; // B
  3: clkdivider = 431-1; // C
  4: clkdivider = 406-1; // C#/Db
  5: clkdivider = 384-1; // D
  6: clkdivider = 362-1; // D#/Eb
  7: clkdivider = 342-1; // E
  8: clkdivider = 323-1; // F
  9: clkdivider = 304-1; // F#/Gb
  10: clkdivider = 287-1; // G
  11: clkdivider = 271-1; // G#/Ab
  12: clkdivider = 0; // should never happen
  13: clkdivider = 0; // should never happen
  14: clkdivider = 0; // should never happen
  15: clkdivider = 0; // should never happen
endcase

reg [8:0] counter_note;
always @(posedge clk) if(counter_note==0) counter_note <= clkdivider; else counter_note <= counter_note-1;

reg [7:0] counter_octave;
always @(posedge clk)
if(counter_note==0)
begin
 if(counter_octave==0)
  counter_octave <= (octave==0?255:octave==1?127:octave==2?63:octave==3?31:octave==4?15:7);
 else
  counter_octave <= counter_octave-1;
end

reg speaker;
always @(posedge clk) if(counter_note==0 && counter_octave==0) speaker <= ~speaker;

endmodule
Divide by 12:
The "divide by 12" module takes a 6 bits value (numerator) and divides it by 12 (denominator). That gives us a 3 bits quotient (0..5) and a 4 bits remainder (0..11). We tried to use the FPGA vendor provided "divide" function, but it is optimized for general divide, while here the denominator is fixed. So a specific divide function was made.

To divide by 12, the trick is to divide by 4 first, then by 3.
Dividing by 4 is trivial: we remove 2 bits out of the numerator, and copy it to the remainder. So we are left with 6-2=4 bits to divide by the value "3". That's easily done with a lookup table.

module divide_by12(numer, quotient, remain);
input [5:0] numer;
output [2:0] quotient;
output [3:0] remain;

reg [2:0] quotient;
reg [3:0] remain_bit3_bit2;

assign remain = {remain_bit3_bit2, numer[1:0]}; // the first 2 bits are copied through

always @(numer[5:2]) // and just do a divide by "3" on the remaining bits
case(numer[5:2])
  0: begin quotient = 0; remain_bit3_bit2 = 0; end
  1: begin quotient = 0; remain_bit3_bit2 = 1; end
  2: begin quotient = 0; remain_bit3_bit2 = 2; end
  3: begin quotient = 1; remain_bit3_bit2 = 0; end
  4: begin quotient = 1; remain_bit3_bit2 = 1; end
  5: begin quotient = 1; remain_bit3_bit2 = 2; end
  6: begin quotient = 2; remain_bit3_bit2 = 0; end
  7: begin quotient = 2; remain_bit3_bit2 = 1; end
  8: begin quotient = 2; remain_bit3_bit2 = 2; end
  9: begin quotient = 3; remain_bit3_bit2 = 0; end
  10: begin quotient = 3; remain_bit3_bit2 = 1; end
  11: begin quotient = 3; remain_bit3_bit2 = 2; end
  12: begin quotient = 4; remain_bit3_bit2 = 0; end
  13: begin quotient = 4; remain_bit3_bit2 = 1; end
  14: begin quotient = 4; remain_bit3_bit2 = 2; end
  15: begin quotient = 5; remain_bit3_bit2 = 0; end
endcase

endmodule
A tune
Let's play a tune now!
It's easy, just a matter of using a ROM to hold the notes.

reg [30:0] tone;
always @(posedge clk) tone <= tone+1;

wire [7:0] fullnote;
music_rom rom(.inclock(clk), .outclock(clk), .address(tone[29:22]), .q(fullnote));

The "music_rom" is generated by your FPGA vendor tool. For example, Altera's Quartus and its "megafunction" generator produces these files.

We also want that
so we change the last line of the previous design from
always @(posedge clk) if(counter_note==0 && counter_octave==0) speaker <= ~speaker;

into
always @(posedge clk) if(counter_note==0 && counter_octave==0 && tone[30]==0 && fullnote!=0) speaker <= ~speaker;

The rest of the design stays the same. Can you recognize the tune?




This page was last updated on August 09 2006.