参考链接:HDLBits导学
Problem 127 Lemmings1
问题:游戏旅鼠涉及到有非常简单的大脑的生物,我们将会使用有限状态机(FSM)对其建模。
在旅鼠的2D世界中,旅鼠只有两种状态:向左走和向右走。当它遇到一个障碍物的时候,会转变方向。特别是,如果旅鼠被左侧撞到,它将会向右走,被右侧撞到,将会向左走。如果被两侧撞到,它依然会转换方向。
用两状态,两输入,一输出的摩尔型状态机对其行为建模
解决:
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, ...
parameter LEFT=0, RIGHT=1;
reg state, next_state;
always @(*) begin
// State transition logic
case({bump_left,bump_right})
2'b00: next_state = state;
2'b01: next_state = LEFT;
2'b10: next_state = RIGHT;
2'b11: next_state = (state==LEFT) ? RIGHT : LEFT;
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 == ...);
// assign walk_right = (state == ...);
assign walk_left = (state == LEFT);
assign walk_right = (state == RIGHT);
endmodule
Problem 128 Lemmings2
问题:除了向左和向右,旅鼠在它们脚下地面消失的时候还会掉落(发出“aaah!”)。地面重新出现的时候,旅鼠将会沿着掉落之前的方向继续行走。当旅鼠在地面消失的时候被碰撞(还没有掉落),不会影响步行方向,或者当地面重新出现但旅鼠仍在掉落过程中时,也不会影响步行方向。
用有限状态机(FSM)对此次行为建模。
解决:
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=0,Right=1,FallL=2,FallR=3;
reg [1:0] state,next_state;
always @(*) begin
case(state)
Left: next_state = ground ? (bump_left ? Right : Left) : FallL;
Right: next_state = ground ? (bump_right ? Left : Right) : FallR;
FallL: next_state = ground ? Left : FallL;
FallR: next_state = ground ? Right : FallR;
endcase
end
always @(posedge clk, posedge areset) begin
if(areset)
state <= Left;
else
state <= next_state;
end
assign walk_left = (state == Left);
assign walk_right = (state == Right);
assign aaah = (state == FallL || state == FallR);
endmodule
Problem 129 Lemmings3
问题:除了走路和掉落外,旅鼠有时候还能做些有用的事情,比如挖洞(当dig=1时,开始挖洞)
旅鼠在地面的时候(ground=1)它能挖洞,直到到达地面的另一边(ground=0)。在那时,由于没有地面,旅鼠将会下落(发出“aaah”),当它再一次到达地面的时候,继续按照它原来的方向行走。和掉落一样,挖洞过程中被撞击不受影响,而且掉落或者没有地面的时候挖洞命令将会被忽视。
(换句话说,旅鼠能下落、挖洞、或者转变方向。如果多个条件同时满足,优先级是:下落>挖洞>转换方向),扩展你的有限状态机模型来建模其行为
解决:
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=0,Right=1,FallL=2,FallR=3,DigL=4,DigR;
reg [1:0] state,next_state;
always @(*) begin
case(state)
//走的优先级是最低的
//判断是否存在地面 不存在就进入下落状态
//存在地面的条件下 判断是否进入挖洞状态
//最后才是判断 是向右走还是向左走
Left: next_state = ground ? (dig ? DigL :(bump_left ? Right : Left)) : FallL;
Right: next_state = ground ? (dig ? DigR :(bump_right ? Left : Right)) : FallR;
DigL: next_state = ground ? DigL : FallL;
DigR: next_state = ground ? DigR : FallR;
FallL: next_state = ground ? Left : FallL;
FallR: next_state = ground ? Right : FallR;
endcase
end
always @(posedge clk, posedge areset) begin
if(areset)
state <= Left;
else
state <= next_state;
end
assign walk_left = (state == Left);
assign walk_right = (state == Right);
assign digging = (state == DigL || state == DigR);
assign aaah = (state == FallL || state == FallR);
endmodule
Problem 130 Lemmings4
问题:尽管旅鼠能够行走,掉落,挖洞,但也并非无懈可击。如果旅鼠下落过程过长在落到地面,它会飞溅。特别地,如果旅鼠下落超过20个周期再下落到地面,它将会飞溅,停止行走,掉落和挖掘(所有的4个输出都将为0),除非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 );
//新增停止状态
parameter Left=0,Right=1,FallL=2,FallR=3,DigL=4,DigR=5,Stop=6;
reg [2:0] state,next_state;
//时钟计数器
reg [4:0] cnt;
always @(*) begin
case(state)
Left: next_state = ground ? (dig ? DigL :(bump_left ? Right : Left)) : FallL;
Right: next_state = ground ? (dig ? DigR :(bump_right ? Left : Right)) : FallR;
DigL: next_state = ground ? DigL : FallL;
DigR: next_state = ground ? DigR : FallR;
//出现地面时 先判断是否时钟计数已经大于了20个周期 大于则进入停止状态
FallL: next_state = ground ? (cnt > 20 ? Stop : Left) : FallL;
FallR: next_state = ground ? (cnt > 20 ? Stop : Right) : FallR;
//停止状态 状态保持不变 等待复位
Stop: next_state = Stop;
endcase
end
always @(posedge clk, posedge areset) begin
if(areset)
state <= Left;
else begin
state <= next_state;
//如果下一个状态是下落状态 则开始计数 否则计数器清零
if(next_state!=FallL&&next_state!=FallR)
cnt = 5'd0;
else begin
//不能让计数器无限增长下去 因为旅鼠下落的周期是不定的 超过飞溅的周期就保持计数不变 能够判定就行
if(cnt>=5'd21)
cnt <= 5'd21;
else
cnt <= cnt + 1'b1;
end
end
end
assign walk_left = (state == Left);
assign walk_right = (state == Right);
assign digging = (state == DigL || state == DigR);
assign aaah = (state == FallL || state == FallR);
endmodule
注意:旅鼠能够下落多远没有上限!!!!