前两个题目较为简单,用二段式和三段式都可以。
Lemmings3加了个digging,优先级介于fall和walk之间,和fall的区别在于:
ground信号完全决定lemming会不会fall,而dig信号的作用是让它开始digging,停止digging需要ground为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 WL = 0, WR = 1, FL = 2, FR = 3, DL = 4, DR = 5;
reg [2:0] st, next_st;
wire [3:0] inp_w;
assign inp_w = {ground, dig, bump_left, bump_right};
always @(*) begin
casez(inp_w)
4'b0???: begin //ground为0,下个状态必fall
case(st)
WL, FL, DL: next_st = FL;
WR, FR, DR: next_st = FR;
default: next_st = st;
endcase
end
4'b11??: begin //dig信号,fall时不受影响
case(st)
WL, DL: next_st = DL;
WR, DR: next_st = DR;
FL: next_st = WL;
FR: next_st = WR;
default: next_st = st;
endcase
end
4'b1010: begin //以下case中,fall变为walk,方向不受影响;digging不变
case(st)
WL, WR: next_st = WR;
FL: next_st = WL;
FR: next_st = WR;
DL, DR: next_st = st;
default: next_st = st;
endcase
end
4'b1001: begin
case(st)
WL, WR: next_st = WL;
FL: next_st = WL;
FR: next_st = WR;
DL, DR: next_st = st;
default: next_st = st;
endcase
end
4'b1011: begin
case(st)
WL: next_st = WR;
WR: next_st = WL;
FL: next_st = WL;
FR: next_st = WR;
DL, DR: next_st = st;
default: next_st = st;
endcase
end
4'b1000: begin
case(st)
WL, WR, DL, DR: next_st = st;
FL: next_st = WL;
FR: next_st = WR;
default: next_st = st;
endcase
end
endcase
end
always @(posedge clk or posedge areset) begin
if(areset)
st <= WL;
else
st <= next_st;
end
assign walk_left = (st == WL);
assign walk_right = (st == WR);
assign aaah = (st == FL || st == FR);
assign digging = (st == DL || st == DR);
endmodule
Lemmings4相较于3加了摔s的功能,fall了超过20个clk会摔s
加一个clk上升沿always语句,用于赋值计数寄存器count_fall;状态替换的always语句加一个死亡判断,别的都不用变
三段式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 WL = 0, WR = 1, FL = 2, FR = 3, DL = 4, DR = 5, SP = 6;
reg [2:0] st, next_st;
wire [3:0] inp_w;
assign inp_w = {ground, dig, bump_left, bump_right};
reg [4:0] count_fall;
//reg dying;
always @(*) begin
casez(inp_w)
4'b0???: begin //ground为0,下个状态必fall
case(st)
WL, FL, DL: next_st = FL;
WR, FR, DR: next_st = FR;
default: next_st = st;
endcase
end
4'b11??: begin //dig信号,fall时不受影响
case(st)
WL, DL: next_st = DL;
WR, DR: next_st = DR;
FL: next_st = WL;
FR: next_st = WR;
default: next_st = st;
endcase
end
4'b1010: begin //以下case中,fall变为walk,方向不受影响;digging不变
case(st)
WL, WR: next_st = WR;
FL: next_st = WL;
FR: next_st = WR;
DL, DR: next_st = st;
default: next_st = st;
endcase
end
4'b1001: begin
case(st)
WL, WR: next_st = WL;
FL: next_st = WL;
FR: next_st = WR;
DL, DR: next_st = st;
default: next_st = st;
endcase
end
4'b1011: begin
case(st)
WL: next_st = WR;
WR: next_st = WL;
FL: next_st = WL;
FR: next_st = WR;
DL, DR: next_st = st;
default: next_st = st;
endcase
end
4'b1000: begin
case(st)
WL, WR, DL, DR: next_st = st;
FL: next_st = WL;
FR: next_st = WR;
default: next_st = st;
endcase
end
endcase
end
always @(posedge clk or posedge areset) begin
if(areset)
st <= WL;
else if(count_fall == 5'd20 && next_st != FL && next_st != FR)
st <= SP;
else
st <= next_st;
end
always @(posedge clk or posedge areset) begin
if(areset) begin
count_fall <= 'b0;
//dying <= 'b0;
end
else if(st == FL || st == FR) begin
if(count_fall != 5'd20)
count_fall <= count_fall + 5'b1;
end
else
count_fall <= 'b0;
end
assign walk_left = (st == SP) ? 1'b0 : (st == WL);
assign walk_right = (st == SP) ? 1'b0 : (st == WR);
assign aaah = (st == SP) ? 1'b0 : (st == FL || st == FR);
assign digging = (st == SP) ? 1'b0 : (st == DL || st == DR);
endmodule