📄 music_tune.v
字号:
// music_tune.v
module music_tune(clk, speaker);
input clk;
output speaker;
//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];
//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));
/*
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.
*/
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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -