1.按键软件去抖动
input[KEY_WIDTH-1:0] key_in; //外部按键输入
output[KEY_WIDTH-1:0]key_out; //按键消抖输出
reg[KEY_WIDTH-1:0]dout1,dout2,dout3; //寄存器
parameter KEY_WIDTH = 8; //参数
assign key_out = (dout1 | dout2 | dout3); //按键消抖输出
always @(posedge clk) // always @(posedge count[17]) 当系统时钟是48MHZ时,count一直计算,计到18位为1时也就满足了按键时钟的要求
begin
dout1 <= key_in;
dout2 <= dout1;
dout3 <= dout2;
end
//下面是利用按键 消抖后的输出 设置一个标志位,将琴键开关转换为乒乓开关 就需要点击2下才可以回复到原来的状态
always @(negedge key_out)
begin
keyen = ~keyen;//将琴键开关转换为乒乓开关
end
或者利用边沿检测的知识
always @(posedge clock)//按键6
begin
if(key_out )//2中的key_out
keyen = ~keyen;
end
按键消抖关键在于提取稳定的低电平状态,滤除前沿、后沿抖动毛刺。对于一个按键信号,可以用一个脉冲对它进行采样。如果连续三次采样为低电平,可以认为信号已经处于键稳定状态,这时输出一个低电平按键信号。继续采样的过程中如果不能满足连续三次采样为低,则认为键稳定状态结束,这时输出变为高电平。
按键消抖:按键消抖处理一般有硬件和软件两种方法。软件消抖是检测到有触发后,延时一段时间(一般为10ms)后再检测触发状态,如果与之前检测到的状态相同,则认为有按键按下;如果没有。则判断为误触发。硬件就是加去抖动电路,这样可以从根本上解决按键抖动的问题。
消抖电路的采样时钟要实际应用可以灵活改变,因为按键触发的时间一般为几百毫秒,干扰毛刺脉宽一般为几百毫秒到几毫秒,所以采样时钟的周期一般为几毫秒。
这里我们可以选择5ms 即上式的clk的频率为200HZ
2.按键的边沿(下降沿)检测
reg [7:0] dout1,dout2,dout3,buff;
always @(posedge clk)
begin
dout1 <= key_in;
dout2 <= dout1;
dout3 <= dout2;
end
always @(posedge clk)
begin
buff<=dout1|dout2|dout3;
end
assign key_out = ~(dout1 | dout2 | dout3)&buff;//按键的边缘检测 if(key_out[0])..然后就可以用key_out来作为控制信号了
//时钟分频部分 系统时钟 48MHZ
always @(posedge clock)
begin
if (count < 17'd120000)
begin
count <= count + 1'b1;
div_clk <= 1'b0;
end
else
begin
count <= 17'd0;
div_clk <= 1'b1;
end
end
//按键消抖部分
always @(posedge clock)
begin
if(div_clk) //分频时钟,用于消抖和扫描
begin
dout1 <= key;
dout2 <= dout1;
dout3 <= dout2;
end
end
//assign key_out = (dout1 | dout2 | dout3); //按键消抖输出
//按键边沿检测部分
always @(posedge clock)
begin
buff <= dout1 | dout2 | dout3; //buff为按键消抖输出
end
assign key_edge = ~(dout1 | dout2 | dout3) & buff; //按键消抖输出
always @(posedge clock) //有按键按下
begin
if(key_edge[0])
hex_r[15:12] <= hex_r[15:12] + 1'b1;
end
3.程序中用到的小分频程序
always @(posedge clk)
begin
if(dividi_clk)
counter<=26'd0;//使counter为0
else
counter<=counter+1'b1;
end
assign dividi=(counter>=26'd48000);//26‘d48000就是分频数(-1)。
如图是8分频的时序图
reg[16:0]count;//时钟分频计数器 120000分频
always @(posedge clock)
begin
if (count < 17'd120000)
begin
count <= count + 1'b1;
div_clk <= 1'b0;
end
else
begin
count <= 17'd0;
div_clk <= 1'b1;
end
end
always @(posedge clock) 都用系统时钟if(div_clk)
always @(posedge clk)
begin
if(cnt==设定值) //设定值-起始值=分频数的一半,即计数到分频数的一半时反转输出
begin
cnt<=起始值;