FSM Verilog - 1 个按钮用于启动和停止

FSM Verilog - 1 pushbutton for both start&stop

所以我是 Verilog 的新手,我正在尝试编写一个简单的 FSM。

输入 a 是一个按钮,按下它 启动 机器。但是每隔一个下一个状态,在最初按下 a 后,会导致返回到 start/initial 状态。

input clk, reset;
input a,b,c;

reg [1:0] state;
reg [1:0] nextstate;

parameter = START=2b'0,
            STATE1=2b'1,
            STATE2=2b'11;

always @(posedge clk)
 if(reset) state <= START;
 else state<=nextstate;

always @(state, a)
 case (state)
   START: begin if(a) nextstate<=STATE1; else nextstate<=START; end
   STATE1: begin if(a) nextstate<=START; else if(b) nextstate<=STATE2; else nextstate<=STATE1; end
   STATE2: begin if(a) nextstate<=START; else if(c) nextstate<=STATE1; else nextstate<=STATE2; end
 endcase

现在将手指放在 a 上意味着我的状态在 STATE1START 之间交替 clk 的每个上升沿。 我该如何解决这个问题?

一个简单的解决方案是跟踪按钮的 "edge",而不是当前状态。例如:

reg aPressed, aPrev;
always @(posedge clk)
    aPrev<=a;

always@(*)
    if (a&&!aPrev) // a is high now, but was low last cycle
        aPressed = 1;
    else
        aPressed = 0;

在此代码中,aPressed 仅在 a 上一个周期为低电平且现在为高电平(即刚刚按下)时才有效。如果您在下一状态逻辑中将 a 替换为 aPressed,则在 aPressed 再次触发之前,用户将需要释放 a 至少一个周期。

always @(*)
    case (state)
        START: begin 
            if(aPressed) nextstate=STATE1; 
            else nextstate=START;
         end
        STATE1: begin 
            if(aPressed) nextstate=START; 
            else if(b) nextstate=STATE2;
            else nextstate=STATE1; 
        end
        STATE2: begin 
            if(aPressed) nextstate=START; 
            else if(c) nextstate=STATE1; 
            else nextstate=STATE2; 
        end
     endcase

旁注:最好使用 always@(*) 组合逻辑,而不是指定敏感度列表always@(state,a))