目录
题目1:Lemmings1
题目2:Lemmings2
题目3:Lemmings3
题目4: Lemmings4
游戏Lemmings涉及具有相当简单大脑的小动物。如此简单,以至于我们将使用有限状态机对其进行建模。
在Lemmings的2D世界中,Lemmings可以处于以下两种状态之一:向左行走或向右行走。如果它碰到障碍物,它会改变方向。特别是,如果一只旅鼠在左边被撞到,它会向右走。如果它在右边被撞到,它将向左走。如果它同时在两侧碰撞,它仍然会改变方向。
实现具有两个状态、两个输入和一个输出的摩尔状态机,用于模拟此行为。
模块声明
module top_module( input clk, input areset, // Freshly brainwashed Lemmings walk left. input bump_left, input bump_right, output walk_left, output walk_right);
分析:输入为遇到左障碍bump_left和右障碍bump_right;输出为walk_left或walk_right;状态为letf或right。由此可得代码:
module top_module(
input clk,
input areset, // Freshly brainwashed Lemmings walk left.
input bump_left,
input bump_right,
output walk_left,
output walk_right); //
parameter left=0, right=1;
reg state, next_state;
always @(*) begin
// State transition logic,组合逻辑
case(state)
left:next_state = bump_left ? right:left;
right:next_state = bump_right ? left:right;
endcase
end
always @(posedge clk, posedge areset) begin
// State flip-flops with asynchronous reset,时序逻辑
if(areset)
state <= left;
else
state <= next_state;
end
// Output logic,输出逻辑
assign walk_left = (state == left);
assign walk_right = (state == right);
endmodule
仿真结果如下:
参见:Lemmings1。
除了左右走动之外,如果脚下的土地消失,莱明斯还会摔倒(大概还会掉下来“啊!”)。
除了左右行走以及在颠簸时改变方向外,当ground=0时,旅鼠会摔倒并说“啊啊!当地面重新出现(地面=1)时,旅鼠将恢复向与坠落前相同的方向行走。在跌倒时被撞击不会影响行走方向,在与地面相同的周期中被撞击消失(但尚未下落),或者当地面在仍然下落时重新出现时,也不会影响行走方向。
构建一个有限状态机来模拟这种行为。
模块声明
module top_module( input clk, input areset, // Freshly brainwashed Lemmings walk left. input bump_left, input bump_right, input ground, output walk_left, output walk_right, output aaah );
分析:与题目1相比增加了一个地面的状态,如果ground = 0,则会跌倒且会发出aaah
的声音,跌倒后的方向状态跟跌倒前的一致。代码编写如下:
module top_module(
input clk,
input areset, // Freshly brainwashed Lemmings walk left.
input bump_left,
input bump_right,
input ground,
output walk_left,
output walk_right,
output aaah );
parameter left = 1'b0, right = 1'b01,left1=2'b10,right1=2'b11;//left1表示从左边跌倒后保持原来的状态;right1表示从右边跌倒后保持原来的状态
reg [1:0] state,next_state;
//组合逻辑
always @(*)
begin
case(state)
left : begin
if(ground == 1'b0)
next_state = left1;
else if(bump_left)
next_state = right;
else
next_state = left;
end
right : begin
if(ground == 1'b0)
next_state = right1;
else if(bump_right)
next_state = left;
else
next_state = right;
end
left1 : begin
if(ground == 1'b0)
next_state = left1;
else
next_state = left;
end
right1 : begin
if(ground == 1'b0)
next_state = right1;
else
next_state = right;
end
endcase
end
//时序逻辑
always @(posedge clk , posedge areset)
begin
if(areset)
state <= left;
else
state <= next_state;
end
//输出逻辑
assign walk_right = (state == right);
assign walk_left = (state == left);
always @(posedge clk)
begin
aaah = !ground;
end
// assign walk_left = (state == left);
//assign walk_right = (state == right);
//assign aaah = ((state == left1)||(state == right1));
endmodule
仿真结果如下:
参见:Lemmings1 和 Lemmings2。
除了走路和跌倒之外,旅鼠有时还可以被告知做一些有用的事情,比如挖掘(当dig=1时开始挖掘)。如果旅鼠目前在地面上行走(地面=1且未掉落),则可以挖掘,并将继续挖掘,直到到达另一侧(地面=0)。在这一点上,由于没有地面,它会掉下来(啊!),然后一旦它再次落地,继续向原来的方向走。与跌倒一样,在挖掘时被撞到没有效果,并且在跌倒或没有地面时被告知要挖洞是被忽略的。
(换句话说,行走的旅鼠可以摔倒,挖掘或改变方向。如果满足这些条件中的多个条件,则 fall 的优先级高于 dig,dig 的优先级高于切换方向的优先级。
扩展有限状态机以对此行为进行建模。
模块声明
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 );
分析:与题目2相比,增加了一个挖掘的状态和挖掘的输出。如果旅鼠在有地面且没掉落状态下则挖掘且继续挖掘;直到到达地面ground = 0的时候,执行与题目2相同的内容。
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 = 0,right = 1,left1 = 2,right1 = 3,dig1 = 4,dig2 = 5;
//left1表示从左边跌倒后保持住原来的方向,right1表示从右边跌倒后保持住原来的方向
//dig1表示向左边挖掘,dig2表示从右边挖掘
//组合逻辑
always @(*)
begin
case(state)
left:begin
if(ground == 1'b0)
next_state = left1;
else if(dig)
next_state = dig1;
else if(bump_left)
next_state = right;
else
next_state = left;
end
right:begin
if(ground == 1'b0)
next_state = right1;
else if(dig)
next_state = dig2;
else if(bump_right)
next_state = left;
else
next_state = right;
end
left1:begin
if(ground == 1'b0)
next_state = left1;
else
next_state = left;
end
right1:begin
if(ground == 1'b0)
next_state = right1;
else
next_state = right;
end
dig1:begin
if(ground == 1'b0)
next_state = left1;
else
next_state = dig1;
end
dig2:begin
if(ground == 1'b0)
next_state = right1;
else
next_state = dig2;
end
endcase
end
//时序逻辑
always @(posedge clk,posedge areset)
begin
if(areset)
state <= left;
else
state <= next_state;
end
//输出逻辑
assign walk_right = (state == right);
assign walk_left = (state == left);
assign aaah = (state == left1 )|(state == right1);
assign digging = (state == dig1) | (state == dig2);
endmodule
仿真结果如下:
另请参阅:Lemmings1、Lemmings2 和 Lemmings3。
虽然旅鼠可以走路、摔倒和挖掘,但旅鼠并非无懈可击。如果旅鼠坠落太久然后撞到地面,它可能会飞溅。特别是,如果一只旅鼠坠落超过20个时钟周期,然后撞到地面,它将飞溅并停止行走,坠落或挖掘(所有4个输出变为0),永远(或直到FSM被重置)。旅鼠在落地前可以跌落多远没有上限。旅鼠只有在撞击地面时才会飞溅;它们不会在半空中飞溅。
扩展有限状态机以对此行为进行建模。
下降20个周期是可以生存的:
跌落21个周期会导致飞溅:
模块声明
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 );
提示:使用 FSM 控制跟踪旅鼠坠落时间的计数器。
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 = 0,right = 1,left1 = 2,right1 = 3,dig1 = 4,dig2 = 5,splat = 6,dead = 7;
reg [4:0] t ;
//left1表示从左边跌倒后保持住原来的方向,right1表示从右边跌倒后保持住原来的方向
//dig1表示向左边挖掘,dig2表示从右边挖掘,splat表示飞溅,dead表示死亡
//t表示计数
//计数器
initial
t <= 5'b1;//使用initial语句初始化
always @(posedge clk,posedge areset)
begin
if(areset)
t <= 5'b1;
else if((next_state == left1) | (next_state == right1))
t <= t+1'b1;
else
t <= 5'b1;
end
//组合逻辑
always @(*) begin
case(state)
left:begin
if(ground == 1'b0)
next_state = left1;
else if(dig)
next_state = dig1;
else if(bump_left)
next_state = right;
else
next_state = left;
end
right:begin
if(ground == 1'b0)
next_state = right1;
else if(dig)
next_state = dig2;
else if(bump_right)
next_state = left;
else
next_state = right;
end
left1:begin
if((ground == 1'b0 )&(t <= 5'd20))
next_state = left1;
else if((ground == 1'b0 )&( t>5'd20))
next_state = splat;
else
next_state = left;
end
right1:begin
if((ground == 1'b0 ) &(t <= 5'd20))
next_state = right1;
else if((ground == 1'b0 )& t>5'd20)
next_state = splat;
else
next_state = right;
end
dig1:begin
if(ground == 1'b0)
next_state = left1;
else
next_state = dig1;
end
dig2:begin
if(ground == 1'b0)
next_state = right1;
else
next_state = dig2;
end
splat:begin
if(ground == 1'b1)
next_state = dead;
else
next_state = splat;
end
dead:begin
next_state = dead;
end
endcase
end
//时序逻辑
always @(posedge clk ,posedge areset)
begin
if(areset)
state <= left;
else
state <= next_state;
end
//输出逻辑
assign walk_right = (state == right);
assign walk_left = (state == left);
assign aaah = ((state == left1 )|(state == right1)|(state == splat));
assign digging = (state == dig1) | (state == dig2);
endmodule
仿真结果如下: