music_tune.v

来自「基于FPGA的VHDL编程实现各种音频信号」· Verilog 代码 · 共 73 行

V
73
字号
// 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 + =
减小字号Ctrl + -
显示快捷键?