Verilog 键值去抖动模块实现

该模块使用 Verilog 语言实现了按键去抖动功能,主要通过以下步骤完成:

  1. 按键信号采样: 使用两个寄存器 key_samp1key_samp2 分别对按键信号进行采样,并锁存采样结果。
  2. 按键变化检测: 使用两个信号 key_changed1key_changed2 来检测按键状态的改变,当按键由按下变为松开时,信号变为 1,并且只维持一个时钟周期。
  3. 延时计数: 使用一个 20 位的计数器 cnt,当检测到按键按下时,计数器被清零,然后开始计数。
  4. 去抖动判断: 当计数器计数值达到 20'hF_FFFF 时,表示已经经过了 20.9715ms,如果此时按键信号仍然保持稳定,则认为去抖动成功,并将按键信号写入 key_samp2 寄存器。
  5. 输出键值:key_changed2 信号为 1 时,输出最终去抖动后的键值 o_key_val

代码实现

module key_debounce(
  input            i_clk,
  input            i_rst_n,
  input      [9:1] i_key,               // 按下为 0,松开为 1
  output reg [9:1] o_key_val            // 键值
);

//++++++++++++++++++++++++++++++++++++++
reg [9:1] key_samp1, key_samp1_locked;

// 将 i_key 采集至 key_samp1
always @ (posedge i_clk, negedge i_rst_n)
  if(!i_rst_n) 
    key_samp1 <= 9'h1FF;
  else         
    key_samp1 <= i_key;

// 将 key_samp1 锁存至 key_samp1_locked
always @ (posedge i_clk, negedge i_rst_n)
  if(!i_rst_n) 
    key_samp1_locked <= 9'h1FF;
  else         
    key_samp1_locked <= key_samp1;
//--------------------------------------

//++++++++++++++++++++++++++++++++++++++
wire [9:1] key_changed1;

// 当 key_samp1 由 1 变为 0 时
// key_changed1 由 0 变为 1,只维持一个时钟周期
assign key_changed1 = key_samp1_locked & (~key_samp1); 
//--------------------------------------


//++++++++++++++++++++++++++++++++++++++
reg [19:0] cnt;

// 一旦有按键按下,cnt 立即被清零
always @ (posedge i_clk, negedge i_rst_n)
  if(!i_rst_n)
    cnt <= 20'h0;
  else if(key_changed1)
    cnt <= 20'h0;
  else
    cnt <= cnt + 1'b1;
//--------------------------------------


//++++++++++++++++++++++++++++++++++++++
reg [9:1] key_samp2, key_samp2_locked;

// 只有当按键不变化(不抖动),且维持 20ms 以上时
// 才将 i_key 采集至 key_samp2
always @ (posedge i_clk, negedge i_rst_n)
  if(!i_rst_n)
    key_samp2 <= 9'h1FF;
  else if(cnt == 20'hF_FFFF)            // 0xFFFFF/50M = 20.9715ms
    key_samp2 <= i_key;

// 将 key_samp2 锁存至 key_samp2_locked
always @ (posedge i_clk, negedge i_rst_n)
  if(!i_rst_n)
    key_samp2_locked <= 9'h1FF;
  else
    key_samp2_locked <= key_samp2;
//--------------------------------------

//++++++++++++++++++++++++++++++++++++++
wire [9:1] key_changed2;

// 当 key_samp2 由 1 变为 0 时
// key_changed2 由 0 变为 1,只维持一个时钟周期
assign key_changed2 = key_samp2_locked & (~key_samp2); 
//--------------------------------------


//++++++++++++++++++++++++++++++++++++++
// 每次按键稳定后,输出键值
// 按下为 0,松开为 1
always @ (posedge i_clk, negedge i_rst_n)
  if(!i_rst_n)
    o_key_val <= 9'h1FF;
  else if(key_changed2)
    o_key_val <= key_samp2;
//--------------------------------------

endmodule

代码说明

  • i_clk:时钟信号
  • i_rst_n:复位信号,低电平有效
  • i_key:按键信号,按下为 0,松开为 1
  • o_key_val:去抖动后的键值,按下为 0,松开为 1
  • key_samp1, key_samp1_locked:用于采样和锁存按键信号的寄存器
  • key_samp2, key_samp2_locked:用于存储去抖动后的按键信号的寄存器
  • key_changed1, key_changed2:用于检测按键状态变化的信号
  • cnt:用于延时计数的寄存器,计数周期为 20.9715ms

注意事项

  • 该模块的时钟频率为 50MHz,如果实际应用中使用的时钟频率不同,需要修改计数器的最大值,以便保证去抖动时间为 20ms。
  • 实际应用中,可能需要根据按键的具体特性调整去抖动时间,例如调整计数器的最大值或使用不同的去抖动算法。

总结

该模块提供了一个简单的 Verilog 键值去抖动方案,通过对按键信号进行采样、计数和判断,可以有效地滤除按键抖动,确保按键信号的稳定性。

Verilog 键值去抖动模块实现

原文地址: https://www.cveoy.top/t/topic/olwD 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录