所以我对Verilog很陌生,我正在尝试编写一个简单的FSM。
输入a
是一个按钮,按启动机器。但是,在最初按a
之后,每个其他下一个状态都会导致返回到开始/初始状态。
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
之间交替显示。
我该如何解决这个问题?
答案 0 :(得分:0)
一个简单的解决方案是跟踪边缘&#34;按钮,而不是当前状态。例如:
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
,则系统会要求用户在a
再次触发之前至少释放一个aPressed
。
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)
,这是一种很好的做法)