HDLBits中文版,标准参考答案 | 3.2.5 Finite State Machines | 有限状态机(2)

news2025/5/24 10:47:00

关注 望森FPGA  查看更多FPGA资讯

这是望森的第 17 期分享

作者 | 望森
来源 | 望森FPGA

目录

1 Lemmings 1

2 Lemmings 2

3 Lemmings 3

4 Lemmings 4

5 One-hot FSM | 独热 FSM

6 PS/2 packet parser | PS/2 数据包解析器

7 PS/2 packet parser anddatapath | PS/2 数据包解析器和数据路径


本文中的代码都能够正常运行,请放心食用😋~

练习的官方网站是:https://hdlbits.01xz.net/

注:作者将每个练习的知识点都放在了题目和答案之后


1 Lemmings 1

题目:

游戏《旅鼠》涉及的动物大脑相当简单。非常简单,我们将使用有限状态机对其进行建模。

在《旅鼠》的 2D 世界中,旅鼠可以处于两种状态之一:向左行走或向右行走。如果撞到障碍物,它会改变方向。具体来说,如果旅鼠左侧受到撞击,它会向右行走。如果右侧受到撞击,它会向左行走。如果两侧同时受到撞击,它仍会改变方向。

实现一个 Moore 状态机,该状态机具有两个状态、两个输入和一个输出,可以对此行为进行建模。

答案:

我的答案:
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 LEFT=1'b0, RIGHT=1'b1; 

    wire LEFT2LEFT,LEFT2RIGHT,RIGHT2RIGHT,RIGHT2LEFT;

    always @(posedge clk or posedge areset) begin    // This is a sequential always block
        // State flip-flops with asynchronous reset
        if(areset)begin
            state <= LEFT;
        end
        else begin
            state <= next_state;
        end
    end
    
    always @(*) begin    // This is a combinational always block
        // State transition logic
        case(state)
            LEFT : begin
                if (LEFT2LEFT)begin
                    next_state = LEFT;
                end
                else if (LEFT2RIGHT)begin
                    next_state = RIGHT;
                end
            end
            RIGHT : begin
                if (RIGHT2RIGHT)begin
                    next_state = RIGHT;
                end
                else if (RIGHT2LEFT)begin
                    next_state = LEFT;
                end
            end
            default next_state = state;
        endcase
    end
    
    assign LEFT2LEFT         = !bump_left;
    assign LEFT2RIGHT         = bump_left;
    assign RIGHT2RIGHT         = !bump_right;
    assign RIGHT2LEFT         = bump_right;

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

endmodule

参考答案:
module top_module (
        input clk,
        input areset,
        input bump_left,
        input bump_right,
        output walk_left,
        output walk_right
);

        // Give state names and assignments. I'm lazy, so I like to use decimal numbers.
        // It doesn't really matter what assignment is used, as long as they're unique.
        parameter WL=0, WR=1;
        reg state;
        reg next;
    
    
    // Combinational always block for state transition logic. Given the current state and inputs,
    // what should be next state be?
    // Combinational always block: Use blocking assignments.    
    always@(*) begin
                case (state)
                        WL: next = bump_left  ? WR : WL;
                        WR: next = bump_right ? WL : WR;
                endcase
    end
    
    
    // Combinational always block for state transition logic. Given the current state and inputs,
    // what should be next state be?
    // Combinational always block: Use blocking assignments.    
    always @(posedge clk, posedge areset) begin
                if (areset) state <= WL;
        else state <= next;
        end
                
                
        // Combinational output logic. In this problem, an assign statement are the simplest.
        // In more complex circuits, a combinational always block may be more suitable.                
        assign walk_left = (state==WL);
        assign walk_right = (state==WR);

        
endmodule

知识点:

提示:


2 Lemmings 2

题目:

除了左右行走外,如果脚下的地面消失,旅鼠还会摔倒(大概会发出“啊啊啊”的声音)。

除了左右行走和被撞时改变方向外,当地面 = 0 时,旅鼠还会摔倒并发出“啊啊啊”的声音。当地面重新出现(地面 = 1 时),旅鼠会继续沿摔倒前的方向行走。摔倒时被撞不会影响行走方向,在地面消失(但尚未摔倒)的同一周期内被撞,或者在摔倒时地面重新出现,也不会影响行走方向。

