题目中有明确指出优先级,在描述状态转移条件时应充分考虑优先级,先判断是否存在ground(决定了是否fall),之后是否在dig,之后是否受到bump。
在描述fall_left
、fall_right
、dig_left
和 dig_right
条件转移时,只考虑ground == 1'b0,是因为只有当ground
输入为低电平时,才会转移到这些状态。
module top_module(
input clk,
input areset, // Freshly brainwashed Lemmings walk left.
input bump_left,
input bump_right,
input ground,
input dig,
output walk_left,
output walk_right,
output aaah,
output digging );
//状态寄存器
reg [2:0] state ,next_state;
//状态空间
parameter left = 3'b000,right = 3'b001, fall_left = 3'b010, fall_right = 3'b011 ,dig_left = 3'b100,dig_right =3'b101 ;
//状态转移条件
always@(*)begin
case(state)
left:begin
if(ground ==1'b0)
next_state = fall_left;
else if(dig == 1'b1)
next_state = dig_left;
else if (bump_left)
next_state = right;
else
next_state = left;
end
right:begin
if(ground ==1'b0)
next_state = fall_right;
else if(dig == 1'b1)
next_state = dig_right;
else if (bump_right)
next_state = left;
else
next_state = right;
end
fall_left:begin
if(ground==1'b0)
next_state = fall_left;
else
next_state = left;
end
fall_right:begin
if(ground == 1'b0)
next_state = fall_right;
else
next_state = right;
end
dig_left:begin
if(ground == 1'b0)
next_state = fall_left;
else
next_state = dig_left;
end
dig_right:begin
if(ground == 1'b0)
next_state = fall_right;
else
next_state = dig_right;
end
default:next_state <= left;
endcase
end
//状态转移过程
always@(posedge clk or posedge areset)begin
if (areset)
state <= left;
else
state <= next_state;
end
//Output
assign walk_left = (state == left);
assign walk_right = (state == right);
always@(posedge clk)begin
if(ground == 1'b0)
aaah <= 1'b1;
else
aaah <= 1'b0;
end
assign digging = (state == dig_left) | (state == dig_right);
endmodule
正确结果:
错误示范:
// always @(posedge clk) begin
// if (state == dig_left | state == dig_right)
// digging <= 1'b1;
// else
// digging <= 1'b0;
// end
always @(posedge clk) begin
if (dig == 1'b1)
digging <= 1'b1;
else
digging <= 1'b0;
end
总结:
1.digging
输出与状态机的状态有关,因此最好根据状态机的状态来控制 digging
输出,而不是根据 dig
输入信号直接控制。而aaah的输出是直接与ground信号输入相关的,由于fall的优先级高于dig和bump,也不会因为状态转移发生改变,因此可以直接控制。aaah也可以通过组合逻辑assign赋值语句通过next_state的fall_left或者fall_right的状态直接得到,避免了时钟clk引起的时延变化,得到了与state状态时,通过时序逻辑判断ground输入信号得到的aaah输出结果相同。
assign aaah = (state == fall_left) | (state == fall_right);
2.digging
的值应该在状态为 dig_left
或 dig_right
时为1,其他状态下为0。