米联客-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总结

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

相关推荐
周湘zx4 小时前
项目三:信号源的FPGA实现
fpga开发
9527华安5 小时前
FPGA多路MIPI转FPD-Link视频缩放拼接显示,基于IMX327+FPD953架构,提供2套工程源码和技术支持
fpga开发·架构·音视频
上理考研周导师5 小时前
【FPGA】ISE13.4操作手册,新建工程示例
fpga开发
技术小白爱FPGA8 小时前
Xilinx 平台 drp 动态调节 mmcm
fpga开发
北京太速科技股份有限公司11 小时前
太速科技-889-基于RFSOC XCZU49DR的 16T16R的软件无线电硬件
fpga开发
stm 学习ing12 小时前
HDLBits训练5
c语言·fpga开发·fpga·eda·hdlbits·pld·hdl语言
超能力MAX12 小时前
IIC驱动EEPROM
单片机·嵌入式硬件·fpga开发
吉大一菜鸡1 天前
FPGA学习(基于小梅哥Xilinx FPGA)学习笔记
笔记·学习·fpga开发
9527华安1 天前
FPGA实现MIPI转FPD-Link车载同轴视频传输方案,基于IMX327+FPD953架构,提供工程源码和技术支持
fpga开发·架构·mipi·imx327·fpd-link·fpd953