构建一个有限状态机来模拟此行为。

答案:

1.状态转换图

2.代码

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=0, RIGHT=1, ...
    reg [1:0] state, next_state;
        parameter LEFT=2'd0, RIGHT=2'd1,FALL_LEFT=2'd2,FALL_RIGHT=2'd3; 

    wire LEFT2LEFT,LEFT2RIGHT,LEFT2FALL_LEFT,RIGHT2RIGHT,RIGHT2LEFT,RIGHT2FALL_RIGHT
    ,FALL_LEFT2FALL_LEFT,FALL_LEFT2LEFT,FALL_RIGHT2FALL_RIGHT,FALL_RIGHT2RIGHT;

    always @(posedge clk or posedge areset) begin    // This is a sequential always block
        // State flip-flops with asynchronous reset
        if(areset)begin
            state <= LEFT;
        end
        else begin
            state <= next_state;
        end
    end
    
    always @(*) begin    // This is a combinational always block
        // State transition logic
        case(state)
            LEFT : begin
                if (LEFT2LEFT)begin
                    next_state = LEFT;
                end
                else if (LEFT2RIGHT)begin
                    next_state = RIGHT;
                end
                else if (LEFT2FALL_LEFT)begin
                    next_state = FALL_LEFT;
                end
            end
            RIGHT : begin
                if (RIGHT2RIGHT)begin
                    next_state = RIGHT;
                end
                else if (RIGHT2LEFT)begin
                    next_state = LEFT;
                end
                else if (RIGHT2FALL_RIGHT)begin
                    next_state = FALL_RIGHT;
                end
            end
            FALL_LEFT : begin
                if (FALL_LEFT2FALL_LEFT)begin
                    next_state = FALL_LEFT;
                end
                else if (FALL_LEFT2LEFT)begin
                    next_state = LEFT;
                end
            end
            FALL_RIGHT : begin
                if (FALL_RIGHT2FALL_RIGHT)begin
                    next_state = FALL_RIGHT;
                end
                else if (FALL_RIGHT2RIGHT)begin
                    next_state = RIGHT;
                end
            end
            default next_state = state;
        endcase
    end
    
    assign LEFT2LEFT                         = !bump_left && ground;
    assign LEFT2RIGHT                         = bump_left && ground;
    assign LEFT2FALL_LEFT                 = !ground;
    assign RIGHT2RIGHT                         = !bump_right && ground;
    assign RIGHT2LEFT                         = bump_right && ground;
    assign RIGHT2FALL_RIGHT         = !ground;
    assign FALL_LEFT2FALL_LEFT      = !ground;
    assign FALL_LEFT2LEFT                 = ground;
    assign FALL_RIGHT2FALL_RIGHT    = !ground;
    assign FALL_RIGHT2RIGHT         = ground;

    // Output logic
    // assign out = (state == ...);
    assign walk_left        = (state == LEFT);
    assign walk_right       = (state == RIGHT);
    assign aaah                 = (state == FALL_LEFT) || (state == FALL_RIGHT);
    
endmodule

知识点:

提示:


3 Lemmings 3

题目:

除了行走和跌倒,有时还可以命令旅鼠做一些有用的事情,比如挖掘(当 dig=1 时,它会开始挖掘)。如果旅鼠当前正在地面上行走( ground=1 且没有跌倒),它可以挖掘,并会继续挖掘直到到达另一侧( ground=0 )。此时,由于没有地面,它会跌倒(aaah!),然后再次接触地面后继续沿其原始方向行走。与跌倒一样,在挖掘时受到撞击不会产生任何影响,并且在跌倒或没有地面时被告知挖掘会被忽略。

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

扩展您的有限状态机以模拟此行为。

答案:

