Verilog有限状态机(3)
前言
今天继续更新状态机小节的习题,本章主要编写Lemmings Game部分。
题库
题目描述10:
Game Lemmings1:有个小人左右走,它只有两种状态:向左走和向右走;左边碰到东西之后它就向右走,右边碰到东西之后它就向左走,两边都碰到东西就跟当前方向的反方向走;复位时小人向左走
Solution10:
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=1'b0, RIGHT=1'b1;
reg state, next_state;
wire [1:0] bump;
assign bump = {bump_left,bump_right};
always @(*) begin
case(state)
LEFT:begin
if((bump == 2'b10) || (bump == 2'b11))begin
next_state = RIGHT;
end
else begin
next_state = LEFT;
end
end
RIGHT:begin
if((bump == 2'b01) || (bump == 2'b11))begin
next_state = LEFT;
end
else begin
next_state = RIGHT;
end
end
endcase
end
always @(posedge clk, posedge areset) begin
if(areset)begin
state <= LEFT;
end
else begin
state <= next_state;
end
end
// Output logic
assign walk_left = (state == LEFT);
assign walk_right = (state == RIGHT);
endmodule
题目描述11:
Game Lemmings2:有个小人左右走,它只有两种状态:向左走和向右走;左边碰到东西之后它就向右走,右边碰到东西之后它就向左走,两边都碰到东西就跟当前方向的反方向走;复位时小人向左走;
添加ground信号,ground=1时规则与上述规则相同;ground=0时,记录当前走的方向,并将aaah信号置1,直到ground=1时,走与掉落之前相同的方向。
Solution11:
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 = 2'b0;
parameter RIGHT = 2'b1;
parameter AH_LEFT = 2'b10;
parameter AH_RIGHT = 2'b11;
reg [1:0] state,next_state;
wire [1:0] bump;
assign bump = {bump_left,bump_right};
always @(*)begin
case(state)
LEFT:begin
if(ground == 1'b0)begin
next_state = AH_LEFT;
end
else if((bump == 2'b10) || (bump == 2'b11))begin
next_state = RIGHT;
end
else begin
next_state = LEFT;
end
end
RIGHT:begin
if(ground == 1'b0)begin
next_state = AH_RIGHT;
end
else if((bump == 2'b01) || (bump == 2'b11))begin
next_state = LEFT;
end
else begin
next_state = RIGHT;
end
end
AH_LEFT:begin
if(ground == 1'b0)begin
next_state = AH_LEFT;
end
else begin
next_state = LEFT;
end
end
AH_RIGHT:begin
if(ground == 1'b0)begin
next_state = AH_RIGHT;
end
else begin
next_state = RIGHT;
end
end
endcase
end
always@(posedge clk,posedge areset)begin
if(areset)begin
state <= LEFT;
end
else begin
state <= next_state;
end
end
assign walk_left = (state == LEFT);
assign walk_right = (state == RIGHT);
assign aaah = ((state == AH_LEFT) | (state == AH_RIGHT));
endmodule
题目描述12:
Game Lemmings3:有个小人左右走,它只有两种状态:向左走和向右走;左边碰到东西之后它就向右走,右边碰到东西之后它就向左走,两边都碰到东西就跟当前方向的反方向走;复位时小人向左走;
添加ground信号,ground=1时规则与上述规则相同;ground=0时,记录当前走的方向,并将aaah信号置1,直到ground=1时,走与掉落之前相同的方向。
添加dig信号,ground=1时一直挖,ground=0时,进入aaah状态,直到ground再次为1,方向与dig开始的方向相同。
优先级:fall>dig>switch direction
手绘状态转移图:
Solution12:
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'b0;
parameter RIGHT = 3'b1;
parameter DIG_LEFT = 3'b10;
parameter DIG_RIGHT = 3'b11;
parameter FALL_LEFT = 3'b100;
parameter FALL_RIGHT = 3'b101;
reg [2:0] state,next_state;
wire [1:0] bump;
assign bump = {bump_left,bump_right};
always @(*)begin
case(state)
LEFT:begin
if(ground == 1'b0)begin
next_state = FALL_LEFT;
end
else if(dig == 1'b1)begin
next_state = DIG_LEFT;
end
else if((bump == 2'b10) || (bump == 2'b11))begin
next_state = RIGHT;
end
else begin
next_state = LEFT;
end
end
RIGHT:begin
if(ground == 1'b0)begin
next_state = FALL_RIGHT;
end
else if(dig == 1'b1)begin
next_state = DIG_RIGHT;
end
else if((bump == 2'b01) || (bump == 2'b11))begin
next_state = LEFT;
end
else begin
next_state = RIGHT;
end
end
DIG_LEFT:begin
if(ground == 1'b0)begin
next_state = FALL_LEFT;
end
else begin
next_state = DIG_LEFT;
end
end
DIG_RIGHT:begin
if(ground == 1'b0)begin
next_state = FALL_RIGHT;
end
else begin
next_state = DIG_RIGHT;
end
end
FALL_LEFT:begin
if(ground == 1'b0)begin
next_state = FALL_LEFT;
end
else begin
next_state = LEFT;
end
end
FALL_RIGHT:begin
if(ground == 1'b0)begin
next_state = FALL_RIGHT;
end
else begin
next_state = RIGHT;
end
end
endcase
end
always @(posedge clk,posedge areset)begin
if(areset)begin
state <= LEFT;
end
else begin
state <= next_state;
end
end
assign walk_left = (state == LEFT);
assign walk_right = (state == RIGHT);
assign digging = ((state == DIG_LEFT) | (state == DIG_RIGHT));
assign aaah = ((state == FALL_LEFT) | (state == FALL_RIGHT));
endmodule
题目描述13:
Game Lemmings4:小人行动规则与上述规则相同,添加小人会die的规则:
如果小人fall超过20cycles,则当其接触地面时直接die(未接触地面时不会die) dig,fall,left和right输出全部置零,直到reset信号来临。
手绘状态转移图:(Dead状态少个自己到自己的状态)
Solution13:
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'b0;
parameter RIGHT = 3'b1;
parameter DIG_LEFT = 3'b10;
parameter DIG_RIGHT = 3'b11;
parameter FALL_LEFT = 3'b100;
parameter FALL_RIGHT = 3'b101;
parameter DEAD = 3'b110;
parameter SPLATTER = 3'b111;
reg [2:0] state,next_state;
reg [4:0] Cycle_Count;
wire [1:0] bump;
assign bump = {bump_left,bump_right};
always @(*)begin
case(state)
LEFT:begin
if(ground == 1'b0)begin
next_state = FALL_LEFT;
end
else if(dig == 1'b1)begin
next_state = DIG_LEFT;
end
else if((bump == 2'b10) || (bump == 2'b11))begin
next_state = RIGHT;
end
else begin
next_state = LEFT;
end
end
RIGHT:begin
if(ground == 1'b0)begin
next_state = FALL_RIGHT;
end
else if(dig == 1'b1)begin
next_state = DIG_RIGHT;
end
else if((bump == 2'b01) || (bump == 2'b11))begin
next_state = LEFT;
end
else begin
next_state = RIGHT;
end
end
DIG_LEFT:begin
if(ground == 1'b0)begin
next_state = FALL_LEFT;
end
else begin
next_state = DIG_LEFT;
end
end
DIG_RIGHT:begin
if(ground == 1'b0)begin
next_state = FALL_RIGHT;
end
else begin
next_state = DIG_RIGHT;
end
end
FALL_LEFT:begin
if((ground == 1'b0) && (Cycle_Count < 5'd20))begin
next_state = FALL_LEFT;
end
else if((ground == 1'b0) && (Cycle_Count >= 5'd20))begin
next_state = SPLATTER;
end
else begin
next_state = LEFT;
end
end
FALL_RIGHT:begin
if((ground == 1'b0) && (Cycle_Count < 5'd20))begin
next_state = FALL_RIGHT;
end
else if((ground == 1'b0) && (Cycle_Count >= 5'd20))begin
next_state = SPLATTER;
end
else begin
next_state = RIGHT;
end
end
SPLATTER:begin
if(ground == 1'b1)begin
next_state = DEAD;
end
else begin
next_state = SPLATTER;
end
end
DEAD:begin
next_state = DEAD;
end
endcase
end
always @(posedge clk,posedge areset)begin
if(areset)begin
state <= LEFT;
end
else begin
state <= next_state;
end
end
always @(posedge clk,posedge areset)begin
if(areset)begin
Cycle_Count <= 5'd0;
end
else if((next_state == FALL_LEFT) || (next_state == FALL_RIGHT)) begin
Cycle_Count <= Cycle_Count + 1'b1;
end
else begin
Cycle_Count <= 5'd0;
end
end
assign walk_left = (state == LEFT);
assign walk_right = (state == RIGHT);
assign aaah = ((state == FALL_LEFT) || (state == FALL_RIGHT) || (state == SPLATTER));
assign digging = ((state == DIG_LEFT) || (state == DIG_RIGHT));
endmodule
结语
今天更新的几道旅鼠题非常有意思,大家可以先自己尝试。代码若有问题的话可以与我交流。