一、简述游戏功能
流程1:游戏开始时,即在复位状态下,马里奥向左走;
流程2:在向左走的过程中,可能会发生碰撞,若发生碰撞转为向右走;
流程3:向右走过程中,也可能会发生碰撞,若发生碰撞转为向左走;
流程4:向左走过程中,可能遇到地面空洞,掉下去的话,马里奥被惊吓,大喊“啊!!!”,若在20个时钟周期内,马里奥继续下降。若超过20个时钟周期,马里奥进入生死判决时刻,若地面恢复,马里奥将回不到地面,处于死亡状态,game over,否则,地面恢复,马里奥可以继续向左走。
流程5:同理,向右走过程中,可能遇到地面空洞,掉下去的话,马里奥被惊吓,大喊“啊!!!”,若在20个时钟周期内,马里奥将继续下降。若超过20个时钟周期,马里奥进入生死判决时刻,若地面恢复,马里奥将回不到地面,处于死亡状态,game over,否则,地面恢复,马里奥可以继续向右走。
流程6:此外,马里奥还有挖洞的技能:若向左走的途中挖洞,可能会挖到空洞,马里奥再次被惊吓,大喊“啊!!!”,同时与流程3内容一致。若向右走的途中挖洞,可能会挖到空洞,马里奥再次被惊吓,大喊“啊!!!”,同时与流程4内容一致。
二、状态解读
根据游戏功能,可解读为八个状态,分别为:
Left:向左走
Right:向右走
Dig_left:向左挖洞
Dig_right:向右挖洞
Fall_left:向左走的过程中掉到洞中
Fall_right:向右走的过程中掉到洞中
SP:生死判决时刻
Dead:死亡状态
三、程序源码
module top_module(
input clk,
input areset, // 复位信号,初始状态为向左走
input bump_left, //向左走发生碰撞
input bump_right,//向右走发生碰撞
input ground, //地面 0:空洞
input dig, //是否挖洞
output walk_left,//向左走
output walk_right,//向右走
output aaah, //大喊“啊!!!”
output digging ); //正在挖洞
//先来定义8个状态
parameter
Left = 8'b0000_0001,
Right = 8'b0000_0010,
Dig_left = 8'b0000_0100,
Dig_right = 8'b0000_1000,
Fall_left = 8'b0001_0000,
Fall_right = 8'b0010_0000,
SP = 8'b0100_0000,
Dead = 8'b1000_0000;//掉到坑里,时间长,且地面被封上,死了
//定义用于存储状态的寄存器变量
reg [7:0] state,next_state;
reg [4:0] count;
//先来定义一个计数器,用于计算掉到坑里的时间
initial
count = 5'b1;//因为要计算20个周期,所以计数器的位宽定义5位够用了
always@(posedge clk or posedge areset)//产生要计数的计数器
begin
if(areset)
count <= 5'b1;
else if((next_state == Fall_left)||(next_state == Fall_right))
count <= count + 1'b1;
else
count <= 5'b1;
end
//第一个块用于描述状态的初始状态,可以使得将下一状态跳转到当前状态
always@(posedge clk or posedge areset)
begin
if(areset)
state <= Left;
else
state <= next_state;
end
//第二个块用来描述状态之间的转移
always@(*)
begin
case(state)
Left:begin
if(ground == 1'b0)
next_state = Fall_left;
else if(dig == 1'b1)
next_state = Dig_left;
else if(bump_left)
next_state = Right;
else
next_state = Left;
end
Right:begin
if(ground == 1'b0)
next_state = Fall_right;
else if(dig == 1'b1)
next_state = Dig_right;
else if(bump_right == 1'b1)
next_state = Left;
else
next_state = Right;
end
Dig_left:begin
if(ground == 1'b0)
next_state = Fall_left;
else
next_state = Dig_left;
end
Dig_right:begin
if(ground == 1'b0)
next_state = Fall_right;
else
next_state = Dig_right;
end
Fall_left:begin
if((ground == 1'b0)&&(count <= 5'd20))
next_state = Fall_left;
else if((ground == 1'b0)&&(count > 5'd20))//进入下一个撞击判断状态,如果地面恢复了,则将撞死
next_state = SP;
else
next_state = Left;
end
Fall_right:begin
if((ground == 1'b0)&&(count <= 5'd20))
next_state = Fall_right;
else if((ground == 1'b0)&&(count > 5'd20))//进入下一个撞击判断状态,如果地面恢复了,则将撞死
next_state = SP;
else
next_state = Right;
end
SP:begin //终极判决状态
if(ground == 1'b1)
next_state = Dead;
else
next_state = SP;
end
Dead:begin
next_state = Dead;
end
default:state = 8'bxxxxxxxx;
endcase
end
//输出情况
assign walk_left = (state == Left);
assign walk_right = (state == Right);
assign aaah = ((state == Fall_left)||(state == Fall_right)||(state == SP));
assign digging = ((state == Dig_left)||(state == Dig_right));
endmodule