1.状态转换图

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=3'd0, RIGHT=3'd1,DIG_LEFT=3'd2,DIG_RIGHT=3'd3,FALL_LEFT=3'd4,FALL_RIGHT=3'd5; 

    wire LEFT2LEFT,LEFT2RIGHT,LEFT2DIG_LEFT,LEFT2FALL_LEFT,
    RIGHT2RIGHT,RIGHT2LEFT,RIGHT2DIG_RIGHT,RIGHT2FALL_RIGHT,
    DIG_LEFT2FALL_LEFT,DIG_LEFT2DIG_LEFT,
    DIG_RIGHT2FALL_RIGHT,DIG_RIGHT2DIG_RIGHT,
    FALL_LEFT2FALL_LEFT,FALL_LEFT2LEFT,
    FALL_RIGHT2FALL_RIGHT,FALL_RIGHT2RIGHT;

    always @(posedge clk or posedge areset) begin    // This is a sequential always block
        // State flip-flops with asynchronous reset
        if(areset)begin
            state <= LEFT;
        end
        else begin
            state <= next_state;
        end
    end
    
    always @(*) begin    // This is a combinational always block
        // State transition logic
        case(state)
            LEFT : begin
                if (LEFT2LEFT)begin
                    next_state = LEFT;
                end
                else if (LEFT2RIGHT)begin
                    next_state = RIGHT;
                end
                else if (LEFT2DIG_LEFT)begin
                    next_state = DIG_LEFT;
                end
                else if (LEFT2FALL_LEFT)begin
                    next_state = FALL_LEFT;
                end
            end
            RIGHT : begin
                if (RIGHT2RIGHT)begin
                    next_state = RIGHT;
                end
                else if (RIGHT2LEFT)begin
                    next_state = LEFT;
                end
                else if (RIGHT2DIG_RIGHT)begin
                    next_state = DIG_RIGHT;
                end
                else if (RIGHT2FALL_RIGHT)begin
                    next_state = FALL_RIGHT;
                end
            end
            DIG_LEFT : begin
                if (DIG_LEFT2FALL_LEFT)begin
                    next_state = FALL_LEFT;
                end
                else if (DIG_LEFT2DIG_LEFT)begin
                    next_state = DIG_LEFT;
                end
            end
            DIG_RIGHT : begin
                if (DIG_RIGHT2FALL_RIGHT)begin
                    next_state = FALL_RIGHT;
                end
                else if (DIG_RIGHT2DIG_RIGHT)begin
                    next_state = DIG_RIGHT;
                end
            end
            FALL_LEFT : begin
                if (FALL_LEFT2FALL_LEFT)begin
                    next_state = FALL_LEFT;
                end
                else if (FALL_LEFT2LEFT)begin
                    next_state = LEFT;
                end
            end
            FALL_RIGHT : begin
                if (FALL_RIGHT2FALL_RIGHT)begin
                    next_state = FALL_RIGHT;
                end
                else if (FALL_RIGHT2RIGHT)begin
                    next_state = RIGHT;
                end
            end
            default next_state = LEFT;
        endcase
    end
    
    /*bump_left,bump_right,ground,dig,*/
    
    assign LEFT2LEFT                = !bump_left && ground && !dig;
    assign LEFT2RIGHT               = bump_left && ground && !dig;
    assign LEFT2DIG_LEFT            = ground && dig;
    assign LEFT2FALL_LEFT           = !ground;
    
    assign RIGHT2RIGHT              = !bump_right && ground && !dig;
    assign RIGHT2LEFT               = bump_right && ground && !dig;
    assign RIGHT2DIG_RIGHT          = ground && dig;
    assign RIGHT2FALL_RIGHT         = !ground;
    
    assign DIG_LEFT2FALL_LEFT      = !ground;
    assign DIG_LEFT2DIG_LEFT        = ground;
    
    assign DIG_RIGHT2FALL_RIGHT     = !ground;
    assign DIG_RIGHT2DIG_RIGHT      = ground ;
    
    assign FALL_LEFT2FALL_LEFT      = !ground;
    assign FALL_LEFT2LEFT           = ground;
    
    assign FALL_RIGHT2FALL_RIGHT    = !ground;
    assign FALL_RIGHT2RIGHT         = ground;

    // Output logic
    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 Lemmings 4

题目:

尽管旅鼠可以行走、跌倒和挖洞,但它们并非无懈可击。如果旅鼠跌倒时间过长,然后撞到地面,它就会 splatter 四分五裂。具体来说,如果旅鼠跌倒超过 20 个时钟周期,然后撞到地面,它就会四分五裂并停止行走、跌倒或挖洞(所有 4 个输出都变为 0),永远(或直到 FSM 重置)。旅鼠在撞到地面之前可以跌倒多远没有上限。旅鼠只有在撞到地面时才会四分五裂;它们不会在半空中四分五裂。

