[笔记].独立按键消抖的改进.[Verilog]
引子
先前的[笔记].一种独立键盘消抖的Verilog写法.[Verilog]是针对4个按键写的。今天我略为改动下,改成参数化,已验证,非常好用。
代码
key_debounce.v
module key_debounce #(parameter KEY_WIDTH = 4) ( input i_clk, input i_rst_n, input [KEY_WIDTH:1] i_key, // 按下为0,松开为1 output reg [KEY_WIDTH:1] o_key_val // 键值 ); //++++++++++++++++++++++++++++++++++++++ reg [KEY_WIDTH:1] key_samp1, key_samp1_locked; // 将i_key采集至key_samp1 always @ (posedge i_clk, negedge i_rst_n) if(!i_rst_n) key_samp1 <= {KEY_WIDTH{1'b1}}; 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 <= {KEY_WIDTH{1'b1}}; else key_samp1_locked <= key_samp1; //-------------------------------------- //++++++++++++++++++++++++++++++++++++++ wire [KEY_WIDTH: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 [KEY_WIDTH: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 <= {KEY_WIDTH{1'b1}}; 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 <= {KEY_WIDTH{1'b1}}; else key_samp2_locked <= key_samp2; //-------------------------------------- //++++++++++++++++++++++++++++++++++++++ wire [KEY_WIDTH: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 <= {KEY_WIDTH{1'b1}}; else o_key_val <= ~key_changed2; //-------------------------------------- endmodule
解析
关键是如何正确使用全局参数。第2行,在module名和moudule的I/O中间声明一些参量;同声明moudule的I/O一样,声明多个参量,使用逗号隔开;注意小括号末尾无需分号。第16行及以下类似行,先前是key_samp1 <= 4'hF,现在怎么写呢?复制KEY_WIDTH个1'b1即可:key_samp1_locked <= {KEY_WIDTH{1'b1}}。
参考
1 Quartus II->Edit->Insert Template..