米联客-FPGA程序设计Verilog语法入门篇连载-24 FPGA知识_认识FPGA中的状态机

软件版本:无

操作系统:WIN10 64bit

硬件平台:适用所有系列FPGA

板卡获取平台:https://milianke.tmall.com/

登录"米联客"FPGA社区 http://www.uisrc.com 视频课程、答疑解惑!

1概述

让FPGA电路,有序执行任务,我们需要状态机电路。所有的时序电路都是随着时间的流逝发生各种状态,在FPGA中,基于时序编写状态机,可以完成几乎所有的逻辑控制任务。状态机就是用来管理电路的逻辑状态。如果你学习过C语言,你可能主要用switch case进行条件判断,但是学习了FPGA的状态机后,你可以考虑下改进下你的C语言设计,利用C语言的switch case来实现状态机,对于很多基于时间的逻辑类控制,状态机是非常好的管理方案,适合于一切的编程。

状态机的描述通常有三种方:一段式状态机、二段式状态机、三段式状态机,当然你可以写出四段式,五段式,但是一般来说,常用的不超过三段式。如果选用是一段、二段还是三段根据实际情况,一般原则,很简单的状态机一段式搞定,稍微复杂的用二段式,很复杂的用三段式。大部分情况我们都是面对的简单的状态机。

2一段式状态机

cpp 复制代码
module detect_1(

    input clk_i,

    input rst_n_i,

    output out_o

    );



reg out_r;

//状态声明和状态编码

reg [1:0] state;

parameter [1:0] S0=2'b00;

parameter [1:0] S1=2'b01;

parameter [1:0] S2=2'b10;

parameter [1:0] S3=2'b11;



always@(posedge clk_i)

begin

    if(!rst_n_i)begin

        state<=0;

       out_r<=1'b0;

    end

    else 

        case(state)

            S0 :

            begin

               out_r<=1'b0;

               state<= S1;

            end

            S1 :

            begin

                out_r<=1'b1;

                state<= S2;

            end 

            S2 :

            begin

                 out_r<=1'b0;

                 state<= S3;

            end

            S3 :

            begin

                 out_r<=1'b1;

            end

        endcase

end

assign out_o=out_r;

endmodule

通常来说一段式状态机是不推荐使用的,但是实际情况是对于简单的代码没必要严格去比较采用一段式或者二段式状态机,而且一段式的状态机,写起来比较顺手,所以规模不大的简单状态机放心用吧。

3两段式状态机

cpp 复制代码
module detect_2(

     input clk_i,

     input rst_n_i,

     output out_o

);

    reg out_r;

    //状态声明和状态编码

    reg [1:0] Current_state;

    reg [1:0] Next_state;

    parameter [1:0] S0=2'b00;

    parameter [1:0] S1=2'b01;

    parameter [1:0] S2=2'b10;

    parameter [1:0] S3=2'b11;

   

    //时序逻辑:描述状态转换

    always@(posedge clk_i)

    begin

        if(!rst_n_i)

           Current_state<=0;

        else

            Current_state<=Next_state;

    end

   

    //组合逻辑:描述下一状态和输出

    always@(*)

    begin

        case(Current_state)

            S0 :

                begin

                 out_r=1'b0;

                 Next_state= S1;

                end

            S1 :

                begin

                 out_r=1'b1;

                 Next_state= S2;

                end

            S2 :

                begin

                 out_r=1'b0;

                 Next_state= S3;

                end

            S3 :

                 begin

                 out_r=1'b1;

                 Next_state=Next_state;

                 end

            endcase

    end

    assign out_o=out_r;    

endmodule

两段式状态机采用两个always模块实现状态机的功能,其中一个always采用同步时序逻辑描述状态转移,另一个always采用组合逻辑来判断状态条件转移。虽然对于简单的代码我们没必要去比较一段式好还是两段式好,但是如果推荐肯定还是使用两段式的状态机,不过很多时候笔者也偷懒,使用一段式的状态机。但是如果对于时序要求和状态机机有一定的规模的电路,还是用两段式的吧。

代码翻译的电路原理图:

总之两段式状态机是推荐的状态机设计方法。

4三段式状态机

cpp 复制代码
module detect_3(

        input clk_i,

        input rst_n_i,

        output out_o

        );

    reg out_r;

    //状态声明和状态编码

    reg [1:0] Current_state;

    reg [1:0] Next_state;

    parameter [1:0] S0=2'b00;

    parameter [1:0] S1=2'b01;

    parameter [1:0] S2=2'b10;

    parameter [1:0] S3=2'b11;

   

    //时序逻辑:描述状态转换

    always@(posedge clk_i)

    begin

        if(!rst_n_i)

            Current_state<=0;

        else

            Current_state<=Next_state;

    end

   

    //组合逻辑:描述下一状态

    always@(*)

    begin

        case(Current_state)

            S0:

                Next_state = S1;

            S1:

                Next_state = S2;

            S2:

                Next_state = S3;

            S3:

                Next_state = Next_state;

         default :

            Next_state = S0;

          endcase

    end

    //输出逻辑:让输出out,经过寄存器out_r锁存后输出,消除毛刺

    always@(*)

    begin

        case(Current_state)

               S0,S2:

                   out_r<=1'b0;

               S1,S3:

                   out_r<=1'b1;

           default :

              out_r<=out_r;

            endcase

    end    assign out_o=out_r;    

三段式状态机在第一个always模块采用同步时序逻辑方式描述状态转移,第二个always模块采用组合逻辑方式描述状态转移规律,第三个always描述电路的输出。通常让输出信号经过寄存器缓存之后再输出,消除电路毛刺。这种状态机也是比较推崇的,主要是由于维护方便,组合逻辑与时序逻辑完全独立。

代码翻译的电路原理图:

5总结

通过对比三种状态机的写法,可以发现,三段式的状态机翻译出来的原理图是最简洁最高效的编写方式,两段式也是很简洁的,但是比三段式差了一点点,而一段式是最差的表现。所以推荐是使用两段式以上的状态机。

相关推荐
武汉凯迪正大电气4 小时前
武汉凯迪正大—变压器空负载特性参数测试仪 变压器容量及损耗参数测试仪
fpga开发
IM_DALLA4 小时前
【Verilog学习日常】—牛客网刷题—Verilog快速入门—VL16
学习·fpga开发
IM_DALLA4 小时前
【Verilog学习日常】—牛客网刷题—Verilog快速入门—VL18
学习·fpga开发
芯冰乐4 小时前
综合时如何计算net delay?
后端·fpga开发
落雨无风6 小时前
quartus pin 分配(三)
fpga开发
cycf10 小时前
深入浅出通信原理
fpga开发·信息与通信
IM_DALLA1 天前
【Verilog学习日常】—牛客网刷题—Verilog快速入门—VL21
学习·fpga开发
皇华ameya1 天前
AMEYA360:村田电子更适合薄型设计应用场景的3.3V输入、12A输出的DCDC转换IC
fpga开发
千穹凌帝1 天前
SpinalHDL之结构(二)
开发语言·前端·fpga开发
一口一口吃成大V2 天前
FPGA随记——FPGA时序优化小经验
fpga开发