习题笔记 Lemmings4

See also: Lemmings1, Lemmings2, and Lemmings3.

Although Lemmings can walk, fall, and dig, Lemmings aren't invulnerable. If a Lemming falls for too long then hits the ground, it can splatter. In particular, if a Lemming falls for more than 20 clock cycles then hits the ground, it will splatter and cease walking, falling, or digging (all 4 outputs become 0), forever (Or until the FSM gets reset). There is no upper limit on how far a Lemming can fall before hitting the ground. Lemmings only splatter when hitting the ground; they do not splatter in mid-air.

Extend your finite state machine to model this behaviour.

笔记:用了两个方法,主要区别在于统计掉落时间的计数器部分以及设计的状态数,上述两个不同的设计导致会导致判定落地延迟的不同。

方法一:设计八个状态,当下落时间足够时进入“落地必寄”的状态,落地后进入死亡状态,由于从下落状态至落地必寄状态再至死亡状态会有延迟,因此落地时长的判定设置为19 (个人总觉得这种方法会有问题,但说不上来)

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;  //注意状态数和对应位宽是否足够
    reg [4:0]F_Time;             //记录下落时间
    wire Ready_SP;               //标记下落时间已足够splater
    parameter W_L=3'b000, W_R=3'b001, F_L=3'b010, F_R=3'b011, D_L=3'b100, D_R=3'b101, B_SP=3'b110 ,SP=3'b111 ,ON=1'b1, OFF=1'b0 ;

    //下落时间计数器
    always @(posedge clk or posedge areset)  
    begin 
      if (areset)
      F_Time <= 5'd0;                        //重置时计数器清零
      else if(state==F_L|state==F_R)              
      F_Time <= (F_Time==5'd19 ? 5'd19 : F_Time + 1'd1);
      else F_Time <= 5'd0;                   //中断下落状态计数器清零
    end
      
    assign Ready_SP=(F_Time==5'd19 ? 1'b1 : 1'b0);  //下落时间足够后触发R_SP信号
    
    
    always @(*)  //8个状态 6个常规状态 W_L W_R F_L F_R D_L D_R 记录落地死亡状态 B_SP 死亡状态 SP
    begin
      case(state)   
      W_L : next_state = (ground ? (dig ? D_L : (bump_left  ? W_R : W_L)): F_L); //walk状态优先通过ground是否为0信号判定fall
      W_R : next_state = (ground ? (dig ? D_R : (bump_right ? W_L : W_R)): F_R); //ground为1则判断dig,最后判断bump
      F_L : next_state = (ground ? W_L : (Ready_SP ? B_SP : F_L));               //不考虑落地直接转向,则下落状态要么维持,要么落地转为行走
      F_R : next_state = (ground ? W_R : (Ready_SP ? B_SP : F_R));               //下落过程时间若过长,进入B_SP状态
      D_L : next_state = (ground ? D_L : F_L);                                   //一旦开挖就挖到挖穿下落为止
      D_R : next_state = (ground ? D_R : F_R);
      B_SP: next_state = (ground ? SP  : B_SP);                                  //下落过程中B_SP保持状态,落地即splater
      SP  : next_state = SP;                                                     //状态锁定,直到reset
      
      endcase
    end

    always @(posedge clk or posedge areset)
    begin
      if (areset)
        state <= W_L;
      else
        state <= next_state;
    end 

    assign walk_left  = (state==W_L ? ON : OFF);
    assign walk_right = (state==W_R ? ON : OFF);
    assign aaah       = (state==F_L)|(state==F_R)|(state==B_SP);  //B_SP状态也要ahhh
    assign digging    = (state==D_L)|(state==D_R);

endmodule

方法二:去掉方法一中的Ready_Splater状态,改为条件达成的情况下,在时钟沿到来时直接由下落状态进入死亡状态,此时由于少了一个状态转换的周期,所以计数器计数改为20,相比之下个人认为这种方法更符合逻辑。

//lemmings4  改
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;  //注意状态数和对应位宽是否足够
    reg [4:0]F_Time;             //记录下落时间
    wire Ready_SP;               //代表已经下落了至少20周期
    parameter W_L=3'b000, W_R=3'b001, F_L=3'b010, F_R=3'b011, D_L=3'b100, D_R=3'b101, SP=3'b111 ,ON=1'b1, OFF=1'b0 ;

    //下落时间计数器  注意:计数器总是慢于state一个周期,即下落时长满了n个周期后,计数器才计到n,而不是在第n个下落周期时段内时,计数器为n
    always @(posedge clk or posedge areset)  
    begin 
      if (areset)
      F_Time <= 5'd0;                        //重置时计数器清零
      else if(state==F_L|state==F_R)              
      F_Time <= (F_Time==5'd20 ? 5'd20 : F_Time + 1'd1);
      else F_Time <= 5'd0;                   //中断下落状态计数器清零
    end
      
    assign Ready_SP=(F_Time==5'd20 ? 1'b1 : 1'b0);  //下落时间足够后触发R_SP信号
    
    
    always @(*)  //7个状态 6个常规状态 W_L W_R F_L F_R D_L D_R  死亡状态 SP
    begin
      case(state)   
      W_L : next_state = (ground ? (dig ? D_L : (bump_left  ? W_R : W_L)): F_L); //walk状态优先通过ground是否为0信号判定fall
      W_R : next_state = (ground ? (dig ? D_R : (bump_right ? W_L : W_R)): F_R); //ground为1则判断dig,最后判断bump
      F_L : next_state = (ground ? (Ready_SP ? SP : W_L): F_L);               //不考虑落地直接转向,则下落状态要么维持,要么落地转为行走
      F_R : next_state = (ground ? (Ready_SP ? SP : W_R): F_R);               //Ready_SP代表已经下落了至少20个周期,此时ground=0代表此刻下落时长超过了20周期,进入splater状态
      D_L : next_state = (ground ? D_L : F_L);                                   //一旦开挖就挖到挖穿下落为止
      D_R : next_state = (ground ? D_R : F_R);
      SP  : next_state = SP;                                                     
      
      endcase
    end

    always @(posedge clk or posedge areset)
    begin
      if (areset)
        state <= W_L;
      else
        state <= next_state;
    end 

    assign walk_left  = (state==W_L ? ON : OFF);
    assign walk_right = (state==W_R ? ON : OFF);
    assign aaah       = (state==F_L)|(state==F_R)|(state==B_SP);  //B_SP状态也要ahhh
    assign digging    = (state==D_L)|(state==D_R);

endmodule
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值