module k_xd( //定义模块的输入输出端口,三个输入信号,系统时钟信号s_clk
input s_clk, //复位信号rst_n,按键输入信号k
input rst_n, //两个输出信号,按键数据有效信号k_flag,按键消抖后的数据k_value
input k,
output reg k_flag,
output reg k_value
);
reg [31:0] delay_c; //定义两个寄存器变量,delay_c用于延时计数
reg k_reg; //k_reg用于存储按键k的状态
always @(posedge s_clk or negedge rst_n) //为时序逻辑电路,在s_clk上升沿,或rst_n下降沿触发
begin //如果复位信号有效,初始化定义的寄存器变量k_reg
if(!rst_n) //delay_c
k_reg <= 1'b1; //复位信号无效时,把按键k的状态值赋给k_reg
delay_c <= 32'd0; //当按键值发生变化时(按键按下一次),给延时变量
end //delay_c赋初值,延时时间为20ms
else begin //当按键稳定时,delay_c递减,延时20ms
k_reg <= k;
if(k_reg != k)
delay_c <= 32'd1000_0000;
else if(k_reg == k) begin
if(delay_c > 32'd0)
delay_c <= delay_c - 1'b1;
else
delay_c <= delay_c;
end
end
end
always @(posedge s_clk or negedge rst_n) //s_clk上升沿或者rst_n下降沿触发
begin
if(!rst_n) begin //如果复位信号有效,标志变量k_falg置0,
k_flag <= 1'b0; //k_value置1
k_value <= 1'b1; //当延时20ms时,标志信号k_flag置1
end //此时按键值为有效值,赋予变量k_value
else begin
if(delay_c == 32'd1) begin //没有到达延时时间时,标志位k_flag,变量值k_value
k_flag <= 1'b1; //不变
k_value <= k;
end
else begin
k_flag <= 1'b0;
k_value <= k_value
end
end
end
endmodule
学习过单片机一段时间,按键消抖一般采用延时消抖,当按键按下时,先延时一段时间,等按键稳定时,再读取此时按键的值。
本实验为按键控制蜂鸣器发音,蜂鸣器高电平发音,按一次键可以改变蜂鸣器的发音状态。
module b_c( //按键控制蜂鸣器模块的端口定义,时钟信号s_clk,复位信号rst_n
input s_clk, //按键有效信号k_flag,按键状态信号k_value
input rst_n, //蜂鸣器输出b
input k_flag,
input k_value,
output reg b
);
always @(posedge s_clk or negedge rst_n) //程序很简单,当复位信号有效,蜂鸣器变量初始化置1
begin
if(!rst_n) //当k_falg有效时,此时为消抖后的按键状态
b <= 1'b1; //蜂鸣器变量发生反转
else if(k_flag or (~k_value))
b <= ~b;
end
endmodule
编写一个主程序调用上述两个模块。
module k_b(
input s_clk,
input rst_n,
input k,
output b
);
wire k_value;
wire k_flag;
k_xd u_k_xd(
.s_clk (s_clk),
.rst_n (rst_n),
.k (k),
.k_flag (k_flag),
.k_value (k_value)
);
b_c u_b_c(
.s_clk (s_clk),
.rst_n (rst_n),
.k_falg (k_flag),
.k_value (k_value),
.b (b)
);