老师给了我一个任务。这个是其中的一个模块——长短按键识别。就是说,我按着按键短点,可以实现功能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