请选择 进入手机版 | 继续访问电脑版

fpga论坛|fpga设计论坛

 找回密码
 我要注册

QQ登录

只需一步,快速开始

搜索
查看: 106|回复: 3

FPGA状态机电路综合分析

[复制链接]
月影星痕 发表于 2019-8-15 10:11:17 | 显示全部楼层 |阅读模式
在FPGA中,状态机是比较常用的。特别是要处理一些串行执行的操作。但是对于我们编写的状态机,综合出来的电路应该是长什么样子的了?这个在初学的时候都是不关心的,但是深入的话,还是要了解的。
           状态机分为两种,一种是moore型,一种是mealy型。两种的区别就是输出逻辑是否会由输入决定。
           如下图:
           状态机分为三部分模块
第一部分为次态组合逻辑电路,通过将状态输出反馈到次态组合逻辑电路,在和输入信号决定,下一状态是什么状态。
           第二部分就是时序电路,就是一个触发器,将下一状态的值给现在的状态
           第三部分是输出逻辑,通过判断当前的状态,得到输出


  
           在写状态机代码,有三种方式。就是书上说的一段式,二段式,三段式。把3个模块都写在一个always中,就是一段式。将前面两个模块写在一个always中,就是二段式。三个模块分为三个always中写,就是三段式。推荐是使用三段式。这样,逻辑清楚,也便于综合器综合。

  
           考虑以下简单的状态机代码。
      
module led(
    input                   clk,
    input                   rst_n,
    input                   change,
    output  reg [3:0]       led

    );
    localparam   led_0001    = 'd0;
    localparam  led_0010   = 'd1;
    localparam   led_0100    = 'd2;
    localparam   led_1000    = 'd3;
    reg [1:0]   state;
    always@(posedge clk or negedge rst_n) begin

        if(!rst_n)

            state <= led_0001;

        else

            case(state)

            led_0001:

                if(change)

                    state <= led_0010;

            led_0010:

                if(change)

                    state <= led_0100;

            led_0100:

                if(change)

                    state <= led_1000;

            led_1000:

                if(change)

                    state <= led_0001;

        endcase

    end

   
    `define use_case

    `ifdef use_case

    always@* begin

        case(state)

            led_0001:   led = 4'b0001;

            led_0010:   led = 4'b0010;

            led_0100:   led = 4'b0100;

            led_1000:   led = 4'b1000;

        endcase

        end

        `else

        always@* begin

            if(state == led_0001)

                led = 4'b0001;

            else if(state == led_0010)

                led = 4'b0010;

            else if(state == led_0100)

                led = 4'b0100;

            else

                led = 4'b1000;

        end

        `endif

endmodule

功能其实很简单,有4个状态,按照普通二进制编码。每个状态在输入信号change有效的时候状态跳转。在每个状态,4个LED输出是不一样的。
在代码中,使用了预编译`ifdef。这里输出逻辑采用if和case来实现,比较看看综合出来的电路区别。

  
首先是使用case综合。查看综合报告。

综合对代码进行分析,推断出有有一个有限状态机,位数是2,状态是4。还推断出时钟是上升沿,复位是异步低有效。看出,综合器还是比较厉害的。

综合器对状态机的编码进行优化,代码中用的是自然二进制,综合器优化成格雷码。

之后,还得到了用的资源情况。总共使用7个LUT,2个触发器。一个时钟buffer,I/O BUFFER用了6个。
之后是一些时序相关的信息,这里不关心时序。

  
看看综合出来的电路。这个时候要看Technology电路。这个电路才是用LUT和触发器构成的。

这就是综合出来的电路图。用LUT和触发器实现。
电路第一部分就是次态产生组合逻辑电路。第二部分就是时序逻辑,第三部分就是输出组合逻辑电路。
这里,时序逻辑的FFd1是状态的高位,FFd2是状态的低位。
看第一部分的最上面的LU3,这个产生状态机的高位的下一状态。

看看这个逻辑电路的真值表。I2是状态机的高位,I1是状态机的低位,I0是输入change信号。这里分析真值表的前两个。在状态在00的时候,不论输入change信号是什么,状态的高位是不会变化的。因为这一状态和下一状态的高位都是0。下面的真值表可以自己分析下。
这样,就得到状态的高位的次态产生组合逻辑电路。同理,在把状态的其他位的次态产生组合逻辑电路在实现即可了。组合逻辑电路都是使用LUT来实现。因为FPGA的基本结构就是LUT。
第二部分就是将次态传递给现态。
第三部分就是输出逻辑了。根据现态,得到输出的值。看第一个LUT2.

I1是状态的高位,I0是状态的低位。当状态为00的时候,输出为1。和代码中写的一样。
这样下来,是不是对状态机的电路综合要明白很多了了。状态机的关键就是第一部分电路,怎么得到下一状态。上面写的代码是比较简单的,所以第一部分电路是比较简单,当写复杂后,这部分电路就复杂了。
在来看看使用if实现区别。

上图是综合出来的电路图,看出和case是一样的。如果去看LUT的真值表的话,发现真值表都是一样的。说明,使用case和if综合出来的电路是一样的。这,怎么可能了?书上说,这两个综合出来的电路应该是不一样的,if是有优先级的。如果是用逻辑门来搭的话,电路是不一样的,但是使用LUT可就不是这样的了,而是两个的电路是一样的了。当然前提是两个电路的功能是一样的。对于同样的输入,输出是一样的。
对于LUT,会预先计算电路的输出,然后填入到LUT中,这样,不管你是用if还是case来写的代码,输出值都是一样,填入到LUT的值也是一样的。但是对于用门电路的话,这就不一样了,if会用较少的资源,而case会用较多的资源。
Sunlife 发表于 2019-8-15 14:28:42 | 显示全部楼层
                       
hellokity 发表于 2019-8-18 13:42:37 | 显示全部楼层
在FPGA中,状态机是比较常用的。特别是要处理一些串行执行的操作。
zxopenljx 发表于 2019-10-9 15:13:18 | 显示全部楼层
FPGA状态机电路综合分析
您需要登录后才可以回帖 登录 | 我要注册

本版积分规则

QQ|小黑屋|手机版|Archiver|FPGA论坛 ( 京ICP备10035964号  

GMT+8, 2019-10-18 16:29 , Processed in 0.090448 second(s), 22 queries .

至芯科技 Powered by Discuz X3.2

© 2001-2014 Comsenz Inc.

快速回复 返回顶部 返回列表