Music box 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 octave, so 64 notes give us over 5 octaves, more than enough for a little tune.
Step 1.
To play a range of increasing notes, we instantiate a 28-bit 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 (a bit over 5 octaves, so 3 bits are enough, since it goes from 0 to 5) 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 care 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.
|
always @* 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, now we need 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( input clk, output reg 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 @* 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 always @(posedge clk) if(counter_note==0 && counter_octave==0) speaker <= ~speaker; endmodule |
Divide by 12:
The "divide by 12" module takes a variable 6-bit value (numerator) and divides it by the fixed value 12 (denominator). That gives us a 3-bit quotient (0..5) and a 4-bit remainder (0..11). To divide by 12, it is easier to divide by 4 first, then by 3. Dividing by 4 is trivial: we remove 2 bits out of the numerator, and copy them to the remainder. So we are left with 6-2=4 bits to divide by the value "3", which we do with a lookup table.
|
module divide_by12( input [5:0] numer, output reg [2:0] quotient, output [3:0] remain ); reg [1:0] remain_bit3_bit2; assign remain = {remain_bit3_bit2, numer[1:0]}; // the first 2 bits are copied through always @* // 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 |