看着之前编写的,感觉有点问题。首先状态机格式就有点不对头,改了下,再加上了单击和双击的辨别。感觉这次好多了。

  不过还没完,还有个功能在研究中。。。看看怎么和NIOS II连接起来,做成一个完整的项目。

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

input clk;
input reset;
input key_in;
output reg RST; //复位信号RST ,高电平有效
output reg UPDOWN; //车行方向指示,为0是去行,为1时是回行
output reg STOP_RUN; //停车态或行车态, 0停车态 1行车态
output reg CONFIG; //CONFIG=1,表示进入设置状态



reg [2:0] STATE; //状态

parameter S0=3'b000,
S1=3'b001,
S2=3'b010,
S3=3'b011,
S4=3'b100,
S5=3'b101,
S6=3'b110,
S7=3'b111; //状态机编码


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

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


//**********************************************
reg [9:0] count_d;
reg [9:0] count; //
//**********************************************
always@(posedge clk or negedge reset)
begin
if(!reset)
begin
STATE<=S0;
STOP_RUN <= 1'b0; //停车态
UPDOWN <= 1'b0;
RST <= 1'b0;
CONFIG <= 1'b0;
count_d <= 1'b0;
count <= 1'b0;

end
else if(cnt==20'd4_999) //10ms扫描一次
begin
case(STATE)
//----
S0: //判别是否有按键按下
begin
if(key_in==0)
STATE<=S1;
else
begin
count <= 10'd0;
//STATE<=S0;
//STOP_RUN <= 1'b0;
RST <= 1'b0;
end
end
//----
S1: //判别短单击
begin
if(key_in==0)
begin
if(count>=10'd210) //按键按下的时间超过2.1s,跳转下个状态
STATE<=S2;
else //
count <= count + 10'd1;
end
else
begin
if(count>=10'd3) //30ms,防抖
begin
count <= 10'd0;
STATE<=S5;
end
else //按键有按下,但时间太短,不允响应,跳转S0
STATE<=S0;
end
end
//----
S2: //复位
begin
if(key_in==0)
begin
if(count>=10'd400)
STATE<=S3;//按键按下的时间超过4s,跳转下个状态
else
count <= count + 10'd1;
end

else
begin
if(count>=10'd220) //大于等于2.2s 产生复位信号
begin
RST <= 1;
count <= 10'd0;
STATE<=S0;
end
else //按键有按下,但时间不足3s,不允响应,跳转S0
STATE<=S0;
end
end
//----
S3: //设置指示
begin
if(key_in==0)
begin
if(count>=10'd800)
STATE<=S4; //按键按下的时间超过8s,跳转下个状态
else
count <= count + 10'd1;
end
else
begin
if(count>=10'd420) //大于等于4.2s CONFIG置位
begin
CONFIG <= ~CONFIG;
count <= 10'd0;
STATE<=S0;
end
else //按键有按下,但时间不足5s,不允响应,跳转S0
STATE<=S0;
end
end
//----
S4: //按键按下超过8s一直没放开
begin
if(key_in==0) //按键一直没有释放,一直处于S4
STATE <= S4;
else //按键释放,跳转S0
STATE <= S0;
end
//----
S5: //判别一次按键后短时间内是否有第二次按键
begin
if(key_in)
begin
if(count_d>=50)//两次按键如果大于0.5s ,则不予响应,跳转S6--STOP_RUN
begin
count_d <= 10'd0;
STATE<=S6;
end
else
count_d <= count_d + 10'd1;
end
else //两次按键如果小于0.5s,表明有双击,跳转S7
STATE<=S7;
end
//----
S6: //单击 输出STOP_RUN
begin
if(count_d==0)
begin
STOP_RUN <= ~STOP_RUN;
STATE <= S0;
end
end
//----
S7: //双击 输出UPDOWN
begin
if(key_in)
begin
if(count_d<=49 && count_d>=2)
begin
UPDOWN <= ~UPDOWN;
STATE <= S0;
count_d <= 10'd0;
end
else //两次按键如果小于20ms ,表明有抖动,重新跳回S5
STATE<=S5;
end
end
//----
default:
STATE <= S0;
//----
endcase
end

else
;
end

//******************************************************************
endmodule

 

 posted on 2012-02-24 13:53  _轩小宸  阅读(1266)  评论(0编辑  收藏  举报