扩展您的有限状态机以模拟此行为。

跌倒 20 个周期是可以存活的:

跌落21次导致四分五裂:

答案:

1.状态转换图

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=3'd0, RIGHT=3'd1,DIG_LEFT=3'd2,DIG_RIGHT=3'd3,
    FALL_LEFT=3'd4,FALL_RIGHT=3'd5,SLATTER=3'd6; 
    
    reg [4:0] cnt_fall;
    reg FALL_20clk;
    
    wire LEFT2LEFT,LEFT2RIGHT,LEFT2DIG_LEFT,LEFT2FALL_LEFT,
    RIGHT2RIGHT,RIGHT2LEFT,RIGHT2DIG_RIGHT,RIGHT2FALL_RIGHT,
    DIG_LEFT2FALL_LEFT,DIG_LEFT2DIG_LEFT,
    DIG_RIGHT2FALL_RIGHT,DIG_RIGHT2DIG_RIGHT,
    FALL_LEFT2FALL_LEFT,FALL_LEFT2LEFT,FALL_LEFT2SLATTER,
    FALL_RIGHT2FALL_RIGHT,FALL_RIGHT2RIGHT,FALL_RIGHT2SLATTER;

        //FALL counter & 20clk flag
    always @(posedge clk or posedge areset) begin
        if(areset)begin
            cnt_fall <= 5'd0;
        end
        else if(state == FALL_LEFT || state == FALL_RIGHT)begin
            cnt_fall <= cnt_fall + 5'd1;
        end
        else begin
            cnt_fall <= 5'd0;
        end
    end
    always @(*) begin 
        if(areset)begin
            FALL_20clk = 1'd0;
        end
        else if(cnt_fall > 5'd19)begin
            FALL_20clk = 1'd1;
        end
        else begin
            FALL_20clk = FALL_20clk;
        end
    end
    
    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 (LEFT2LEFT)begin
                    next_state = LEFT;
                end
                else if (LEFT2RIGHT)begin
                    next_state = RIGHT;
                end
                else if (LEFT2DIG_LEFT)begin
                    next_state = DIG_LEFT;
                end
                else if (LEFT2FALL_LEFT)begin
                    next_state = FALL_LEFT;
                end
            end
            RIGHT : begin
                if (RIGHT2RIGHT)begin
                    next_state = RIGHT;
                end
                else if (RIGHT2LEFT)begin
                    next_state = LEFT;
                end
                else if (RIGHT2DIG_RIGHT)begin
                    next_state = DIG_RIGHT;
                end
                else if (RIGHT2FALL_RIGHT)begin
                    next_state = FALL_RIGHT;
                end
            end
            DIG_LEFT : begin
                if (DIG_LEFT2FALL_LEFT)begin
                    next_state = FALL_LEFT;
                end
                else if (DIG_LEFT2DIG_LEFT)begin
                    next_state = DIG_LEFT;
                end
            end
            DIG_RIGHT : begin
                if (DIG_RIGHT2FALL_RIGHT)begin
                    next_state = FALL_RIGHT;
                end
                else if (DIG_RIGHT2DIG_RIGHT)begin
                    next_state = DIG_RIGHT;
                end
            end
            FALL_LEFT : begin
                if (FALL_LEFT2FALL_LEFT)begin
                    next_state = FALL_LEFT;
                end
                else if (FALL_LEFT2LEFT)begin
                    next_state = LEFT;
                end
                else if (FALL_LEFT2SLATTER)begin
                    next_state = SLATTER;
                end
            end
            FALL_RIGHT : begin
                if (FALL_RIGHT2FALL_RIGHT)begin
                    next_state = FALL_RIGHT;
                end
                else if (FALL_RIGHT2RIGHT)begin
                    next_state = RIGHT;
                end
                else if (FALL_RIGHT2SLATTER)begin
                    next_state = SLATTER;
                end
            end
            SLATTER : begin
                next_state = SLATTER;
            end
            default next_state = LEFT;
        endcase
    end
    
    /*bump_left,bump_right,ground,dig,*/
    assign LEFT2LEFT                = !bump_left && ground && !dig;
    assign LEFT2RIGHT               = bump_left && ground && !dig;
    assign LEFT2DIG_LEFT            = ground && dig;
    assign LEFT2FALL_LEFT           = !ground;
    
    assign RIGHT2RIGHT              = !bump_right && ground && !dig;
    assign RIGHT2LEFT               = bump_right && ground && !dig;
    assign RIGHT2DIG_RIGHT          = ground && dig;
    assign RIGHT2FALL_RIGHT         = !ground;
    
    assign DIG_LEFT2FALL_LEFT      = !ground;
    assign DIG_LEFT2DIG_LEFT        = ground;
    
    assign DIG_RIGHT2FALL_RIGHT     = !ground;
    assign DIG_RIGHT2DIG_RIGHT      = ground ;
    
    assign FALL_LEFT2FALL_LEFT      = !ground;
    assign FALL_LEFT2LEFT           = ground && !FALL_20clk;
    assign FALL_LEFT2SLATTER        = ground && FALL_20clk;
    
    assign FALL_RIGHT2FALL_RIGHT    = !ground;
    assign FALL_RIGHT2RIGHT         = ground && !FALL_20clk;
    assign FALL_RIGHT2SLATTER       = ground && FALL_20clk;

    // Output logic
    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

知识点:

提示:使用 FSM 来控制计数器,追踪 Lemming 下落的时间长度。


5 One-hot FSM | 独热 FSM

题目:

给定以下具有 1 个输入和 2 个输出的状态机:

假设此状态机使用独热编码,其中 state[0] 到 state[9] 分别对应于状态 S0 到 S9。除非另有说明,否则输出为零。

实现状态机的状态转换逻辑和输出逻辑部分(但不是状态触发器)。您将在 state[9:0] 中得到当前状态,并且必须生成 next_state[9:0] 和两个输出。通过检查得出逻辑方程,假设采用独热编码。(测试台将使用非独热输入进行测试,以确保您不会尝试执行更复杂的事情)。

提示:

通过查看状态转换图的入边,可以推导出独热状态转换逻辑的逻辑方程。

答案:

module top_module(
    input in,
    input [9:0] state,
    output [9:0] next_state,
    output out1,
    output out2
);
    parameter S0 = 0, S1 = 1, S2 = 2, S3 = 3, S4 = 4, S5 = 5, S6 = 6, S7 = 7, S8 = 8, S9 = 9 ; 
 
    assign next_state[S0] = (state[S0] & !in) | (state[S1] & !in) | (state[S2] & !in) | (state[S3] & !in) | (state[S4] & !in) | 
    (state[S7] & !in) | (state[S8] & !in) | (state[S9] & !in) ;
    assign next_state[S1] = (state[S0] & in) | (state[S8] & in) | (state[S9] & in) ; 
    assign next_state[S2] = state[S1] & in ; 
    assign next_state[S3] = state[S2] & in ; 
    assign next_state[S4] = state[S3] & in ; 
    assign next_state[S5] = state[S4] & in ; 
    assign next_state[S6] = state[S5] & in ; 
    assign next_state[S7] = (state[S6] & in) | (state[S7] & in) ; 
    assign next_state[S8] = state[S5] & !in ; 
    assign next_state[S9] = state[S6] & !in ; 
 
    assign out1 = state[S8] | state[S9] ; 
    assign out2 = state[S7] | state[S9] ; 
 
endmodule

6 PS/2 packet parser | PS/2 数据包解析器

题目:

PS/2 鼠标协议发送三个字节长的消息。但是,在连续的字节流中,消息的开始和结束位置并不明显。唯一的迹象是每个三字节消息的第一个字节始终具有 bit[3]=1(但其他两个字节的 bit[3] 可能为 1 或 0,具体取决于数据)。

我们想要一个有限状态机,当给定输入字节流时,它将搜索消息边界。我们将使用的算法是丢弃字节,直到我们看到 bit[3]=1 的字节。然后我们假设这是消息的第 1 个字节,并在收到所有 3 个字节(完成)后发出消息接收信号。

在成功接收每条消息的第三个字节后,FSM 应立即在循环中发出完成信号。

一些时序图用于解释所需行为

在无错误的情况下,每三个字节形成一条消息:

当发生错误时,搜索字节1:

请注意,这与 1xx 序列识别器不同。这里不允许重叠序列:

答案:

1.状态转换图

2.代码

module top_module(
    input clk,
    input [7:0] in,
    input reset,    // Synchronous reset
    output done); //

    reg [1:0] state, next_state;
    parameter BYTE1=2'd0, BYTE2=2'd1, BYTE3=2'd2, DONE=2'd3; 
    wire BYTE12BYTE1,BYTE12BYTE2,DONE2BYTE1,DONE2BYTE2;
    
    // State transition logic (combinational)
    always @(posedge clk) begin
        if(reset)begin
            state <= BYTE1;
        end
        else begin
            state <= next_state;
        end
    end

    always @(*) begin
        case(state)
            BYTE1 : begin
                if (BYTE12BYTE1)begin
                    next_state = BYTE1;
                end
                else if (BYTE12BYTE2)begin
                    next_state = BYTE2;
                end
            end
            BYTE2 : begin
                next_state = BYTE3;
            end
            BYTE3 : begin
                next_state = DONE;
            end
            DONE : begin
                if (DONE2BYTE1)begin
                    next_state = BYTE1;
                end
                else if (DONE2BYTE2)begin
                    next_state = BYTE2;
                end
            end
            default next_state = 2'd0;
        endcase
    end
    
    assign BYTE12BYTE1       = in[3] == 0;
    assign BYTE12BYTE2       = in[3] == 1;
    assign DONE2BYTE1        = in[3] == 0;
    assign DONE2BYTE2        = in[3] == 1;

    // Output logic
    assign done         = (state == DONE);
    

endmodule

知识点:

提示:

  • 尽管 in[7:0] 是一个字节,但 FSM 只有一个输入:in[3]。

  • 您需要 4 个状态。三个状态可能行不通,因为其中一个状态需要断言 done,而对于每个收到的消息,done 只会断言一个周期。


7 PS/2 packet parser anddatapath | PS/2 数据包解析器和数据路径

题目:

现在您有了一个可以识别 PS/2 字节流中的三字节消息的状态机,请添加一个数据路径,该数据路径还会在收到数据包时输出 24 位(3 字节)消息(out_bytes[23:16] 是第一个字节,out_bytes[15:8] 是第二个字节,等等)。

只要 done 信号被置位,out_bytes 就必须有效。您可以在其他时间输出任何内容(即,无关紧要)。

例如:

答案:

module top_module(
    input clk,
    input [7:0] in,
    input reset,    // Synchronous reset
    output [23:0] out_bytes,
    output done); //

// FSM from fsm_ps2
    reg [1:0] state, next_state;
    parameter BYTE1=2'd0, BYTE2=2'd1, BYTE3=2'd2, DONE=2'd3; 
    wire BYTE12BYTE1,BYTE12BYTE2,DONE2BYTE1,DONE2BYTE2;
    
    // State transition logic (combinational)
    always @(posedge clk) begin
        if(reset)begin
            state <= BYTE1;
        end
        else begin
            state <= next_state;
        end
    end

    always @(*) begin
        case(state)
            BYTE1 : begin
                if (BYTE12BYTE1)begin
                    next_state = BYTE1;
                end
                else if (BYTE12BYTE2)begin
                    next_state = BYTE2;
                end
            end
            BYTE2 : begin
                next_state = BYTE3;
            end
            BYTE3 : begin
                next_state = DONE;
            end
            DONE : begin
                if (DONE2BYTE1)begin
                    next_state = BYTE1;
                end
                else if (DONE2BYTE2)begin
                    next_state = BYTE2;
                end
            end
            default next_state = 2'd0;
        endcase
    end
    
    assign BYTE12BYTE1       = in[3] == 0;
    assign BYTE12BYTE2       = in[3] == 1;
    assign DONE2BYTE1        = in[3] == 0;
    assign DONE2BYTE2        = in[3] == 1;

    // Output logic
    assign done         = (state == DONE);
// New: Datapath to store incoming bytes.
    reg [23:0] in_temp;
    always @(posedge clk) begin
        in_temp <= {in_temp[15:0],in};
    end
    assign out_bytes = (state == DONE) ? in_temp : 0 ;
    
endmodule

知识点:

提示:

使用 PS/2 数据包解析器的 FSM 并添加数据路径来捕获传入的字节。

讲解:

在上题基础上,增加三个字节的寄存器,在 DONE 状态时输出数据即可。


- END -

公z号/CSDN搜索【望森FPGA】,查看更多FPGA资讯~

相关推荐文章,点击跳转:

望森FPGA的HDLBits合集

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2201950.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

55 WebSocket

55 WebSocket 参考资料 WebSocket SpringBoot使用WebSocket SpringBoot 集成WebSocket详解 前言 WebSocket是HTML5下一种新的协议&#xff08;websocket协议本质上是一个基于tcp的协议&#xff09;它实现了浏览器与服务器全双工通信&#xff0c;能更好的节省服务器资源和…

AI大模型微调产品经理面试必备全攻略,非常详细收藏我这一篇就够了

前言 这两天跟很多做程序员的朋友聊天&#xff0c;怎么看全网火爆的大模型。让我挺意外的是&#xff0c;大家的反馈普遍都很焦虑 。 在AI大模型微调领域的产品经理面试中&#xff0c;总会遇到一系列与技术细节、项目经验、市场趋势以及职业规划相关的问题。以下是一些建议的面…

RabbitMQ中如何解决消息堆积问题,如何保证消息有序性

RabbitMQ中如何解决消息堆积问题 如何保证消息有序性 只需要让一个消息队列只对应一个消费者即可

cdr激活码序列号coredraw2024安装包破解版coreldraw2024永久序列号最新

&#x1f31f;设计界的新宠儿来啦&#xff01;CorelDRAW 2024震撼登场&#x1f389; ### &#x1f308; 开篇狂想曲&#xff1a;设计师们的“瑞士军刀”升级记&#xff01;&#x1f3a8; 嘿&#xff0c;亲爱的创意达人们&#x1f44b;&#xff01;今天&#xff0c;就让我们共同…

6.将扩散模型与其他生成模型的关联(1)

在本章中&#xff0c;我们首先介绍其他5种重要的生成模型&#xff0c;包括变分自编码器抗网络、归一化流、自回归模型和基于能量的模型&#xff0c;分析它们的优点和局限性&#xff0c;并说明这些生成模型是如何通过纳入扩散模型而得到促进的。1 .变分自编码器与扩散模型 …

Java | Leetcode Java题解之第455题分发饼干

题目&#xff1a; 题解&#xff1a; class Solution {public int findContentChildren(int[] g, int[] s) {Arrays.sort(g);Arrays.sort(s);int m g.length, n s.length;int count 0;for (int i 0, j 0; i < m && j < n; i, j) {while (j < n &&…

鸿蒙开发之ArkUI 界面篇 二十五 点赞综合案例

要实现如下图效果&#xff0c;红框处是点赞数&#xff0c;点击会变色和数字增加1&#xff1a; 我们首先分析布局结构&#xff0c;整体式垂直方向的布局&#xff0c;外层容器自然是Colum&#xff0c;上层是图片组件Image&#xff0c;接下来是Text组件&#xff0c;接下来是Row组件…

Unity实战案例全解析 类宝可梦回合制的初级案例 源码分析(加了注释和流程图)

这是一个老教程了&#xff0c;但是对于没有写过回合制的初级程序同学来讲是比较适合的&#xff0c;也可以直接看源码&#xff0c;半小时内可以解决战斗 当然&#xff0c;我也没写过回合制系统所以就到处找&#xff0c;思路明白了就能自己修改了 视频教程 - 油管链接 Turn-Bas…

ComfyUI | 5分钟部署最新Flux大模型

Midjourney 和 Stable Diffusion 都是目前流行的 AI 图像生成工具&#xff0c;它们能够根据文本描述生成高质量的图像。都是基于深度学习技术的文本到图像生成模型&#xff0c;但它们各自基于不同的大模型。 但最近推出了一款比前两者更强大&#xff0c;生成图像更加逼真&…

UE4 材质学习笔记04(着色器性能优化)

一.着色器性能优化 1.衡量着色器的性能 衡量着色器性能的主要方法有三个 第一个&#xff1a;可以使用场景的视图模式的优化视图模式的着色器复杂度 下面的滑条代表了着色器指令的复杂度 如果场景大部分是绿色的&#xff0c;说明着色器耗能低&#xff0c;反之白色则是很糟糕…

VS Code安装以及配置

安装 1. 下载安装 VScode官网 注意&#xff0c;这一步最好全部打勾 2. 设置默认terminal为cmd 3. 修改Run Code的配置 参考&#xff1a; https://blog.csdn.net/weixin_46474921/article/details/132841711

2024年诺贝尔物理学奖 机器学习与神经网络领域前景面面观 如何抉择

近日&#xff0c;2024年诺贝尔物理学奖颁发给了机器学习与神经网络领域的研究者&#xff0c;这是历史上首次出现这样的情况。这项奖项原本只授予对自然现象和物质的物理学研究作出重大贡献的科学家&#xff0c;如今却将全球范围内对机器学习和神经网络的研究和开发作为了一种能…

【element-tiptap】如何增加一个扩展项,为文字渲染颜色?

源码地址&#xff1a; https://github.com/Leecason/element-tiptap 可以看到&#xff0c;当前这个页面的文字&#xff0c;都是黑色的&#xff08;除了链接&#xff09; 酱紫有些单调&#xff0c;我喜欢五颜六色的。那么这篇文章就来看下菜单项里面如何增加一个颜色的扩展&…

Anaconda保姆安装教程

步骤1&#xff1a;下载Anaconda安装包 访问官网&#xff1a; 进入Anaconda官网下载页面&#xff0c;官网会根据电脑的操作系统自动选择适合的操作系统安装程序。 尝试进入清华大学开源软件镜像站&#xff0c;选择想要的版本进行下载&#xff0c;通常下载速度较快。 本文以从…

OpenAI重磅发布交互界面canvas,让ChatGPT成为写作和编程利器

OpenAI 宣布推出类似 Anthropic 的 Artifacts 的应用 canvas&#xff0c;并称「这是一种使用 ChatGPT 写作和编程的新方式」。 在 Claude 中试过 Artifacts 的朋友都知道&#xff0c;这能极大提升 LLM 输出结果的表现力&#xff0c;其支持输出文本文件、代码、网页、SVG 等等。…

Windows11 24H2 64位专业精简版:告别卡顿,流畅运行!

今日&#xff0c;系统之家小编给您分享2024年最新发布的Windows11 24H2精简版系统下载&#xff0c;该版本系统采用微软官方Windows11 24H2 26100.2033 专业版离线制作&#xff0c;安全无毒&#xff0c;不符合硬件要求的电脑也能升级。本次更新修复了系统蓝屏、绿屏的安全问题&a…

【赵渝强老师】K8s中的有状态控制器StatefulSet

在K8s中&#xff0c;StatefulSets将Pod部署成有状态的应用程序。通过使用StatefulSets控制器&#xff0c;可以为Pod提供持久存储和持久的唯一性标识符。StatefulSets控制器与Deployment控制器不同的是&#xff0c;StatefulSets控制器为管理的Pod维护了一个有粘性的标识符。无论…

数据科学初学者都应该知道的 15 个基本统计概念

一、介绍 数据科学的核心是统计学&#xff0c;它已经存在了几个世纪&#xff0c;但在当今的数字时代仍然至关重要。为什么&#xff1f;因为基本的统计概念是数据分析的支柱&#xff0c;使我们能够理解每天生成的大量数据。这就像与数据对话&#xff0c;统计学可以帮助我们提出正…

【读书笔记·VLSI电路设计方法解密】问题7:什么是基于标准单元的专用集成电路 (ASIC) 设计方法论

标准单元方法论是一种基于预组装库单元的芯片设计方法。该库中包含的标准单元和宏单元(例如存储器、I/O、特殊功能单元、锁相环(PLLs)等)已经在预定的工艺节点中设计、布局并经过验证。这些单元经过完全表征,并在逻辑、时序、物理和电气模型方面进行了定义,并正确地打包在…

npm install报错一堆sass gyp ERR!

执行npm install &#xff0c;出现一堆gyp含有sass错误的情况下。 解决办法&#xff1a; 首页可能是node版本问题&#xff0c;太高或者太低&#xff0c;也会导致npm install安装错误&#xff08;不会自动生成node_modules文件&#xff09;&#xff0c;本次试验&#xff0c;刚开…