adxiaowei

状态机(FSM)verilog&vhdl

0
阅读(3641)


本人搜集网上资料详细整理如下:


      时序电路的状态是一个状态变量集合,这些状态变量在任意时刻的值都包含了为确定电路的未来行为而必需考虑的所有历史信息。

状态机:

      状态机分为两种、一种称为Mealy状态机,它的时序逻辑输出不但取决于状态还取决于输入;另外一种称为Moore,它的输出只取决于当前的状态。实际的设计工作中大部分都是Mealy状态机。 

     moore状态机其次态有现态和输入共同决定是他们的函数,其输出和输入没有关系,有现态唯一决定,也就是说一个现态有一个唯一的输出
     mealy状态机的次态和moore状态机一样有现态和输入共同决定,但是他的输出不但与现在有关还和输入有关,输出有现在和输入共同决定,是他们的函数。也就是说一个现态根据不同的输入会有不会的输出

      有限状态机设计一般步骤:1、逻辑抽象,得出状态转换图;2、状态化简;3、状态分配;4、选定触发器的类型并求出状态方程、驱动方程和输出方程;5、按照方程得出逻辑图。 
      FSM的描述方法有3中: 
          1、在1个always 模块里面,该模块中既描述状态转移,又描述状态的输入和输出,这种写法一般被称为一段式FSM 描述方法; 
          2、还有一种写法是将用2 个always 模块,其中一个always 模块采用同步时序描述状态转移;另一个模块采用组合逻辑判断状态转移条件,描述状态转移规律,这种写法被称为两段式FSM 描述方法;
 

          3、还有一种写法是在两段式描述方法基础上发展出来的,这种写法使用3 个always 模块,一个always模块采用同步时序描述状态转移;第二个采用组合逻辑判断状态转移条件,描述状态转移规律;第三个always模块使用同步时序电路描述每个状态的输出,这种写法本书称为三段式。 
        三种描述方式的优缺点比较如下表:




     状态机采用VerilogHDL语言编码,建议分为三个always段完成。

     三段式描述方法虽然代码结构复杂了一些,但是换来的优势是使FSM做到了同步寄存器输出,消除了组合逻辑输出的不稳定与毛刺的隐患,而且更利于时序路径分组,一般来说在FPGA/CPLD等可编程逻辑器件上的综合与布局布线效果更佳。

     三段式建模描述FSM的状态机输出时,只需指定case敏感表为次态寄存器, 然后直接在每个次态的case分支中描述该状态的输出即可,不用考虑状态转移条件。

    设计中的有限状态机(FSM),三段式状态机的第一块为同步时序always模块,格式化描述次态寄存器迁移到现态寄存器;第二部分为组合逻辑always模块,描述状态转移条件判断;第三部分为同步时序always模块,格式化描述次态寄存器输出。其中第二部分为组合逻辑,按照平时的习惯,为了抑制warning信息,对于always的敏感列表我都采用always@(*)的方式。

     


示列如下:

//第一个进程,同步时序always模块,格式化描述次态寄存器迁移到现态寄存器
always @ (posedge clk or negedge rst_n)   //异步复位
if(!rst_n)
current_state <= IDLE;
else
current_state <= next_state;         //注意,使用的是非阻塞赋值

//第二个进程,组合逻辑always模块,描述状态转移条件判断或者状态转移规律
always @ (*)          //电平触发
begin
next_state = x;        //要初始化,使得系统复位后能进入正确的状态
case(current_state)
S1: if(...)
next_state = S2;   //阻塞赋值
...
endcase
end

//第三个进程,同步时序always模块,格式化描述次态寄存器输出
always @ (posedge clk or negedge rst_n)
...//初始化
case(next_state)
S1:
out1 <= 1'b1;   //注意是非阻塞逻辑
S2:
out2 <= 1'b1;
default:...    //default的作用是免除综合工具综合出锁存器。
endcase
end

     三段式并不是一定要写为3个always块,如果状态机更复杂,就不止3段了。


    因此,三段式状态机中,需要注意的是第二部分case中的条件应该为当前态第三部分case中的条件应该为次态。因为第二段是组合逻辑,第三段是时序逻辑,时序逻辑比组合逻辑滞后,所以用次态提前。另外就是设计输入的时候一定要仔细。


尤其注意:
  1、第二段的always(组合部分,赋值用=)里面判断条件一定要包含所有情况!可以用else保证包含完全。
  2、第二段always中,组合逻辑电平要维持超过一个clock,仿真时注意。

三、总结

        三段式:状态切换用时序逻辑,次态输出用组合逻辑,信号输出用时序逻辑。信号输出的process中,case语句用next state做条件,可以解决比组合逻辑输出慢一拍的问题。
有时候判断次态需要用到计数器怎么办呢(计数器是时序电路,用组合逻辑是实现不了的)?方法是独立实现一个计数器,而在组合逻辑里用使能信号(或清除、置位等)来控制它。

欢迎大家来讨论。。。

--小伟--