题目:
Although Lemmings can walk, fall, and dig, Lemmings aren't invulnerable. If a Lemming falls for too long then hits the ground, it can splatter. In particular, if a Lemming falls for more than 20 clock cycles then hits the ground, it will splatter and cease walking, falling, or digging (all 4 outputs become 0), forever (Or until the FSM gets reset). There is no upper limit on how far a Lemming can fall before hitting the ground. Lemmings only splatter when hitting the ground; they do not splatter in mid-air.
Extend your finite state machine to model this behaviour.
Falling for 20 cycles is survivable:
Falling for 21 cycles causes splatter:
AI翻译如下:
虽然旅鼠可以走路、跌倒和挖掘,但旅鼠并不是刀枪不入的。如果旅鼠跌倒时间过长然后撞到地上,它可能会飞溅。特别是,如果旅鼠跌倒超过 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 );
//独热码定义状态空间
parameter LEFT = 3'b001;
parameter RIGHT = 3'b010;
parameter FALL_L = 3'b011;
parameter FALL_R = 3'b100;
parameter DIG_L = 3'b101;
parameter DIG_R = 3'b110;
parameter SPLAT = 3'b111;
//设置当前状态、下一状态、计数器
reg [2:0] state;
reg [2:0] next_state;
reg [15:0] cnt;
//状态转换
always @(*) begin
case (state)
LEFT :next_state = (dig&ground)?DIG_L:(ground ? (bump_left?RIGHT:LEFT) : FALL_L);
RIGHT :next_state = (dig&ground)?DIG_R:(ground ? (bump_right?LEFT:RIGHT) : FALL_R);
FALL_L:next_state = (cnt>16'd19)?(ground?SPLAT:FALL_L):(ground?LEFT:FALL_L);
FALL_R:next_state = (cnt>16'd19)?(ground?SPLAT:FALL_R):(ground?RIGHT:FALL_R);
DIG_L :next_state = ground ? DIG_L:FALL_L;
DIG_R :next_state = ground ? DIG_R:FALL_R;
SPLAT :next_state=SPLAT;
endcase
end
//状态跳转
always @(posedge clk or posedge areset) begin
if(areset)
state<=LEFT;
else
state<=next_state;
end
//设置计数器
always @(posedge clk or posedge areset) begin
if(areset)
cnt<=16'd0;
else begin
if((state==FALL_L)|(state==FALL_R))
cnt<=cnt+16'd1;
else
cnt<=16'd0;
end
end
//设置输出
assign aaah=((state==FALL_L)|(state==FALL_R))&~(state==SPLAT);
assign walk_left =(state==LEFT)&~(state==SPLAT);
assign walk_right=(state==RIGHT)&~(state==SPLAT);
assign digging=((state==DIG_L)|(state==DIG_R))&~(state==SPLAT);
endmodule