HDLBits/Sequential Logic/Finite State Machines/Lemmings3
In addition to walking and falling, Lemmings can sometimes be told to do useful things, like dig (it starts digging when dig=1). A Lemming can dig if it is currently walking on ground (ground=1 and not falling), and will continue digging until it reaches the other side (ground=0). At that point, since there is no ground, it will fall (aaah!), then continue walking in its original direction once it hits ground again. As with falling, being bumped while digging has no effect, and being told to dig when falling or when there is no ground is ignored.
(In other words, a walking Lemming can fall, dig, or switch directions. If more than one of these conditions are satisfied, fall has higher precedence than dig, which has higher precedence than switching directions.)
Extend your finite state machine to model this behaviour.
主要在於狀態的增加我沒有理清楚。題目中作者說如果旅鼠在地面上(ground = 1)並且挖掘信號為1,則它可以開始挖洞,一直挖,直到把地都挖穿了(ground = 0),此時,旅鼠就掉下去了,並且发出大叫。
增加了挖寶功能,當地面是平整時,可以進行挖寶,直到將地面挖空。
Game Lemmings3:有個小人左右走,它只有兩種狀態:向左走和向右走;左邊碰到東西之後它就向右走,右邊碰到東西之後它就向左走,兩邊都碰到東西就跟當前方向的反方向走;覆位時小人向左走;
添加ground信號,ground=1時規則與上述規則相同;ground=0時,記錄當前走的方向,並將aaah信號置1,直到ground=1時,走與掉落之前相同的方向。
添加dig信號,ground=1時一直挖,ground=0時,進入aaah狀態,直到ground再次為1,方向與dig開始的方向相同。
優先級:fall>dig>switch direction
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 );
parameter LEFT = 4'd0, RIGHT = 4'd1, GROUND_LEFT = 4'd2, GROUND_RIGHT = 4'd3;
parameter DIGGING_LEFT = 4'd4, DIGGING_RIGHT = 4'd5;
reg [3:0] current_state;
reg [3:0] next_state;
always@(posedge clk or posedge areset)begin
if(areset)begin
current_state <= LEFT;
end
else begin
current_state <= next_state;
end
end
always@(*)begin
case(current_state)
LEFT:begin
next_state = ground ? (dig ? DIGGING_LEFT : (bump_left ? RIGHT : LEFT)) : GROUND_LEFT;
end
RIGHT:begin
next_state = ground ? (dig ? DIGGING_RIGHT : (bump_right ? LEFT : RIGHT)) : GROUND_RIGHT;
end
GROUND_LEFT:begin
next_state = ground ? LEFT : GROUND_LEFT;
end
GROUND_RIGHT:begin
next_state = ground ? RIGHT : GROUND_RIGHT;
end
DIGGING_LEFT:begin
next_state = ground ? DIGGING_LEFT : GROUND_LEFT;
end
DIGGING_RIGHT:begin
next_state = ground ? DIGGING_RIGHT : GROUND_RIGHT;
end
default:begin
next_state = LEFT;
end
endcase
end
assign walk_left = (current_state == LEFT);
assign walk_right = (current_state == RIGHT);
assign digging = (current_state == DIGGING_LEFT || current_state == DIGGING_RIGHT);
assign aaah = (current_state == GROUND_LEFT || current_state == GROUND_RIGHT);
endmodule
//-------------------------------------------------
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 );
parameter LEFT = 4'd0, RIGHT = 4'd1, GROUND_LEFT = 4'd2, GROUND_RIGHT = 4'd3;
parameter DIGGING_LEFT = 4'd4, DIGGING_RIGHT = 4'd5;
wire [1:0] bump;
assign bump = {bump_left,bump_right};
reg [3:0] current_state;
reg [3:0] next_state;
always@(posedge clk or posedge areset)begin
if(areset)begin
current_state <= LEFT;
end
else begin
current_state <= next_state;
end
end
always@(*)begin
case(current_state)
LEFT:begin
if(ground == 1'b0)begin
next_state <= GROUND_LEFT;
end
else if(dig == 1'b1)begin
next_state <= DIGGING_LEFT;
end
else if((bump == 2'b10) || (bump == 2'b11))begin
next_state <= RIGHT;
end
else begin
next_state <= LEFT;
end
//next_state = ground ? (dig ? DIGGING_LEFT : (bump_left ? RIGHT : LEFT)) : GROUND_LEFT;
end
RIGHT:begin
if(ground == 1'b0)begin
next_state <= GROUND_RIGHT;
end
else if(dig == 1'b1)begin
next_state <= DIGGING_RIGHT;
end
else if((bump == 2'b01) || (bump == 2'b11))begin
next_state <= LEFT;
end
else begin
next_state <= RIGHT;
end
//next_state = ground ? (dig ? DIGGING_RIGHT : (bump_right ? LEFT : RIGHT)) : GROUND_RIGHT;
end
GROUND_LEFT:begin
next_state = ground ? LEFT : GROUND_LEFT;
end
GROUND_RIGHT:begin
next_state = ground ? RIGHT : GROUND_RIGHT;
end
DIGGING_LEFT:begin
next_state = ground ? DIGGING_LEFT : GROUND_LEFT;
end
DIGGING_RIGHT:begin
next_state = ground ? DIGGING_RIGHT : GROUND_RIGHT;
end
default:begin
next_state = LEFT;
end
endcase
end
assign walk_left = (current_state == LEFT);
assign walk_right = (current_state == RIGHT);
assign digging = (current_state == DIGGING_LEFT || current_state == DIGGING_RIGHT);
assign aaah = (current_state == GROUND_LEFT || current_state == GROUND_RIGHT);
endmodule