FPGA状态机电路综合分析
0赞
在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会用较多的资源。