学员作品:基于状态机的按键消抖

Posted by

我们写按键消抖Verilog代码一般是用一个计数器来获得20ms的时间区间,最后获得一个稳定的按键状态输出。要么是按键按下事件,要么是按键释放事件。我们再学习状态机的时候,可以考虑用状态机的方式来写按键消抖代码。

以下代码是学员再练习状态机书写的过程中写的基于状态机的按键消抖代码,可以作为学习研究之用。

//使用状态机实现按键消抖
//学员-陈科霖
module debounce_fsm
(
		input clk,
		input rst_n,
		input key,
		
		output reg key_flag,//按键事件 (按下or释放)
		output reg key_value

);
parameter IDLE = 2'd1;
parameter s1 = 2'd2;
parameter s2 = 2'd3;//消抖后状态
parameter SUM = 100;

reg [1:0] current_state;
reg [1:0] nex_state;
reg key_event;


reg [25:0] counter;
reg key_reg;

//三段式状态机 第一段
always @(posedge clk or negedge rst_n)begin
	if(rst_n == 1'b0)
		current_state <= IDLE;
	else
		current_state <= nex_state;
end
//第二段(控制状态迁移)
always @(*)begin
	case(current_state)
		IDLE :		
				if(key_reg != key)
					nex_state = s1;
				else
					nex_state = IDLE;
		s1	 :
				if(counter == SUM)
					nex_state = s2;
				else
					nex_state = s1;
		s2	 :  
				nex_state = IDLE;
	endcase
end

//第三段(产生key_flag和key_value)
always @(posedge clk or negedge rst_n)begin
	if(rst_n == 1'b0)begin
		key_flag <= 1'b0;
		key_value <= 1'b1;
	end
	else if(current_state == s2)begin
		key_flag <= 1'b1;
		key_value <= key_reg;
	end
	else begin
		key_flag <= 1'b0;
		key_value <= 1'b0;
	end
end

//消抖延时计数器 20ms
always @(posedge clk or negedge rst_n)begin
	if(rst_n == 1'b0)
		counter <= 1'b0;
	else if(key_reg != key && current_state == IDLE)begin
		counter <= 1'b0;
	end
	else 
	 if(counter < SUM && current_state == s1 && key_event)
		counter <= counter + 1'b1;
	else begin
		counter <= counter;
	end
end

always @(posedge clk or negedge rst_n)begin
	if(rst_n == 1'b0)
		key_reg <= 1'b1;
	else
		key_reg <= key;
end
endmodule 

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注

我们将24小时内回复。
取消