FPGA状态机设计思想

时间:2025-05-02  作者:Diven  阅读:0

01

FPGA状态机设计思想

状态机设计概述

硬件电路设计通常以并行方式实现,但是在实际工程中经常会存在系统按照顺序逻辑执行的需求。如果希望分多个时间步骤完成一个任务,同时减少使用大量使能信号衔接多个模块造成的麻烦,就需要引出状态机的概念。

状态机(State Machine)由输入、输出和状态三要素构成,输入是指一些引发状态变化的条件,输出是指状态改变后引起的变化,状态是指顺序逻辑执行的步骤,通常利用一些逻辑值进行表示。

以NAND FALSH控制过程的状态机为例,NAND FALSH操作通常需要按顺序依次执行擦除、坏块检测和读写操作:NAND FLASH在系统复位信号rst = 1后进入空闲状态IDLE;当指令使能信号i_cmd_en = 1且指令选择信号i_cmd_sel = h18时,NAND FLASH 进入擦除状态ERASE;当指令结束信号i_cmd_finish = 1时,NAND FLASH进入擦除状态读取状态......NAND FLASH根据不同的输入条件和当前状态实现状态跳转,通过在不同状态实现不同功能,完成NAND FLASH读写等操作。

状态机设计按照不同的标准分类:

1. 输出与输入是否相关:

Moore型状态机:输出只与状态相关,与输入无关;

Mealy型状态机:输出与状态和输入都相关。

2. 状态转移与输出是否依赖时钟信号:

同步状态机:状态转移和输出都发生在时钟沿;

异步状态机:状态转移和输出不依赖时钟信号,而是依赖于输入信号的变化。

3. 输出与状态是否相关:

顺序逻辑状态机:输出与输入和状态都相关,当前时刻的输出会影响下一个时刻的状态;

组合逻辑状态机:输出只与输入相关,与状态无关,当前时刻的输出不会影响下一个时刻的状态。

4. 状态数目是否有限:

有限状态机:状态数目是有限的,可以用状态转移图来表示状态和状态之间的转移关系;

无限状态机:状态数目是无限的,一般用差分方程或状态转移函数来表示状态转移关系。

在FPGA设计过程中,通常考虑的状态机是有限状态机(FSM, Finite State Machine)。FPGA有限状态机根据写法不同可以分为一段式、两段式和三段式,不同状态机写法在代码可读性和速度面积平衡性方面有所优劣,本文将以不同写法下状态机的Verilog代码为例,对三种状态机写法的效果进行对比分析。

02

一段式状态机设计分析

一段式状态机将状态机的三要素(输入、输出和状态)逻辑实现在同一个always内,示例代码如下:

`timescale 1ns / 1ps

//////////////////////////////////////////////////////////////////////////////////

// Company: Cascatrix

// Engineer: Carson

// 

// Create Date: 2023/07/16

// Design Name: FSM

// Module Name: FSM

// Tool Versions: v1.0

// Description: Finite State Machine 

//////////////////////////////////////////////////////////////////////////////////

Module FSM(

    clk,

    rst_n,

    condition1,

    condition2,

    result

    );

    input           clk;

    input           rst_n;

    input           condition1;

    input           condition2;

    output  [3:0]   result;

    wire            clk;

    wire            rst_n;

    wire            condition1;

    wire            condition2;

    reg     [3:0]   result;

    parameter IDLE = 1;

    parameter STATE_S11 = 2;

    parameter STATE_S12 = 3;

    parameter STATE_S21 = 4;

    parameter STATE_S22 = 4;

    reg [3:0] current_state;   

    always@(posedge clk or negedge rst_n)

    begin

        if(!rst_n)

        begin

            current_state <= IDLE;

            result <= 4'b0101;

        end

        else

        begin

            case(current_state)

            IDLE:

            begin

                if(condition1)

                begin

                    current_state <= STATE_S11;

                    result <= 4'b1110;

                end

                else if(condition2)

                begin

                    current_state <= STATE_S21;

                    result <= 4'b1111;

                end

                else

                begin

                    current_state <= IDLE;

                    result <= 4'b0101;

                end

            end

            STATE_S11:

            begin

                current_state <= STATE_S12;

                result <= 4'b0010;

            end

            STATE_S12:

            begin

                current_state <= IDLE;

                result <= 4'b0101;

            end

            STATE_S21:

            begin

                current_state <= STATE_S22;

                result <= 4'b1000;

            end

            STATE_S22:

            begin

                current_state <= IDLE;

                result <= 4'b0101;

            end

            default:current_state <= IDLE;

            endcase

        end

    end

endmodule

上述代码所实现的一段式状态机RTL视图如下: 

通过分析一段式状态机代码可以发现,状态current_state、输入condition1/2和输出result在同一个always内,整体而言代码编写较为简单。从代码可读性和可维护性的角度而言,一段式状态机的这种代码格式并不利于后期的阅读与维护,当状态机较为复杂时,一段式状态机更容易出现错误。

03

两段式状态机设计分析

两段式状态机将状态机的时序逻辑和组合逻辑划分为两个always,时序逻辑内进行当前状态和下一状态的切换,组合逻辑里实现各个输入、输出和状态的判断,示例代码如下:

`timescale 1ns / 1ps

