Lemmings_HDLbits(旅鼠游戏——基于Verilog描述的有限状态机简单小游戏)

        旅鼠游戏中的动物行为很简单 ,我们将使用有限状态机FSM对其进行建模。

1、行走

        在旅鼠的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, ...
    reg state, next_state;
	parameter right=1,left=0;
    always @(*) 
        begin
            case(state)
                left:next_state<=(bump_left)? right:state;
                right:next_state<=(bump_right)? left:state; //碰壁就掉头
            endcase
        // State transition logic
        end

    always @(posedge clk, posedge areset) 
        begin
        // State flip-flops with asynchronous reset
            if(areset) state<=left;
            else state<=next_state;
    	end
    assign walk_left = (state==left)? 1:0;
    assign walk_right = (state==right)? 1:0;
    // Output logic
 
endmodule

2、坠落

        除了左右行走,如果地面在他们下面消失,旅鼠还会摔倒(想必还会“啊!”)。

        除了在撞倒时改变方向和行走,当ground=0时,旅鼠还会摔倒并说“啊!”。当地面再次出现(ground=1)时,旅鼠将继续沿着坠落前的方向行走。坠落时被撞击不会影响行走方向,在地面消失(但尚未坠落)的同一周期内被撞击,或在仍下落时地面重新出现,也不会影响行走方向。

         四种状态如下(和我理解的不一样,我以为fall_是指在下落后向左走,所以fall_left也可以发生碰撞改变方向,后来写完发现不匹配看了提示才发现,fall_是指一直往下落,没有水平方向的动作了,只有保持下落或者ground=1)

        状态的理解以及变换非常重要!(理解之后代码就很好写了,如下的二段式)

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 ); 
    reg [1:0] state,next_state;
    parameter left=0,right=1,fall_left=2,fall_right=3;
    //定义四种状态
    always @(*)
        begin
            case(state)
                left:next_state<=(~ground)?fall_left:(bump_left)?right:left;
                right:next_state<=(~ground)?fall_right:(bump_right)?left:right;
                fall_left:next_state<=(ground)?left:fall_left;
                fall_right:next_state<=(ground)?right:fall_right;
            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==fall_left|state==fall_right); 
    
endmodule

3、挖掘!

        除了行走和坠落,旅鼠有时还可以被告知做一些有用的事情,比如挖土(当dig=1时开始挖土)。如果旅鼠目前正在地面上行走(ground=1且没有坠落),它可以继续挖掘,直到到达另一侧(ground=0)。到那时,因为没有地面,它会掉下来(aaah!),然后,一旦它再次落地,继续沿着原来的方向行走。和坠落一样,在挖掘时被撞击没有任何影响,当坠落或没有地面时被告知要挖掘则被忽略。

        (换句话说,行走的旅鼠可以坠落、挖掘或切换方向。如果满足其中一个以上的条件,坠落的优先级高于挖掘,而挖掘的优先级高于切换方向)

         增加了dig_left和dig_right两种状态。

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 ); 
    reg [2:0] state,next_state;
    parameter left=0,right=1,fall_left=2,fall_right=3,dig_left=4,dig_right=5;
    
    always @(*)
        begin
            case(state) //描述状态变化
                left:next_state<=(~ground)? fall_left:(dig)? dig_left:(bump_left)? right:left;
                right:next_state<=(~ground)? fall_right:(dig)? dig_right:(bump_right)? left:right;
                fall_left:next_state<=(ground)? left:fall_left;
                fall_right:next_state<=(ground)? right:fall_right;
                dig_left:next_state<=(~ground)? fall_left:dig_left;
                dig_right:next_state<=(~ground)? fall_right:dig_right;
            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==fall_left|state==fall_right);
    assign digging = (state==dig_left|state==dig_right);
    
endmodule

4、挖掘!

        虽然旅鼠可以行走、跌倒和挖掘,但旅鼠并非无懈可击。如果一只旅鼠坠落太久,然后撞到地面,它可能会飞溅(寄了)。如果一只旅鼠坠落超过20个时钟周期,然后撞到地面,它将飞溅并停止行走、坠落或挖掘(所有4个输出都变为0),直到永远(或直到FSM复位)。对于一只旅鼠在落地前能落多远没有上限。旅鼠只有在触地时才会飞溅,它们不会在半空中飞溅。(飞溅这个描述好残忍)

     (坠落20个周期是可以存活的)

        状态变换图: 

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 ); 
    
    reg [2:0] state,next_state;
    parameter left=0,right=1,fall_left=2,fall_right=3,dig_left=4,dig_right=5,go_die=6;
    reg [4:0] time_fall_left,time_fall_right; 
    //定义坠落时间
    always @(*)
        begin
            case(state) //描述状态变化
                left:next_state<=(~ground)? fall_left:(dig)? dig_left:(bump_left)? right:left;
                right:next_state<=(~ground)? fall_right:(dig)? dig_right:(bump_right)? left:right;
                fall_left:next_state<=(time_fall_left>5'd19&&ground)? go_die:(ground)? left:fall_left;
                //易错,一开始这里的时间判断写成了>20,但实际是从0开始,到time=19时已经有20个周期了。
                fall_right:next_state<=(time_fall_right>5'd19&&ground)? go_die:(ground)? right:fall_right;
                dig_left:next_state<=(~ground)? fall_left:dig_left;
                dig_right:next_state<=(~ground)? fall_right:dig_right;
                go_die: next_state<=go_die; 
                //一旦寄了就保持不变了
            endcase
        end
    
    always @(posedge clk,posedge areset)
        begin
            if(areset) begin state<=left;time_fall_left<=0;time_fall_right<=0;end //时间也需要置零
            else 
                begin 
                    state<=next_state;
                    if(state==fall_left&&next_state==fall_left) time_fall_left<=time_fall_left+1;
                    else if(state==fall_left&&next_state==left) time_fall_left<=0; 
                    //考虑在20个周期内ground=1,则time_fall归零
                    if(state==fall_right&&next_state==fall_right) time_fall_right<=time_fall_right+1;
                    else if(state==fall_right&&next_state==right) time_fall_right<=0;
                end
        end 
    //先判断是否时go_die状态
    assign walk_left =(state==go_die)? 0:(state==left);
    assign walk_right =(state==go_die)? 0:(state==right);
    assign aaah =(state==go_die)? 0:(state==fall_left|state==fall_right);
    assign digging =(state==go_die)? 0:(state==dig_left|state==dig_right);
 

endmodule

结束啦!

  • 4
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值