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
上意味着我的状态在 STATE1
和 START
之间交替 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)
)
所以我是 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
上意味着我的状态在 STATE1
和 START
之间交替 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)
)