基于verilog HDL——长短按键识别

 

  老师给了我一个任务。这个是其中的一个模块——长短按键识别。就是说,我按着按键短点,可以实现功能1;按着久点,可以实现功能2。初学Verilog,有很多不懂,编写过程稍微吃力。以前用C很好写,但是用Verilog感觉就不同了。所以我第一个想法就是直接用状态机,但是新学,编起来有点乱,思维绞死。然后果断放弃,改用另个——直接计数,按键按下开始计数,再识别按键释放时的计数。想法不错,嘿嘿,然后感觉可行。可编到一半,又有点晕了。不习惯并行思维。于是在这个基础上,加了状态机。果断,行。嘿嘿。。。。终于搞掂。

  虽然已经出来了,但是感觉还是有点问题的,希望前辈能稍微指点迷津。嘿嘿。

  

 
module key(clk,reset,key_in,STOP_RUN,RST,CONFIG);

input clk;
input reset;
input key_in;
output reg RST;                 //复位信号RST ,高电平有效
output reg STOP_RUN;            //停车态或行车态
output reg CONFIG;              //CONFIG=1,表示进入设置状态


reg [2:0] CURRENT_STATE,NEXT_STATE;                    //当前状态,下一个状态                      
parameter S0=3'b000,S1=3'b001,S2=3'b010,S3=3'b011,S4=3'b100; //状态机编码



//**********************************************
always@(posedge clk or negedge reset)
	if(!reset)
		CURRENT_STATE <= S0;
	else
		CURRENT_STATE <= NEXT_STATE;
		

//**********************************************
reg[19:0] cnt;                  //分频计数器

always@(posedge clk or negedge reset)
begin
	if(!reset)
		cnt<=20'd0;                 
	else if(cnt==20'd50_000)
		cnt<=20'd0;                 //计数50_000个时钟
	else
		cnt<=cnt+20'd1; 
end 


//**********************************************
reg [9:0] count;                   //
always@(posedge clk or negedge reset)
begin
	if(!reset)
		begin
			NEXT_STATE<=S0;
			STOP_RUN <= 1'b0;          //停车态
			RST <= 1'b0;
			CONFIG <= 1'b0;
		end
	else if(cnt==20'd49_999)           //10ms扫描一次
	begin
		case(NEXT_STATE)
		S0:
		begin
			if(key_in==0)	
				NEXT_STATE<=S1;
			else
				begin
				count <= 10'd0;
				//NEXT_STATE<=S0;
				//STOP_RUN <= 1'b0;
				//RST <= 1'b0;
				end
		end
		
		S1:
		begin
			if(key_in==0)
				begin
					if(count>=10'd200)       //按键按下的时间超过2s,跳转下个状态
						NEXT_STATE<=S2;
					else                    //
						count <= count + 10'd1;
				end	
			else 
				begin
					if(count>=10'd3)   //30ms
						begin
							STOP_RUN <= ~STOP_RUN;        //行车态
							count <= 10'd0;
							NEXT_STATE<=S0;
						end
					else        //按键有按下,但时间太短,不允响应,跳转S0
						NEXT_STATE<=S0;
				end
		end
		
		S2:
		begin
			if(key_in==0)
			begin
				if(count>=10'd400)
					NEXT_STATE<=S3;//按键按下的时间超过4s,跳转下个状态
				else
					count <= count + 10'd1;
			end
			
			else 
				begin
					if(count>=10'd300)
						begin
							RST <= ~RST;
							count <= 10'd0;
							NEXT_STATE<=S0;
						end
					else //按键有按下,但时间不足3s,不允响应,跳转S0
						NEXT_STATE<=S0;
				end                         
		end
		
		S3:
		begin
			if(key_in==0)
			begin
				if(count>=10'd800)
					NEXT_STATE<=S4;      //按键按下的时间超过8s,跳转下个状态
				else
					count <= count + 10'd1;
			end
			
			else 
				begin
					if(count>=10'd500)
						begin
							CONFIG <= ~CONFIG;
							count <= 10'd0;
							NEXT_STATE<=S0;
						end
					else //按键有按下,但时间不足5s,不允响应,跳转S0
						NEXT_STATE<=S0;
				end                         
		end
		
		S4:
		begin
			if(key_in==0)        //按键一直没有释放,一直处于S4
				NEXT_STATE <= S4;
			else                 //按键释放,跳转S0
				NEXT_STATE <= S0;
		end
        /**/
		default:
			NEXT_STATE <= S0;
			
		endcase
	end
	
	else
		;
end


endmodule

原文地址:https://www.cnblogs.com/xuanxiaochen/p/2327305.html