HDLBITS笔记34:Lemmings1、Lemmings2、Lemmings3、Lemmings4

目录

题目1:Lemmings1

题目2:Lemmings2

 题目3:Lemmings3

题目4: Lemmings4


题目1:Lemmings1

游戏Lemmings涉及具有相当简单大脑的小动物。如此简单,以至于我们将使用有限状态机对其进行建模。

在Lemmings的2D世界中,Lemmings可以处于以下两种状态之一:向左行走或向右行走。如果它碰到障碍物,它会改变方向。特别是,如果一只旅鼠在左边被撞到,它会向右走。如果它在右边被撞到,它将向左走。如果它同时在两侧碰撞,它仍然会改变方向。

实现具有两个状态、两个输入和一个输出的摩尔状态机,用于模拟此行为。

模块声明

module top_module(
    input clk,
    input areset,    // Freshly brainwashed Lemmings walk left.
    input bump_left,
    input bump_right,
    output walk_left,
    output walk_right);

分析:输入为遇到左障碍bump_left和右障碍bump_right;输出为walk_left或walk_right;状态为letf或right。由此可得代码:

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;
    always @(*) begin
        // State transition logic,组合逻辑
        case(state)
            left:next_state = bump_left ? right:left;
            right:next_state = bump_right ? left:right;
        endcase
    end

    always @(posedge clk, posedge areset) begin
        // State flip-flops with asynchronous reset,时序逻辑
        if(areset)
            state <= left;
        else
            state <= next_state;
    end

    // Output logic,输出逻辑
     assign walk_left = (state == left);
     assign walk_right = (state == right);
endmodule

仿真结果如下:

题目2:Lemmings2

参见:Lemmings1

除了左右走动之外,如果脚下的土地消失,莱明斯还会摔倒(大概还会掉下来“啊!”)。

除了左右行走以及在颠簸时改变方向外,当ground=0时,旅鼠会摔倒并说“啊啊!当地面重新出现(地面=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 ); 

分析:与题目1相比增加了一个地面的状态,如果ground = 0,则会跌倒且会发出aaah