//////////////////////////////////////////////////////////////////////////////////

// Company: Cascatrix

// Engineer: Carson

// 

// Create Date: 2023/07/16

// Design Name: FSM

// Module Name: FSM

// Tool Versions: v1.0

// Description: Finite State Machine 

//////////////////////////////////////////////////////////////////////////////////

module FSM(

    clk,

    rst_n,

    condition1,

    condition2,

    result

    );

    input           clk;

    input           rst_n;

    input           condition1;

    input           condition2;

    output  [3:0]   result;

    wire            clk;

    wire            rst_n;

    wire            condition1;

    wire            condition2;

    reg     [3:0]   result;

    parameter IDLE = 1;

    parameter STATE_S11 = 2;

    parameter STATE_S12 = 3;

    parameter STATE_S21 = 4;

    parameter STATE_S22 = 4;

    reg [3:0] next_state;   

    reg [3:0] current_state;   

    always@(posedge clk or negedge rst_n)

    begin

        if(!rst_n)

            current_state <= IDLE;

        else

            current_state <= next_state;

    end

    always@(current_state or condition1 or condition2)

    begin

        if(!rst_n)

        begin

            next_state = IDLE;

            result = 4'b0101;

        end

        else

        begin

            case(next_state)

            IDLE:

            begin

                if(condition1)

                begin

                    next_state = STATE_S11;

                    result = 4'b1110;

                end

                else if(condition2)

                begin

                    next_state = STATE_S21;

                    result = 4'b1111;

                end

                else

                begin

                    next_state = IDLE;

                    result = 4'b0101;

                end

            end

            STATE_S11:

            begin

                next_state = STATE_S12;

                result = 4'b0010;

            end

            STATE_S12:

            begin

                next_state = IDLE;

                result = 4'b0101;

            end

            STATE_S21:

            begin

                next_state = STATE_S22;

                result = 4'b1000;

            end

            STATE_S22:

            begin

                next_state = IDLE;

                result = 4'b0101;

            end

            default:next_state = IDLE;

            endcase

        end

    end

endmodule

上述代码所实现的两段式状态机RTL视图如下: 

相比于一段式状态机,两段式状态机通过划分组合逻辑和时序逻辑提高代码的可读性和可维护性,对组合逻辑内容更改即可提高。两段式状态机的组合逻辑输出在同一个模块中可能会出现竞争冒险,因此较为容易出现毛刺等问题。

04

三段式状态机设计分析

三段式状态机将两段式状态机组合逻辑的状态和输出划分为两部分,状态转换使用组合逻辑、逻辑输出使用时序逻辑,示例代码如下:

