简单介绍
本来是需要介绍蜂鸣器的,这里就不多做介绍了,因为我也不知道怎么解释,这里只是加入了自己的理解。
蜂鸣器在Verilog语言里面一般用beep来写,高电平表示关闭,而低电平表示触发。只是让蜂鸣器响这些就够了,但是我们今天需要播放音乐,需要播放不同的音频,所以这里有一些新的理解。
音频介绍
一般能够找到的简谱频率都是偏低音,也就是262hz开始的,但是这些低音在蜂鸣器上发音不太准,(也许占空比低点会好点,但是我没试过)这里选择了钢琴的高音区,如下图。
这里直接使用的白键的音,我们使用50MHz/音阶频率得到的结果,表示我们要在相应的位置计数并改变蜂鸣器的状态,可让蜂鸣器发出一秒内相应的音节频率。
今天我们直接写一个明日香处刑曲,也就是马来西亚民谣RASA SAYANGE(乐)。
代码内容
module beep_play(
input wire clk ,
input wire rst_n ,
output wire beep
);
//各个音节代码,方便使用
localparam G1 = 5'd01 ,
G2 = 5'd02 ,
G3 = 5'd03 ,
G4 = 5'd04 ,
G5 = 5'd05 ,
G6 = 5'd06 ,
G7 = 5'd07 ;
localparam M1 = 5'd08 ,
M2 = 5'd09 ,
M3 = 5'd10 ,
M4 = 5'd11 ,
M5 = 5'd12 ,
M6 = 5'd13 ,
M7 = 5'd14 ;
localparam D1 = 5'd15 ,
D2 = 5'd16 ,
D3 = 5'd17 ,
D4 = 5'd18 ,
D5 = 5'd19 ,
D6 = 5'd20 ,
D7 = 5'd21 ;
//计数器,用于计时和记录音节位置
parameter MAX_0_3s = 24'd15_000_000;
parameter MAX_FLAG = 8'd147;
reg beep_r;//控制蜂鸣器
reg [7:0] flag;//记录蜂鸣器的音节位置
reg [4:0] music_r;//记录音节的内容
reg [23:0] cnt;//时间计数器
reg [17:0] MAX_music;//用于记录音节频率
reg [17:0] cnt_music;//记录单个音节的震荡计数
//记录单个音节的长度
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
cnt <= 24'd0;
end
else if (cnt == MAX_0_3s - 1'd1) begin
cnt <= 24'd0;
end
else begin
cnt <= cnt + 1'd1;
end
end
//记录音节位置,用于表示音乐播放到某个位置
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
flag <= 8'd0;
end
else if (flag == MAX_FLAG && cnt == MAX_0_3s - 1'd1) begin
flag <= 8'd0;
end
else if (flag != MAX_FLAG && cnt == MAX_0_3s - 1'd1) begin
flag <= flag + 1'd1;
end
else begin
flag <= flag;
end
end
//用于记录音节的震荡位置,此数*频率=50MHz,既是上述的
always @(*) begin
case (music_r)
D1 : MAX_music = 18'd47778 ;
D2 : MAX_music = 18'd42565 ;
D3 : MAX_music = 18'd37922 ;
D4 : MAX_music = 18'd35793 ;
D5 : MAX_music = 18'd31888 ;
D6 : MAX_music = 18'd28409 ;
D7 : MAX_music = 18'd25310 ;
M1 : MAX_music = 18'd23889 ;
M2 : MAX_music = 18'd21283 ;
M3 : MAX_music = 18'd18961 ;
M4 : MAX_music = 18'd17897 ;
M5 : MAX_music = 18'd15944 ;
M6 : MAX_music = 18'd14205 ;
M7 : MAX_music = 18'd12655 ;
G1 : MAX_music = 18'd11945 ;
G2 : MAX_music = 18'd10641 ;
G3 : MAX_music = 18'd9480 ;
G4 : MAX_music = 18'd8948 ;
G5 : MAX_music = 18'd7972 ;
G6 : MAX_music = 18'd7102 ;
G7 : MAX_music = 18'd6327 ;
default : MAX_music = 18'd6327 ;
endcase
end
//用于记录音节的位置的音频
//次吃保存的乐谱是号称明日香处刑曲的RASA SAYANGE,简谱参考哔哩哔哩作者,有一些我的修改,毕竟机器比人要不会变通一点。
//作者:Tiny五角星 https://www.bilibili.com/read/cv23088573/ 出处:bilibili
always @(*) begin
case (flag)
8'd000 : music_r = M6;
8'd001 : music_r = M6;
8'd002 : music_r = M5;
8'd003 : music_r = M4;
8'd004 : music_r = M3;
8'd005 : music_r = M3;
8'd006 : music_r = M1;
8'd007 : music_r = M3;
8'd008 : music_r = M2;
8'd009 : music_r = M2;
8'd010 : music_r = D7;
8'd011 : music_r = D7;
8'd012 : music_r = M1;
8'd013 : music_r = M1;
8'd014 : music_r = M1;
8'd015 : music_r = M1;
8'd016 : music_r = M5;
8'd017 : music_r = M5;
8'd018 : music_r = M5;
8'd019 : music_r = M5;
8'd020 : music_r = G1;
8'd021 : music_r = G1;
8'd022 : music_r = M7;
8'd023 : music_r = M6;
8'd024 : music_r = M5;
8'd025 : music_r = M5;
8'd026 : music_r = M3;
8'd027 : music_r = M4;
8'd028 : music_r = M5;
8'd029 : music_r = M5;
8'd030 : music_r = G1;
8'd031 : music_r = G1;
8'd032 : music_r = M6;
8'd033 : music_r = M6;
8'd034 : music_r = M5;
8'd035 : music_r = M4;
8'd036 : music_r = M3;
8'd037 : music_r = M3;
8'd038 : music_r = M1;
8'd039 : music_r = M3;
8'd040 : music_r = M2;
8'd041 : music_r = M2;
8'd042 : music_r = D7;
8'd043 : music_r = D7;
8'd044 : music_r = M1;
8'd045 : music_r = M1;
8'd046 : music_r = M1;
8'd047 : music_r = M1;
8'd048 : music_r = M3;
8'd049 : music_r = M4;
8'd050 : music_r = M5;
8'd051 : music_r = M5;
8'd052 : music_r = G1;
8'd053 : music_r = G1;
8'd054 : music_r = M7;
8'd055 : music_r = M6;
8'd056 : music_r = M5;
8'd057 : music_r = M5;
8'd058 : music_r = M3;
8'd059 : music_r = M4;
8'd060 : music_r = M5;
8'd061 : music_r = M5;
8'd062 : music_r = G1;
8'd063 : music_r = G1;
8'd064 : music_r = M6;
8'd065 : music_r = M6;
8'd066 : music_r = M5;
8'd067 : music_r = M4;
8'd068 : music_r = M3;
8'd069 : music_r = M3;
8'd070 : music_r = M1;
8'd071 : music_r = M3;
8'd072 : music_r = M2;
8'd073 : music_r = M2;
8'd074 : music_r = D7;
8'd075 : music_r = D7;
8'd076 : music_r = M1;
8'd077 : music_r = M1;
8'd078 : music_r = M1;
8'd079 : music_r = M1;
8'd080 : music_r = M3;
8'd081 : music_r = M4;
8'd082 : music_r = M5;
8'd083 : music_r = M5;
8'd084 : music_r = M5;
8'd085 : music_r = M5;
8'd086 : music_r = M3;
8'd087 : music_r = M3;
8'd088 : music_r = M3;
8'd089 : music_r = M4;
8'd090 : music_r = M5;
8'd091 : music_r = M5;
8'd092 : music_r = M5;
8'd093 : music_r = M5;
8'd094 : music_r = M3;
8'd095 : music_r = M3;
8'd096 : music_r = M3;
8'd097 : music_r = M4;
8'd098 : music_r = M6;
8'd099 : music_r = M6;
8'd100 : music_r = M5;
8'd101 : music_r = M4;
8'd102 : music_r = M3;
8'd103 : music_r = M3;
8'd104 : music_r = M1;
8'd105 : music_r = M3;
8'd106 : music_r = M2;
8'd107 : music_r = M2;
8'd108 : music_r = D7;
8'd109 : music_r = D7;
8'd110 : music_r = M1;
8'd111 : music_r = M1;
8'd112 : music_r = M1;
8'd113 : music_r = M1;
8'd114 : music_r = M3;
8'd115 : music_r = M4;
8'd116 : music_r = M5;
8'd117 : music_r = M5;
8'd118 : music_r = M5;
8'd119 : music_r = M5;
8'd120 : music_r = M3;
8'd121 : music_r = M3;
8'd122 : music_r = M3;
8'd123 : music_r = M4;
8'd124 : music_r = M5;
8'd125 : music_r = M5;
8'd126 : music_r = M5;
8'd127 : music_r = M5;
8'd128 : music_r = M3;
8'd129 : music_r = M3;
8'd130 : music_r = M3;
8'd131 : music_r = M4;
8'd132 : music_r = M6;
8'd133 : music_r = M6;
8'd134 : music_r = M5;
8'd135 : music_r = M4;
8'd136 : music_r = M3;
8'd137 : music_r = M3;
8'd138 : music_r = M1;
8'd139 : music_r = M3;
8'd140 : music_r = M2;
8'd141 : music_r = M2;
8'd142 : music_r = D7;
8'd143 : music_r = D7;
8'd144 : music_r = M1;
8'd145 : music_r = M1;
8'd146 : music_r = M1;
8'd147 : music_r = M1;
default : music_r = M1;
endcase
end
//用于记录每个音节应该在那个位置进行震荡
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
cnt_music <= 18'd0;
end
else if (cnt == MAX_0_3s - 1'd1 || cnt_music == MAX_music - 1'd1) begin
cnt_music <= 18'd0;
end
else begin
cnt_music <= cnt_music + 1'd1;
end
end
//让蜂鸣器在指定位置震荡
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
beep_r <= 1'b1;
end
else if (cnt_music >= (MAX_music - 1'd1) / 2) begin
beep_r <= 1'b0;
end
else begin
beep_r <= 1'b1;
end
end
assign beep = beep_r;
endmodule
结束
今天还是玩得还是很开心的,拜拜了您嘞!