HDLbits答案更新系列13(3.2.5 Finite State Machines 3.2.5.10 Lemmings 1等)

目录

前言

3.2.5 Finite State Machines

3.2.5.10 Lemmings 1(Lemmings1)

3.2.5.11 Lemmings 2(Lemmings2)

3.2.5.12 Lemmings 3(Lemmings3)

3.2.5.13 Lemmings 4(Lemmings4)

结语

HDLbits网站链接


前言

今天更新几道题目,这几道题目是旅鼠游戏,这个游戏层层递进,状态机的思想体现地淋漓尽致,希望大家可以做一做,很有趣。

3.2.5 Finite State Machines

3.2.5.10 Lemmings 1(Lemmings1)

Lemmings.gif

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=1'b0, RIGHT=1'b1;
    reg state, next_state;
    
    always@(posedge clk or posedge areset)begin
        if(areset)begin
            state <= LEFT;
        end
        else begin
            state <= next_state;
        end
    end

    always @(*) begin
        case(state)
            LEFT:begin
                if(bump_left)begin
                    next_state = RIGHT;
                end
                else begin
                    next_state = LEFT;
                end
            end
            RIGHT:begin
                if(bump_right)begin
                    next_state = LEFT;
                end
                else begin
                    next_state = RIGHT;
                end
            end
        endcase
    end

    // Output logic
    assign walk_left = (state == LEFT);
    assign walk_right = (state == RIGHT);

endmodule

这道题目比较容易,旅鼠只有两种状态,向左走或者向右走,如果碰到障碍物,它将切换方向,也就是如果在左侧撞到,它将会朝右走,如果在右侧撞到,将会向左走。题目要求moore型状态机实现,应该没什么难度。

3.2.5.11 Lemmings 2(Lemmings2)

Lemmings2.gif

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 = 2'd0, RIGHT = 2'd1, GROUND_LEFT = 2'd2, GROUND_RIGHT = 2'd3;
    reg	[1:0]	current_state;
    reg [1: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 ? (bump_left ? RIGHT : LEFT) : GROUND_LEFT;
            end
            RIGHT:begin
                next_state = ground ? (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
            default:begin
                next_state = LEFT;
            end
        endcase
    end    
    
    assign walk_left = (current_state == LEFT);
    assign walk_right = (current_state == RIGHT);
    assign aaah = (current_state == GROUND_LEFT || current_state == GROUND_RIGHT);
    
    /*
    //second way
    always@(posedge clk or posedge areset)begin
        if(areset)begin
            aaah <= 1'b0;
        end
        else begin
            aaah <= ~ground;
        end
    end
    */

endmodule

这道题目相比第一道题,多加了一个掉落状态,如果ground为1,旅鼠将会发出大叫并且跌落。这里的旅鼠大叫信号(aaah)有两种实现方式,一种就是用状态机输出,另一种是直接将ground取反,但是不建议第二种方式,从作者的题意来看,要根据状态决定输出。

3.2.5.12 Lemmings 3(Lemmings3)

Lemmings3.gif

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);
    
    /*
    //second way
    always@(posedge clk or posedge areset)begin
        if(areset)begin
            aaah <= 1'b0;
        end
        else begin
            aaah <= ~ground;
        end
    end
    */

endmodule

这道题目花了我不少时间,主要在于状态的增加我没有理清楚。题目中作者说如果旅鼠在地面上(ground = 1)并且挖掘信号为1,则它可以开始挖洞,一直挖,直到把地都挖穿了(ground = 0),此时,旅鼠就掉下去了,并且发出大叫。对于大叫信号,和上一道题一样,有两种写法,建议用第一种。大家好好体会一下这道题目。

3.2.5.13 Lemmings 4(Lemmings4)

Lemmings4.gif

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, SPLATTER = 4'd6, AAAH_END = 4'd7;
    reg	[3:0]	current_state;
    reg [3:0]	next_state;
    
    
    reg [4:0]	counter;
    always@(posedge clk or posedge areset)begin
        if(areset)begin
            counter <= 5'd0;
        end
        else if(next_state == GROUND_LEFT || next_state == GROUND_RIGHT)begin
            counter <= counter + 1'b1;
        end
        else begin
            counter <= 5'd0;
        end
    end
    
    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 : (counter == 5'd20 ? SPLATTER : GROUND_LEFT);
            end
            GROUND_RIGHT:begin
                next_state = ground ? RIGHT : (counter == 5'd20 ? SPLATTER : 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
            SPLATTER:begin
                next_state = ground ? AAAH_END : SPLATTER;
            end
            AAAH_END:begin
                next_state = AAAH_END;
            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 || current_state == SPLATTER);   

endmodule

这道题目真是作者又加了一个输出,如果旅鼠跌落的时间太久(大于20个周期),旅鼠就挂了,所以这里需要一个计数器,来计算旅鼠跌落的时间,大家注意,这里的计数器和平常的计数器不太一样,这里计数器的加1条件是当旅鼠开始跌落起计时,如果计数到20个周期,旅鼠就完蛋了...这里的大叫信号只能采用博主答案中的这种方式,没有第二种方式了。建议大家先不要看答案,先自己做一做,这几道题目真是非常有意思。

结语

今天更新这几道旅鼠的题目吧,不知道为啥,每次都把旅鼠打成竹鼠......我也很无奈.....好啦,还是那句老话,如果代码有错误的地方,欢迎大家指出来,我一定尽快改正。

HDLbits网站链接

https://hdlbits.01xz.net/wiki/Main_Page

 

  • 12
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 15
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值