FPGA状态机设计思想

可编程逻辑

1365人已加入

描述

01

状态机设计概述

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

状态机(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读写等操作。

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视图如下: 

Nand flash

通过分析一段式状态机代码可以发现,状态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视图如下: 

Nand flash

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

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视图如下: 

Nand flash

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

05

状态机设计总结

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

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

Nand flash

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

Nand flash

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

Nand flash

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

Nand flash






审核编辑:刘清

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分