2021年7月3日 星期六

HDLBits/Sequential Logic/Finite State Machines/Lemmings3

HDLBits/Sequential Logic/Finite State Machines/Lemmings3

 In addition to walking and falling, Lemmings can sometimes be told to do useful things, like dig (it starts digging when dig=1). A Lemming can dig if it is currently walking on ground (ground=1 and not falling), and will continue digging until it reaches the other side (ground=0). At that point, since there is no ground, it will fall (aaah!), then continue walking in its original direction once it hits ground again. As with falling, being bumped while digging has no effect, and being told to dig when falling or when there is no ground is ignored.

(In other words, a walking Lemming can fall, dig, or switch directions. If more than one of these conditions are satisfied, fall has higher precedence than dig, which has higher precedence than switching directions.)

Extend your finite state machine to model this behaviour.




主要在於狀態的增加我沒有理清楚。題目中作者說如果旅鼠在地面上(ground = 1)並且挖掘信號為1,則它可以開始挖洞,一直挖,直到把地都挖穿了(ground = 0),此時,旅鼠就掉下去了,並且发出大叫。

增加了挖寶功能,當地面是平整時,可以進行挖寶,直到將地面挖空。

Game Lemmings3:有個小人左右走,它只有兩種狀態:向左走和向右走;左邊碰到東西之後它就向右走,右邊碰到東西之後它就向左走,兩邊都碰到東西就跟當前方向的反方向走;覆位時小人向左走;

添加ground信號,ground=1時規則與上述規則相同;ground=0時,記錄當前走的方向,並將aaah信號置1,直到ground=1時,走與掉落之前相同的方向。

添加dig信號,ground=1時一直挖,ground=0時,進入aaah狀態,直到ground再次為1,方向與dig開始的方向相同。

優先級:fall>dig>switch direction

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 = 4'd0, RIGHT = 4'd1, GROUND_LEFT = 4'd2, GROUND_RIGHT = 4'd3;
    parameter DIGGING_LEFT = 4'd4, DIGGING_RIGHT = 4'd5;
    reg [3:0] current_state;
    reg [3:0] next_state;
    
    always@(posedge clk or posedge areset)begin
        if(areset)begin
            current_state <= LEFT;
        end
        else begin
            current_state <= next_state;
        end
    end
    
    always@(*)begin
        case(current_state)
            LEFT:begin
                next_state = ground ? (dig ? DIGGING_LEFT : (bump_left ? RIGHT : LEFT)) : GROUND_LEFT;
            end
            RIGHT:begin
                next_state = ground ? (dig ? DIGGING_RIGHT : (bump_right ? LEFT : RIGHT)) : GROUND_RIGHT;
            end
            GROUND_LEFT:begin
                next_state = ground ? LEFT : GROUND_LEFT;
            end
            GROUND_RIGHT:begin
                next_state = ground ? RIGHT : GROUND_RIGHT;
            end
            DIGGING_LEFT:begin
                next_state = ground ? DIGGING_LEFT : GROUND_LEFT;
            end
            DIGGING_RIGHT:begin
                next_state = ground ? DIGGING_RIGHT : GROUND_RIGHT;
            end
            default:begin
                next_state = LEFT;
            end
        endcase
    end    
    
    assign walk_left = (current_state == LEFT);
    assign walk_right = (current_state == RIGHT);
    assign digging = (current_state == DIGGING_LEFT || current_state == DIGGING_RIGHT);
    assign aaah = (current_state == GROUND_LEFT || current_state == GROUND_RIGHT);
endmodule

//-------------------------------------------------

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 = 4'd0, RIGHT = 4'd1, GROUND_LEFT = 4'd2, GROUND_RIGHT = 4'd3;
    parameter DIGGING_LEFT = 4'd4, DIGGING_RIGHT = 4'd5;
    wire [1:0] bump;
    assign bump = {bump_left,bump_right};
    reg [3:0] current_state;
    reg [3:0] next_state;
     
    always@(posedge clk or posedge areset)begin
        if(areset)begin
            current_state <= LEFT;
        end
        else begin
            current_state <= next_state;
        end
    end
    
    always@(*)begin
        case(current_state)
            LEFT:begin
               if(ground == 1'b0)begin
                    next_state <= GROUND_LEFT;
                end
                else if(dig == 1'b1)begin
                    next_state <= DIGGING_LEFT;
                end
                else if((bump == 2'b10) || (bump == 2'b11))begin
                    next_state <= RIGHT;
                end
                else begin
                next_state <= LEFT;
                end
                //next_state = ground ? (dig ? DIGGING_LEFT : (bump_left ? RIGHT : LEFT)) : GROUND_LEFT;
            end
            RIGHT:begin
              if(ground == 1'b0)begin
                    next_state <= GROUND_RIGHT;
                end
                else if(dig == 1'b1)begin
                    next_state <= DIGGING_RIGHT;
                end
                else if((bump == 2'b01) || (bump == 2'b11))begin
                    next_state <= LEFT;
                end
                else begin
                next_state <= RIGHT;
                end
                //next_state = ground ? (dig ? DIGGING_RIGHT : (bump_right ? LEFT : RIGHT)) : GROUND_RIGHT;
            end
            GROUND_LEFT:begin
                next_state = ground ? LEFT : GROUND_LEFT;
            end
            GROUND_RIGHT:begin
                next_state = ground ? RIGHT : GROUND_RIGHT;
            end
            DIGGING_LEFT:begin
                next_state = ground ? DIGGING_LEFT : GROUND_LEFT;
            end
            DIGGING_RIGHT:begin
                next_state = ground ? DIGGING_RIGHT : GROUND_RIGHT;
            end
            default:begin
                next_state = LEFT;
            end
        endcase
    end    
    
    assign walk_left = (current_state == LEFT);
    assign walk_right = (current_state == RIGHT);
    assign digging = (current_state == DIGGING_LEFT || current_state == DIGGING_RIGHT);
    assign aaah = (current_state == GROUND_LEFT || current_state == GROUND_RIGHT);
endmodule

沒有留言:

張貼留言

Messaging API作為替代方案

  LINE超好用功能要沒了!LINE Notify明年3月底終止服務,有什麼替代方案? LINE Notify將於2025年3月31日結束服務,官方建議改用Messaging API作為替代方案。 //CHANNEL_ACCESS_TOKEN = 'Messaging ...