Verilog按键消抖代码详解:逐行分析与功能实现

在数字电路设计中,按键消抖是一个非常常见的需求。由于机械按键存在抖动问题,直接使用按键信号会导致误判。本文将逐行分析一段Verilog按键消抖代码,帮助你理解其工作原理。

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;
  wire [9:1] key_changed1;
  reg [19:0] cnt;
  reg [9:1] key_samp2, key_samp2_locked;
  wire [9:1] key_changed2;

  // 第一级采样
  // 将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;
  
  // 检测按键状态变化
  // 当key_samp1由1变为0时,key_changed1由0变为1,只维持一个时钟周期
  assign key_changed1 = key_samp1_locked & (~key_samp1); 

  // 计数器:按键按下后开始计数
  // 一旦有按键按下,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;

  // 第二级采样:只有当按键不变化,且维持20ms以上时才采集
  // 假设时钟频率为50MHz
  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;

  // 检测按键状态变化
  // 当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
      o_key_val <= ~key_changed2;

endmodule 

代码解析

这段Verilog代码实现了一个简单的按键消抖模块,其工作原理如下:

  1. 两级采样: 代码采用了两级采样的方式来消除按键抖动。第一级采样直接采集按键信号 i_key,并将采样值存储在 key_samp1 寄存器中。第二级采样则只有在计数器 cnt 达到特定值(20ms)时才会采集按键信号,并将采样值存储在 key_samp2 寄存器中。

  2. 边沿检测: key_changed1key_changed2 用于检测按键状态的变化,即从1到0的下降沿。这两个信号只在检测到下降沿的时钟周期内为高电平,其他时间保持低电平。

  3. 计数器: 计数器 cnt 用于计时。当检测到按键按下(key_changed1 为高电平)时,计数器清零。否则,计数器每个时钟周期加1。

  4. 输出逻辑: 输出信号 o_key_val 的值取决于 key_changed2 的值。当 key_changed2 为高电平时,表示检测到稳定的按键按下,此时 o_key_val 输出低电平;否则,o_key_val 输出高电平。

总结

通过两级采样和延时计数的方式,这段Verilog代码有效地消除了按键抖动,确保了输出信号的稳定性。这种按键消抖方法简单易懂,在实际应用中被广泛使用。


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

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