Verilog中如何消除按钮抖动,避免单次按压被识别多次?
按钮防抖的硬件实现方案(无需轮询/仿真延迟)
针对按钮抖动导致多次移位的问题,完全可以通过直接处理按钮输入解决,下面给出两种适用于实际硬件的纯逻辑实现方案,不需要内部轮询,也不用#10这类仅适用于仿真的延迟语句:
方案1:单次按压锁定(每毫秒仅响应一次)
核心思路是:检测到按钮上升沿后,立即锁定1毫秒,这段时间内不再响应任何边沿,避免抖动触发多次移位。依赖系统全局时钟(比如常见的50MHz)实现定时,属于同步逻辑处理输入。
module TopLevel( input CLK, // 系统全局时钟,例:50MHz input KEY, // 带抖动的按钮输入 input SW, output reg [9:0] LEDR ); // 异步输入同步:避免亚稳态 reg KEY_sync1, KEY_sync2; always @(posedge CLK) begin KEY_sync1 <= KEY; KEY_sync2 <= KEY_sync1; end wire KEY_posedge = KEY_sync2 & ~KEY_sync1; // 提取按钮上升沿 // 1ms定时锁定计数器(50MHz下,50000个时钟周期=1ms) reg [15:0] debounce_cnt; reg debounce_lock; always @(posedge CLK) begin if(KEY_posedge) begin debounce_cnt <= 16'd50000; // 加载定时值 debounce_lock <= 1'b1; // 触发锁定 end else if(debounce_cnt != 0) begin debounce_cnt <= debounce_cnt - 1'b1; end else begin debounce_lock <= 1'b0; // 定时结束,解锁 end end // 仅在未锁定时响应有效上升沿,执行移位 always @(posedge CLK) begin if(KEY_posedge && !debounce_lock) begin LEDR <= {LEDR[8:0], SW}; // 简化移位逻辑,与原代码功能一致 end end endmodule
逻辑说明:
- 先将异步的
KEY输入同步到系统时钟域,解决跨时钟域亚稳态问题; - 检测到上升沿后启动1ms计数器,期间通过
debounce_lock禁止再次响应; - 定时结束后解锁,等待下一次有效按压,单次抖动只会触发一次移位。
方案2:滞回式稳定电平检测
核心思路是:只有当按钮电平持续稳定一段时间(比如20ms,覆盖绝大多数物理抖动时长)后,才判定为有效按压,再触发移位。同样基于系统时钟实现,属于输入信号的滤波处理。
module TopLevel( input CLK, // 系统全局时钟,例:50MHz input KEY, // 带抖动的按钮输入 input SW, output reg [9:0] LEDR ); // 异步输入同步 reg KEY_sync1, KEY_sync2; always @(posedge CLK) begin KEY_sync1 <= KEY; KEY_sync2 <= KEY_sync1; end // 稳定电平计数:跟踪电平持续时间 reg [19:0] stable_cnt; reg KEY_stable; always @(posedge CLK) begin if(KEY_sync2 != KEY_stable) begin stable_cnt <= 20'd1000000; // 50MHz下,1e6个周期=20ms KEY_stable <= KEY_sync2; end else if(stable_cnt != 0) begin stable_cnt <= stable_cnt - 1'b1; end end // 提取稳定后的有效上升沿 reg KEY_stable_prev; always @(posedge CLK) begin KEY_stable_prev <= KEY_stable; end wire KEY_valid_posedge = (stable_cnt == 0) && KEY_stable && ~KEY_stable_prev; // 执行移位操作 always @(posedge CLK) begin if(KEY_valid_posedge) begin LEDR <= {LEDR[8:0], SW}; end end endmodule
逻辑说明:
- 同步输入后,用计数器跟踪电平变化:一旦电平改变,重置计数器;
- 只有当电平持续稳定20ms(计数器归0),才认为是有效电平;
- 检测稳定电平的上升沿作为触发信号,彻底过滤抖动毛刺。
两种方案都是纯硬件逻辑实现,完全适配实际FPGA/ASIC环境,不存在仿真延迟的问题,也不需要轮询机制,属于直接处理按钮输入的防抖方案。
内容的提问来源于stack exchange,提问作者Alex Kibbe
相关产品推荐
相关产品推荐

