来自 HDLBits 的 FSM 问题的输出与预期不同
FSM question from HDLBits has different output than expected
问题:-
考虑用于控制某种类型电机的有限状态机。 FSM 具有来自电机的输入 x 和 y,并产生控制电机的输出 f 和 g。还有一个称为 clk 的时钟输入和一个称为 resetn 的复位输入。
FSM 必须按如下方式工作。只要复位输入有效,FSM 就会保持初始状态,称为状态 A。当复位信号无效时,在下一个时钟边沿之后,FSM 必须将输出 f 设置为 1,持续一个时钟周期.然后,FSM 必须监控 x 输入。当 x 在三个连续的时钟周期中产生值 1、0、1 时,则应在下一个时钟周期将 g 设置为 1。在保持 g = 1 的同时,FSM 必须监控 y 输入。如果 y 在最多两个时钟周期内具有值 1,则 FSM 应永久保持 g = 1(即,直到重置)。但是如果y在两个时钟周期内没有变为1,那么FSM应该永久设置g = 0(直到重置)。
(原题只要求状态图,这里实现FSM)
我的代码:
module top_module (
input clk,
input resetn, // active-low synchronous reset
input x,
input y,
output f,
output g
);
parameter a=0,b=1,c=2,d=3,e=4,f1=5,g1=6,h=7,i=8,per=9;
reg [3:0] state,ns;
always@(posedge clk) begin
if(~resetn)
ns<=a;
case(state)
a:ns<=resetn ? b : a;
b:ns<=c;
c:ns<=x ? d : c;
d:ns<=x ? d : e;
e:ns<=x ? f1 : d;
f1:ns<=y ? per : g1;
g1:ns<=y ? per : i;
per:ns<=resetn ? per : a;
i:ns<=resetn ? i : a;
endcase
end
assign state=ns;
assign f=(state==b);
assign g=(state==f1|state==g1|state==per);
endmodule
您的重置逻辑有问题。您应该将重置子句与其余逻辑分开;它应该只包含在 if
子句中,而不应该包含在 case
语句中。
此外,case
语句应该在 else
子句中:
module top_module (
input clk,
input resetn, // active-low synchronous reset
input x,
input y,
output f,
output g
);
parameter a=0,b=1,c=2,d=3,e=4,f1=5,g1=6,h=7,i=8,per=9;
reg [3:0] state;
always@(posedge clk) begin
if (~resetn) begin
state<=a;
end else begin
case(state)
a:state<=b;
b:state<=c;
c:state<=x ? d : c;
d:state<=x ? d : e;
e:state<=x ? f1 : d;
f1:state<=y ? per : g1;
g1:state<=y ? per : i;
endcase
end
end
assign f=(state==b);
assign g=(state==f1|state==g1|state==per);
endmodule
不需要有2个状态变量。我更改了 FSM,使其只保留 state
.
问题:- 考虑用于控制某种类型电机的有限状态机。 FSM 具有来自电机的输入 x 和 y,并产生控制电机的输出 f 和 g。还有一个称为 clk 的时钟输入和一个称为 resetn 的复位输入。
FSM 必须按如下方式工作。只要复位输入有效,FSM 就会保持初始状态,称为状态 A。当复位信号无效时,在下一个时钟边沿之后,FSM 必须将输出 f 设置为 1,持续一个时钟周期.然后,FSM 必须监控 x 输入。当 x 在三个连续的时钟周期中产生值 1、0、1 时,则应在下一个时钟周期将 g 设置为 1。在保持 g = 1 的同时,FSM 必须监控 y 输入。如果 y 在最多两个时钟周期内具有值 1,则 FSM 应永久保持 g = 1(即,直到重置)。但是如果y在两个时钟周期内没有变为1,那么FSM应该永久设置g = 0(直到重置)。
(原题只要求状态图,这里实现FSM)
我的代码:
module top_module (
input clk,
input resetn, // active-low synchronous reset
input x,
input y,
output f,
output g
);
parameter a=0,b=1,c=2,d=3,e=4,f1=5,g1=6,h=7,i=8,per=9;
reg [3:0] state,ns;
always@(posedge clk) begin
if(~resetn)
ns<=a;
case(state)
a:ns<=resetn ? b : a;
b:ns<=c;
c:ns<=x ? d : c;
d:ns<=x ? d : e;
e:ns<=x ? f1 : d;
f1:ns<=y ? per : g1;
g1:ns<=y ? per : i;
per:ns<=resetn ? per : a;
i:ns<=resetn ? i : a;
endcase
end
assign state=ns;
assign f=(state==b);
assign g=(state==f1|state==g1|state==per);
endmodule
您的重置逻辑有问题。您应该将重置子句与其余逻辑分开;它应该只包含在 if
子句中,而不应该包含在 case
语句中。
此外,case
语句应该在 else
子句中:
module top_module (
input clk,
input resetn, // active-low synchronous reset
input x,
input y,
output f,
output g
);
parameter a=0,b=1,c=2,d=3,e=4,f1=5,g1=6,h=7,i=8,per=9;
reg [3:0] state;
always@(posedge clk) begin
if (~resetn) begin
state<=a;
end else begin
case(state)
a:state<=b;
b:state<=c;
c:state<=x ? d : c;
d:state<=x ? d : e;
e:state<=x ? f1 : d;
f1:state<=y ? per : g1;
g1:state<=y ? per : i;
endcase
end
end
assign f=(state==b);
assign g=(state==f1|state==g1|state==per);
endmodule
不需要有2个状态变量。我更改了 FSM,使其只保留 state
.