蜂鸣器简介
蜂鸣器分类:
按照工作原理可分为:压电式蜂鸣器和电磁式蜂鸣器;
按照音源可分为:有源蜂鸣器和无源蜂鸣器。
有源蜂鸣器:内部有振荡源,直接通以直流电即可发出声音;
无源蜂鸣器:内部无振荡源,需要通以方波、PWM信号才能发出声音。
无源蜂鸣器需要输入一定频率的方波或者PWM信号,蜂鸣器就可以发出声音。输入不同频率的信号,蜂鸣器可以发出不同音色的声音。
PWM:Pulse Width Modulation,脉冲宽度调制。
module beep_tiger(
input wire clk,
input wire rst_n,
output reg beep
);
//每个音符震动一次所占用的时钟周期
//1秒 / 频率 = 震动1次所用的时间
//震动1次所用的时间 / 20ns = 震动1次所用的周期
parameter DO = 16'd47755,//(50_000_000 / 1047)
RE = 16'd42553,
MI = 16'd37907,
FA = 16'd35790,
SO = 16'd31887,
LA = 16'd28409,
SI = 16'd25419;
//单个音符持续最大时间的参数
parameter TIME_MAX = 26'd25_000_000 - 1;
//单个音符持续最大时间的寄存器,以1秒钟举例,50_000_000次的时钟周期
reg [25:0] note_cnt; //34个音符的寄存器
reg [5:0] music_data; //音符的频率计数器(DO.RE.MI的频率计数器)frequency counter
reg [15:0] freq_cnt; //至少要16个位宽
//所有音符频率的数据,存放整个乐谱
reg [15:0] freq_data;
//单个音符持续最大时间的计数器
always@(posedge clk or negedge rst_n)begin
if(!rst_n)
note_cnt <= 0;
else if(note_cnt == TIME_MAX )
note_cnt <= 0;
else
note_cnt <= note_cnt + 1;
end
//34个音符切换的计数器
always@(posedge clk or negedge rst_n)begin
if(!rst_n)
music_data <= 0;
else if((music_data == 6'd33) && (note_cnt == TIME_MAX))
music_data <= 0;
else if(note_cnt == TIME_MAX)
music_data <= music_data + 1;
else
music_data <= music_data;
end
//频率计数器
always@(posedge clk or negedge rst_n)begin
if(!rst_n)
freq_cnt <= 0;
else if(freq_cnt == freq_data)
freq_cnt <= 0;
else
freq_cnt <= freq_cnt + 1;
end
//所有音符频率的数据,按顺序排开,存放整个乐谱
always@(posedge clk or negedge rst_n)begin
if(!rst_n)
freq_data <= DO;
else
case(music_data)
6'd0 : freq_data <= DO;//1
6'd1 : freq_data <= RE;//2
6'd2 : freq_data <= MI;//3
6'd3 : freq_data <= DO;//1
6'd4 : freq_data <= DO;//1
6'd5 : freq_data <= RE;//2
6'd6 : freq_data <= MI;//3
6'd7 : freq_data <= DO;//1
6'd8 : freq_data <= MI;//3
6'd9 : freq_data <= FA;//4
6'd10 : freq_data <= SO;//5
6'd11 : freq_data <= MI;//3
6'd12 : freq_data <= FA;//4
6'd13 : freq_data <= SO;//5
6'd14 : freq_data <= SO;//5
6'd15 : freq_data <= LA;//6
6'd16 : freq_data <= SO;//5
6'd17 : freq_data <= FA;//4
6'd18 : freq_data <= MI;//3
6'd19 : freq_data <= DO;//1
6'd20 : freq_data <= SO;//5
6'd21 : freq_data <= LA;//6
6'd22 : freq_data <= SO;//5
6'd23 : freq_data <= FA;//4
6'd24 : freq_data <= MI;//3
6'd25 : freq_data <= DO;//1
6'd26 : freq_data <= RE;//2
6'd27 : freq_data <= SO;//5
6'd28 : freq_data <= DO;//1
6'd29 : freq_data <= DO;//0/1
6'd30 : freq_data <= RE;//2
6'd31 : freq_data <= SO;//5
6'd32 : freq_data <= DO;//1
6'd33 : freq_data <= DO;//0/1
default : freq_data <= DO;
endcase
end
//定义占空比
wire [14:0] duty_data;
//assign duty_data = freq_data >> 1;//占空比50%
assign duty_data = freq_data >> 2;//占空比25%
//占空比小一点,蜂鸣器发出的声音会清晰一点
always@(posedge clk or negedge rst_n)begin
if(!rst_n)
beep <= 0;
else if(freq_cnt >= duty_data)
beep <= 1;
else
beep <= 0;
end
endmodule