用状态机写独立按键的消抖
直接上代码
//消抖 module key_filter ( input wire clk, //E1 input wire rst_n, //KEY0 L3 input wire ikey_n, //配到了按键3 J6 output reg okey_n //配到了LED0 T12 ); parameter T_5ms = 250_000;//50M时钟,一个周期20ns,5ms就是250000个周期 //我们这里认定高电平持续5ms算是按键真的按下了 localparam KEY_OFF = 4'b0001; localparam ON_SHAKE = 4'b0010; localparam KEY_ON = 4'b0100; localparam OFF_SHAKE = 4'b1000; reg [17:0] cnt; reg [3:0] c_state; reg [3:0] n_state; reg [2:0] reg_syn; wire key_n; always@(posedge clk) reg_syn <= {reg_syn[1:0],ikey_n}; //这里寄存了3个周期 assign key_n = reg_syn[2]; //状态机:时序逻辑:描述状态转移 always@(posedge clk) begin if(rst_n == 0) c_state <= KEY_OFF; else c_state <= n_state; end //状态机:组合逻辑:描述下一个状态 判断状态转移条件,描述状态转移规律 always@(*) begin case (c_state) KEY_OFF : if(key_n) n_state = KEY_OFF; else n_state = ON_SHAKE; ON_SHAKE : if(key_n) n_state = KEY_OFF; else if(cnt < T_5ms - 1) //cnt计数达到5ms,就转移到KEY_ON状态 n_state = ON_SHAKE; //若达不到5ms,则认为还是处于抖动 else n_state = KEY_ON; KEY_ON : if(key_n == 0) n_state = KEY_ON; else n_state = OFF_SHAKE; OFF_SHAKE : if(key_n) if(cnt < T_5ms - 1) n_state = OFF_SHAKE; else n_state = KEY_OFF; else n_state = KEY_ON; endcase end //根据状态做计数器 always@(posedge clk) begin if(rst_n == 0) cnt <= 0; else case (c_state) ON_SHAKE : if(key_n) cnt <= 0; else if (cnt >=T_5ms -1) cnt <= 0; else cnt <= cnt + 1'b1; // if(key_n == 0 && cnt < T_5ms -1) // cnt <= cnt +1'b1; //else //cnt <= 0; OFF_SHAKE : if(key_n == 0) cnt <= 0; else if (cnt >=T_5ms -1) cnt <= 0; else cnt <= cnt + 1'b1; endcase end //状态机:状态输出 always@(posedge clk)begin if(rst_n ==0) okey_n <= 1; else if(c_state == KEY_ON || c_state == OFF_SHAKE ) okey_n <= 0; else okey_n <=1; end endmodule