的声音,跌倒后的方向状态跟跌倒前的一致。代码编写如下:

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 = 1'b0, right = 1'b01,left1=2'b10,right1=2'b11;//left1表示从左边跌倒后保持原来的状态;right1表示从右边跌倒后保持原来的状态
    reg [1:0] state,next_state;
    //组合逻辑
    always @(*)
        begin
            case(state)
                left : begin
                    if(ground == 1'b0)
                    next_state = left1;
                    else if(bump_left)
                    next_state = right;  
                    else
                    next_state = left;   
                end
                right : begin
                    if(ground == 1'b0)
                    next_state = right1;
                    else if(bump_right)
                    next_state = left;  
                    else
                    next_state = right;  
                end
                left1 : begin
                    if(ground == 1'b0)
                    next_state = left1;
                    else
                        next_state = left;
                end
                right1 : begin
                    if(ground == 1'b0)
                    next_state = right1;
                    else
                        next_state = right;
                end
            endcase
        end
    //时序逻辑
     always @(posedge clk , posedge areset)
          begin
              if(areset)
                  state <= left;
              else
                  state <= next_state;
          end
    //输出逻辑
      assign walk_right = (state == right);
      assign walk_left = (state == left);
    always @(posedge clk)
        begin
     aaah = !ground;
       end
   // assign walk_left = (state == left);
    //assign walk_right = (state == right);
   //assign aaah = ((state == left1)||(state == right1));

endmodule

仿真结果如下:

 题目3:Lemmings3

参见:Lemmings1 和 Lemmings2

除了走路和跌倒之外,旅鼠有时还可以被告知做一些有用的事情,比如挖掘(当dig=1时开始挖掘)。如果旅鼠目前在地面上行走(地面=1且未掉落),则可以挖掘,并将继续挖掘,直到到达另一侧(地面=0)。在这一点上,由于没有地面,它会掉下来(啊!),然后一旦它再次落地,继续向原来的方向走。与跌倒一样,在挖掘时被撞到没有效果,并且在跌倒或没有地面时被告知要挖洞是被忽略的。

(换句话说,行走的旅鼠可以摔倒,挖掘或改变方向。如果满足这些条件中的多个条件,则 fall 的优先级高于 dig,dig 的优先级高于切换方向的优先级。

扩展有限状态机以对此行为进行建模。

模块声明

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 ); 

分析:与题目2相比,增加了一个挖掘的状态和挖掘的输出。如果旅鼠在有地面且没掉落状态下则挖掘且继续挖掘;直到到达地面ground = 0的时候,执行与题目2相同的内容。

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,left1 = 2,right1 = 3,dig1 = 4,dig2 = 5;
    //left1表示从左边跌倒后保持住原来的方向,right1表示从右边跌倒后保持住原来的方向
    //dig1表示向左边挖掘,dig2表示从右边挖掘
    //组合逻辑
    always @(*)
        begin
            case(state)
                left:begin
                    if(ground == 1'b0)
                        next_state = left1;
                    else if(dig)
                        next_state = dig1;
                    else if(bump_left)
                        next_state = right;
                    else
                        next_state = left; 
                end
                right:begin
                    if(ground == 1'b0)
                        next_state = right1;
                    else if(dig)
                        next_state = dig2;
                    else if(bump_right)
                        next_state = left;
                    else
                        next_state = right; 
                end
                left1:begin
                    if(ground == 1'b0)
                        next_state = left1;
                    else
                        next_state = left; 
                end
                right1:begin
                    if(ground == 1'b0)
                        next_state = right1;
                    else
                        next_state = right; 
                end
                dig1:begin
                    if(ground == 1'b0)
                        next_state = left1;
                    else
                        next_state = dig1;
                end
                dig2:begin
                    if(ground == 1'b0)
                        next_state = right1;
                    else
                        next_state = dig2;
                end

            endcase
         
        end
    //时序逻辑
    always @(posedge clk,posedge areset)
        begin
            if(areset)
                state <= left;
            else
                state <= next_state;
        end
    //输出逻辑
    assign walk_right = (state == right);
    assign walk_left = (state == left);
    assign aaah = (state == left1 )|(state == right1);
    assign digging = (state == dig1) | (state == dig2);

endmodule

仿真结果如下:

题目4: Lemmings4

另请参阅:Lemmings1Lemmings2 和 Lemmings3

虽然旅鼠可以走路、摔倒和挖掘,但旅鼠并非无懈可击。如果旅鼠坠落太久然后撞到地面,它可能会飞溅。特别是,如果一只旅鼠坠落超过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 ); 

提示:使用 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 ); 
    reg [2:0] state ,next_state;
    parameter left = 0,right = 1,left1 = 2,right1 = 3,dig1 = 4,dig2 = 5,splat = 6,dead = 7;
    reg [4:0] t ;
     //left1表示从左边跌倒后保持住原来的方向,right1表示从右边跌倒后保持住原来的方向
    //dig1表示向左边挖掘,dig2表示从右边挖掘,splat表示飞溅,dead表示死亡
    //t表示计数
//计数器
    initial
        t <= 5'b1;//使用initial语句初始化
    always @(posedge clk,posedge areset)
        begin
            if(areset)
                t <= 5'b1;
            else if((next_state == left1) | (next_state == right1))
               t <= t+1'b1;
                   else
                       t <= 5'b1;
        end
//组合逻辑
    always @(*) begin
        case(state)
              left:begin
                    if(ground == 1'b0)
                        next_state = left1;
                    else if(dig)
                        next_state = dig1;
                    else if(bump_left)
                        next_state = right;
                    else
                        next_state = left; 
                end
                right:begin
                    if(ground == 1'b0)
                        next_state = right1;
                    else if(dig)
                        next_state = dig2;
                    else if(bump_right)
                        next_state = left;
                    else
                        next_state = right; 
                end
                left1:begin
                    if((ground == 1'b0 )&(t <= 5'd20))
                        next_state = left1;
                    else if((ground == 1'b0 )&( t>5'd20))
                        next_state = splat; 
                    else
                        next_state = left;
                end
                right1:begin
                    if((ground == 1'b0 ) &(t <= 5'd20))
                        next_state = right1;
                    else if((ground == 1'b0 )& t>5'd20)
                        next_state = splat; 
                    else
                        next_state = right; 
                end
                dig1:begin
                    if(ground == 1'b0)
                        next_state = left1;
                    else
                        next_state = dig1;
                end
                dig2:begin
                    if(ground == 1'b0)
                        next_state = right1;
                    else
                        next_state = dig2;
                end
            splat:begin
                if(ground == 1'b1)
                    next_state = dead;
                else
                    next_state = splat;
            end
            dead:begin
                next_state = dead;
            end
            endcase
        end
//时序逻辑
        always @(posedge clk ,posedge areset)
                       begin
                           if(areset)
                               state <= left;
                           else
                               state <= next_state;
                       end
 //输出逻辑
    assign walk_right = (state == right);
    assign walk_left = (state == left);
    assign aaah = ((state == left1 )|(state == right1)|(state == splat));
    assign digging = (state == dig1) | (state == dig2);              
endmodule

仿真结果如下:

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值