1、考虑用于控制某种类型电机的有限状态机。FSM有来自电机的输入x和y,并产生控制电机的输出f和g。还有一个称为clk的时钟输入和一个称为reset N的复位输入。
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(直到复位)。
(1)思路一
一开始的思路是:设置A、B、C、D、E、F 共6种状态,初始态为A,当接受到第一个1时变为B;B接收到0则到C;C接收到1则到D(此时需要进行比较复杂的判断);通过y的关系判断E和F。
由于有几个clk的延后,在这里加了几个参数
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,F=5;
reg [3:0] state,nstate;
reg [2:0] q;
integer z;
reg [2:0] ctr;
always @(posedge clk)
begin
if(!resetn) begin state=A;z=0;end
else
begin
z =z+1;
//z=0时,不发生状态转变,=1时才发生,从而达到了延迟一个clk的目的,并输出f;
state=(z>2)?nstate:A;
end
end
assign f=(z==1)? 1:0;
always @(posedge clk)
begin
if(!resetn) begin ctr <=0;q <=0; end
else if(state==D)
begin //加入q对clk进行判断。
if(q==1|q==2) begin ctr <= ctr+y; end
//q=0时,不计y;q=1,2时,考虑y。
else if(q==3) begin ctr<=0;q<=0;end
//q==3时归零(只考虑两个clk)
q<=q+1;
end
end
always @(*)
begin
case(state)
A:nstate =(x)?B:A;
B:nstate =(x)?B:C;
C:nstate =(x)?D:A;
D:nstate =(q<=1)? D:(ctr>=1)?E:F;
E:nstate =E;
F:nstate =F;
default:nstate =A;
endcase
end
assign g =(state==E|state==D)? 1:0;
endmodule
一直显示有错误,原因大概是在y的判断那一部分,实在写不出来,换了个思路。
(2)思路2
相比于思路一,增加了一个状态D0;简化对y的判断方法。
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,F=5,D0=6;
reg [3:0] state,nstate;
reg [2:0] q;
integer z;
reg [2:0] ctr;
always @(posedge clk)
begin
if(!resetn) begin state=A;z=0;end
else
begin
z =z+1;
state=(z>2)?nstate:A;
end
end
assign f=(z==1)? 1:0;
always @(*)
begin
case(state)
A:nstate =(x)?B:A;
B:nstate =(x)?B:C;
C:nstate =(x)?D:A;
D:nstate =(y)? E:D0;
D0:nstate =(y)? E:F;
//加了一个状态明显简单了很多,不需要再对y的判断的同时计数
E:nstate =E;
F:nstate =F;
default:nstate =A;
endcase
end
assign g =(state==E|state==D|state==D0)? 1:0;
endmodule