HDLbits答案更新系列11(3.2 Sequential Logic 3.2.5 Finite State Machines 3.2.5.1 Simple FSM 1等)

本文深入解析状态机设计,包括两段式与三段式状态机的异同,通过具体实例对比异步复位与同步复位的状态机实现,强调电路设计角度下的最佳实践。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

前言

3.2.5 Finite State Machines

3.2.5.1 Simple FSM 1(asynchronous reset)

3.2.5.2 Simple FSM 1(synchronous reset)

3.2.5.3 Simple FSM 2(asynchronous reset)

3.2.5.4 Simple FSM 2(synchronous reset)

结语

HDLbits网站链接


前言

今天终于来到了数字IC设计的另一个重要部分:状态机。对于这部分内容,我可能不会一次更新一个小节,一是因为代码量,二是因为状态机这个小节内容太多了,博主在完成这部分内容时也不是每道题目都很容易就解决了,有几道题目需要深入讲解,所以更新会慢一些,还请大家见谅。当然如果大家有不同的解法,欢迎大家留言~

3.2.5 Finite State Machines

3.2.5.1 Simple FSM 1(asynchronous reset)

module top_module(
    input clk,
    input areset,    // Asynchronous reset to state B
    input in,
    output reg out);//  

    parameter A=1'b0, B=1'b1; 
    reg current_state, next_state;
    
    always@(posedge clk or posedge areset)begin
        if(areset)begin
            current_state <= B;
        end
        else begin
            current_state <= next_state;
        end
    end

    always@(*)begin
        case(current_state)
            B:begin
                if(in == 1'b1)begin
                    next_state = B;
                end
                else begin
                    next_state = A;
                end
            end
            A:begin
                if(in == 1'b1)begin
                    next_state = A;
                end
                else begin
                    next_state = B;
                end
            end
        endcase
    end
    
    //combinational logic way
    always@(*)begin 
        if(current_state == B)begin
            out = 1'b1;
        end
        else begin
            out = 1'b0;
        end
    end
    
    /*
    //second way
    //assign out = (current_state == B);
    */
    
    /*
    //third way
    always@(*)begin
        case(current_state)
            B:begin
                out = 1'b1;
            end
            A:begin
                out = 1'b0;
            end
        endcase
    end
    */    
    
    /*
    //forth way
    //sequential logic way
    always@(posedge clk or posedge areset)begin
        if(areset)begin
            out <= 1'b1;
        end
        else if(next_state == B)begin
            out <= 1'b1;
        end
        else begin
            out <= 1'b0;
        end
    end
    */
    
endmodule

第一题根据状态转移图写代码,这道题目博主给出了四种输出写法,前三种是用组合逻辑输出,最后一种是用时序逻辑输出。注意这道题目时序逻辑复位时的out是状态B。

这里大家一定要明白,虽然从代码结构上来说,这四种方式都可以算作三段式状态机,但是从电路设计的角度来说,只有第四种算是三段式状态机。

两段式状态机的第一个进程是格式化描述次态到现态的转移(即current_state <= next_state),第二个进程是纯组合逻辑描述状态转移条件(即case(current_state)),最后使用组合逻辑对current_state进行判断得到输出结果。

三段式状态机的第一个进程是格式化描述次态到现态的转移(即current_state <= next_state),第二个进程是纯组合逻辑描述状态转移条件(即case(current_state)),第三个进程是使用时序逻辑得到输出结果,注意这里判断的是next_state。

两段式状态机代码简单直观,但是组合逻辑易产生毛刺等不稳定因素,如果电路能够允许一个多余的时序节拍,那么两段式状态机采用寄存器输出是很好的。三段式状态机采用寄存器输出,可以避免毛刺,改善时序条件,但是三段式状态机分割了两部分组合逻辑(状态转移条件组合逻辑和输出组合逻辑),因此这条路径的时序相对紧张。博主个人还是建议大家使用三段式状态机。由于两段式状态机更为简洁,博主为了快速完成题目,后面的题目也使用了较多的两段式状态机,实际应用中还是用三段式多一些。

总之,这两种写法都是博主建议的写法。

3.2.5.2 Simple FSM 1(synchronous reset)

// Note the Verilog-1995 module declaration syntax here:
module top_module(clk, reset, in, out);
    input clk;
    input reset;    // Synchronous reset to state B
    input in;
    output out;//  
    reg out;

    parameter A = 1'b0;
    parameter B = 1'b1;

    reg current_state, next_state;
    
    always@(posedge clk)begin
        if(reset)begin
            current_state <= B;
        end
        else begin
            current_state <= next_state;
        end
    end
    
    always@(*)begin
        case(current_state)
            B:begin
                if(in == 1'b1)begin
                    next_state = B;
                end
                else begin
                    next_state = A;
                end
            end
            A:begin
                if(in == 1'b1)begin
                    next_state = A;
                end
                else begin
                    next_state = B;
                end
            end
        endcase
    end
    
    always@(*)begin
        if(current_state == B)begin
            out = 1'b1;
        end
        else begin
            out = 1'b0;
        end
    end


endmodule

这道题目和第一道题目差不多,只是复位换成了同步复位。

3.2.5.3 Simple FSM 2(asynchronous reset)

module top_module(
    input clk,
    input areset,    // Asynchronous reset to OFF
    input j,
    input k,
    output out); //  

    parameter OFF = 1'b0, ON = 1'b1; 
    reg current_state, next_state;

    always@(posedge clk or posedge areset)begin
        if(areset)begin
            current_state <= OFF;
        end
        else begin
            current_state <= next_state;
        end
    end
    
    always@(*)begin
        case(current_state)
            OFF:begin
                if(j == 1'b1)begin
                    next_state = ON;
                end
                else begin
                    next_state = OFF;
                end
            end
            ON:begin
                if(k == 1'b1)begin
                    next_state = OFF;
                end
                else begin
                    next_state = ON;
                end
            end
        endcase
    end
    
    always@(*)begin
        if(current_state == ON)begin
            out = 1'b1;
        end
        else begin
            out = 1'b0;
        end
    end            

endmodule

这道题目有相比前两道题目多了一个输入,其他没有太多差别。

3.2.5.4 Simple FSM 2(synchronous reset)

module top_module(
    input clk,
    input reset,    // Synchronous reset to OFF
    input j,
    input k,
    output out); //  

    parameter OFF = 1'b0, ON = 1'b1; 
    reg current_state, next_state;

    always@(posedge clk)begin
        if(reset)begin
            current_state <= OFF;
        end
        else begin
            current_state <= next_state;
        end
    end
    
    always@(*)begin
        case(current_state)
            OFF:begin
                if(j == 1'b1)begin
                    next_state = ON;
                end
                else begin
                    next_state = OFF;
                end
            end
            ON:begin
                if(k == 1'b1)begin
                    next_state = OFF;
                end
                else begin
                    next_state = ON;
                end
            end
        endcase
    end
    
    always@(*)begin
        if(current_state == ON)begin
            out = 1'b1;
        end
        else begin
            out = 1'b0;
        end
    end

endmodule

这道题目相比上一道题目,异步复位变成了同步复位,别的没什么区别。

结语

今天先更新这四道题目,这四道题目是最基础的状态机题目,没有什么特别大的难度,重点是清楚两段式状态机和三段式状态机的异同点,仅从结构考虑(广义上),博主在题目3.2.5.1中的四种写法都属于三段式状态机,但是从电路设计的角度来说,只有第四种写法属于三段式状态机,希望大家能够弄清楚这一点。

如果代码有错误的地方希望大家可以提醒我,我一定尽快改正。

HDLbits网站链接

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

`nn.Sequential` 是 PyTorch 中的一个模块,它用于组合多个神经网络层,使得模型构建更加简洁明了。通常,当你想要按照特定顺序应用一系列层时,如线性层(Linear)、激活函数(ReLU)等,可以使用 Sequential 来组织。 然而,`nn.functional` 模块提供了独立于任何 Module 的函数式接口,这些函数可以直接作用于张量,不需要创建一个新的 Layer 对象。例如,`nn.functional.relu()` 可以直接对输入张量应用 ReLU 激活,而不需要先创建一个 `nn.ReLU` 类实例并调用它的 forward 方法。 两者不能直接结合使用的原因在于它们的设计目的不同。`nn.Sequential` 是为了方便管理模型结构和参数,适合构建完整的网络层级;而 `nn.functional` 提供的是底层操作,更灵活但需要手动管理内存和维度变化。 如果你需要在 Sequential 中使用某个来自 nn.functional 的操作,你可以在相应的 Sequential 层后面添加一个 `.apply()` 或 `.forward()` 方法,传入一个函数来实现。例如: ```python from torch import nn from torch.nn import functional as F model = nn.Sequential( nn.Linear(10, 64), lambda x: F.relu(x), # 使用 nn.functional.relu 直接在 Sequential 中 nn.Linear(64, 10) ) # 或者这样使用 .apply() model.apply(lambda module: F.relu(module)) if isinstance(model, nn.Sequential) else model ``` 这里我们通过匿名函数 `lambda x: F.relu(x)` 或 `.apply()` 把 `relu` 函数应用到 `nn.Linear` 后的输出上。但请注意,这种方式并不常见,因为通常会倾向于保持 Sequential 的一致性,如果可能的话,还是推荐使用 `nn.ReLU` 类作为子层。
评论 14
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值