**
FPGA实现按键控制蜂鸣器实验
**
实现功能:
使用按键控制蜂鸣器发声。初始状态为蜂鸣器鸣叫,按下开关后蜂鸣器停止鸣叫,再次按下开关,蜂鸣器重新鸣叫。
设计思路
由实验任务可知,我们只需要在按键按下时改变蜂鸣器的鸣叫状态,但实际上在按键按下的过程中存在按键抖动的干扰,体现在数字电路中就是不断变化的高低电平,为避免在抖动过程中采集到错误的按键状态,我们需要对按键数据进行消除抖动处理。因此本系统应至少包含按键消抖模块和蜂鸣器控制模块,
按键控制蜂鸣器系统框图如图所示。
代码
顶层模块:
module top_key_beep(
input clk,
input rst_n,
input key,
output beep
);
wire key_value;
wire key_flag;
key_filter u_key_filter(
.clk (clk),
.rst_n (rst_n),
.key_in (key),
.key_flag (key_flag),
.key_value (key_value)
);
beep_control u_beep_control(
.clk (clk),
.rst_n (rst_n),
.key_flag (key_flag),
.key_value (key_value),
.beep (beep)
);
endmodule
按键消抖模块:
module key_filter(
input clk , //时钟
input rst_n , //复位
input key_in , //按键信息
output reg key_flag, //按键有效标志,消抖后的
output reg key_value //有效的按键信息输出
);
reg [19:0] cnt_20ms; //20ms计数器
reg key_r0 ; //按键同步信号
reg key_r1 ; //按键打拍信号
reg add_flag; //20ms计数器开始计数标志
wire add_cnt_20ms; //计数器加一条件
wire end_cnt_20ms; //计数器结束条件
wire n_edge ; //按键按下的下降沿
//对按下的按键进行同步、打拍
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
key_r0<=1'b1;
key_r1<=1'b1;
end
else begin
key_r0<=key_in;
key_r1<=key_r0;
end
end
//下降沿检测
assign n_edge=~key_r0&key_r1;
//20ms计数器
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
cnt_20ms <= 20'b0;
end
else if(add_cnt_20ms)begin
if(end_cnt_20ms)
cnt_20ms<=20'b0;
else
cnt_20ms<=cnt_20ms + 1;
end
end
assign add_cnt_20ms = add_flag;
assign end_cnt_20ms = add_cnt_20ms && cnt_20ms== 1_000_000 - 1;
//add_flag
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
add_flag<=1'b0;
end
else if(n_edge!=1'b0)begin
add_flag<=1'b1;
end
else if(end_cnt_20ms)begin
add_flag<=1'b0;
end
end
//寄存按键信息key_value
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
key_value<=1'b1;
key_flag<=1'b0;
end
else if(end_cnt_20ms)begin
key_value<=key_r1;
key_flag<=1'b1;
end
else begin
key_value<=1'b1;
key_flag<=1'b0;
end
end
endmodule
蜂鸣器控制模块:
module beep_control(
input clk, //时钟
input rst_n, //复位
input key_flag, //按键标志
input key_value, //有效按键
output reg beep
);
always @(posedge clk or negedge rst_n)begin
if (!rst_n)
beep <= 1'b1;
else if (key_flag &&(~key_value))
beep <= ~beep;
end
endmodule