try1:
module top_module (
input clk,
input resetn, // active-low synchronous reset
input x,
input y,
output f,
output g
);
parameter a=0,b=1,x1=2,x2=3,y1=4,y2=5,g1=6,g0=7;
//b为resetn无效后的状态,在b状态使f保持一个周期
//b收到1后转移到x1,x1收到0后转移到x2
//x2(1'0')收到1后g=1,同时检测第一个周期y是否为1--y1状态
//y2:第二个周期y==1?
//g1状态保持g=1
//g0:保持g=0;
reg [2:0] state,next_state;
always@(*)
begin
case(state)
a:
next_state<=!resetn?a:b;
b:
next_state<=x?x1:b;
x1:
next_state<=x?x1:x2;
x2:
next_state<=x?y1:b;
y1:
next_state<=y?g1:y2;
y2:
next_state<=y?g1:g0;
g0:
next_state<=g0;
g1:
next_state<=g1;
default:next_state<=a;
endcase
end
always@(posedge clk)
begin
if(!resetn)
state<=a;
else
state<=next_state;
end
always@(posedge clk)
begin
if(state==a&&resetn)
f<=1;
else
f<=0;
end
assign g=(state==y1||state==y2||state==g1);
endmodule
try2:
根据上一次的错误信息可知,g在'0'1的时候输出为1,也就是在状态b(置位f)的时候已经检测到x=1,所以当下一个状态为0,下下个状态为1的时候已经输出g=1,也就是已经探测到了101信号。
简而言之,之前错误原因来源于少检测了一个状态 --因为b状态既置位了f又检测了x1,实际根据题意,b状态只应该置位f,在下一个状态才应该检测x1。
module top_module (
input clk,
input resetn, // active-low synchronous reset
input x,
input y,
output f,
output g
);
parameter a=0,b=1,x1=2,x2=3,y1=4,y2=5,g1=6,g0=7,x3=8;
reg [3:0] state,next_state;
//a:beginning
//b: 置位f一个周期
//x1: 检测x1
//...
//y1,y2:检测y在两个周期有没有变为1
//g1: g置位1
//g0: g置位0
always@(*)
begin
case(state)
a:
next_state<=!resetn?a:b;
b:
next_state<=x1;
x1:
next_state<=x?x2:x1;
x2:
next_state<=x?x2:x3;
x3:
next_state<=x?y1:x1;
y1:
next_state<=y?g1:y2;
y2:
next_state<=y?g1:g0;
g0:
next_state<=g0;
g1:
next_state<=g1;
default:next_state<=a;
endcase
end
always@(posedge clk)
begin
if(!resetn)
state<=a;
else
state<=next_state;
end
assign f=state==b;
assign g=(state==y1||state==y2||state==g1);
endmodule
反思:
这是状态机专题,之前一直不清楚状态机赋值与时序的关系。本题中的x1状态表示:准备接收,还没接收到。在x1状态下接收到1说明x[1]=1,符合题意,可以准备接收x[2],若x1状态下接收到0,不符合题意,继续准备接收x[1],即下一个状态仍然是x1,以此类推...x3状态下接收1,说明已经完成接收101,到下一个状态。
采用非阻塞赋值,表示当前状态的输出将在下一周期发生,即在FSM中当前状态的输出与状态机状态的改变同时发生(都在下一周期)。