`timescale 1ns / 1ps

//////////////////////////////////////////////////////////////////////////////////

// Company: Cascatrix

// Engineer: Carson

// 

// Create Date: 2023/07/16

// Design Name: FSM

// Module Name: FSM

// Tool Versions: v1.0

// Description: Finite State Machine 

//////////////////////////////////////////////////////////////////////////////////

module FSM(

    clk,

    rst_n,

    condition1,

    condition2,

    result

    );

    input           clk;

    input           rst_n;

    input           condition1;

    input           condition2;

    output  [3:0]   result;

    wire            clk;

    wire            rst_n;

    wire            condition1;

    wire            condition2;

    reg     [3:0]   result;

    parameter IDLE = 1;

    parameter STATE_S11 = 2;

    parameter STATE_S12 = 3;

    parameter STATE_S21 = 4;

    parameter STATE_S22 = 4;

    reg [3:0] next_state;   

    reg [3:0] current_state;   

    always@(posedge clk or negedge rst_n)

    begin

        if(!rst_n)

            current_state <= IDLE;

        else

            current_state <= next_state;

    end

    always@(current_state or condition1 or condition2)

    begin

        case(current_state)

        IDLE:

        begin

            if(condition1)

                next_state = STATE_S11;

            else if(condition2)

                next_state = STATE_S21;

            else

                next_state = IDLE;

        end

        STATE_S11: next_state = STATE_S12;

        STATE_S12: next_state = IDLE;

        STATE_S21: next_state = STATE_S22;

        STATE_S22: next_state = IDLE;

        default:next_state = IDLE;

        endcase

    end

    always@(posedge clk or negedge rst_n)

    begin

        if(!rst_n)

            result <= 4'b0101;

        else

        case(current_state)

        IDLE:

        begin

            if(condition1)

                result <= 4'b1110;

            else if(condition2)

                result <= 4'b1111;

            else

                result <= 4'b0101;

        end

        STATE_S11: result <= 4'b0010;

        STATE_S12: result <= 4'b0101;

        STATE_S21: result <= 4'b1000;

        STATE_S22: result <= 4'b0101;

        default:result <= 4'b0101;

        endcase

    end

endmodule

上述代码所实现的三段式状态机RTL视图如下: 

三段式状态机通过时序逻辑解决了两段式写法中组合逻辑产生毛刺的问题,同时保证代码的可读性和可维护性。从资源消耗方面而言,相比于一段式和两段式状态机,三段式状态机会占用更多资源,同时从输入到输出会延迟一个时钟周期。

05

状态机设计

状态机三种写法可以如下:

一段式状态机:一个always块,既描述状态转移,又描述状态的输入输出,当前状态用寄存器输出;

二段式:两个always块,时序逻辑与组合逻辑分开,一个always块采用同步时序描述状态转移;另一个always块采用组合逻辑判断状态转移条件,描述状态转移规律以及输出,当前状态用组合逻辑输出,可能出现竞争冒险,产生毛刺,而且不利于约束,不利于综合器和布局布线器实现高性能的设计;

三段式:三个always块,一个always模块采用同步时序描述状态转移;一个always采用组合逻辑判断状态转移条件,描述状态转移规律;第三个always块使用同步时序描述状态输出,寄存器输出。

注:需要注意的是,状态机三种不同写法的本质区别是状态机三要素(状态、输入和输出)的逻辑功能,而非always块的数量。


审核编辑:刘清

猜您喜欢


压敏电阻作为重要的浪涌保护元件,应用于各种电子设备中。PHYCOM(飞元)作为国内知名的压敏电阻制造商,其产品以高品质和稳定性赢得了众多客户的认可。市面上关于P...
2016-08-31 04:52:24

现代科技中,超级电容器和锂离子电池都很重要。都能储存电能,但工作原理不同。本文将探讨的区别。工作原理超级电容器通过电双层存储电能。锂离子电池则通过化学反应释放能...
2025-03-28 03:31:39

刷子是常见的工具,应用于绘画、清洁、化妆等多个领域。其基本定义是由一根手柄和一束毛发或合成纤维构成的器具。刷子的主要功能是通过毛发的柔软性和弹性,将颜料、液体或...
2018-09-29 00:00:00

概述电子领域中,贴片电阻作为最常用的元件,其规格型号的多样性给设计与采购带来了挑战。为了统一标准,提高生产效率与兼容性,国家制定了一系列关于贴片电阻规格型号的标...
2025-04-14 14:09:22

Arduino MKR Vidor 4000的出现确实让我挺意外的,为何?因为它是一款FPGA开发板。众所周知,Arduino最深入人心的东西就是其简单的入门,...
2019-08-05 17:56:00

现代生活中,以太网无处不在,为我们的日常通信和信息传输提供了基础支持。而作为以太网技术的核心组成部分,电压标准在保证网络连接的稳定性与效率上是重要配件。本篇文章...
2024-08-15 00:00:00


NTC热敏电阻(Negative Temperature Coefficient Thermistor)是常用的温度传感器,其电阻值温度的升高而降低。由于其高灵...
2025-04-15 12:00:40

贴片电阻1203并非指某个具体阻值的电阻,而是指电阻的封装尺寸。1203代表的是英制尺寸,即长0.12英寸,宽0.03英寸。转换为公制,大约是3.05mm x ...
2024-11-29 10:26:09