浅谈有限状态机FSM——以序列检测为例

2019-07-16 00:27发布

tica, sans-serif, 宋体">什么是状态机?简单来说,就是通过不同的状态迁移来完成一些特定的顺序逻辑。硬件的并行性决定了用Verilog描述的硬件实现(譬如不同的always语句)都是并行执行的,那么如果希望分多个时间完成一个任务,怎么办?也许可以用多个使能信号来衔接多个不同的模块,但这样做显得有些繁琐。状态机的提出大大简化这一工作。硬件设计很讲究并行设计思想,虽然用Verilog描述的电路大都是并行实现,但是对于实际工程应用,往往需要让硬件来实现一些具有一定顺序的工作,这就是要用到状态机的思想。(以上摘自特权同学的《深入浅出玩转FPGA》一书) 有限状态机FSM(Finite State Machine)是数字电路设计中的常用模块。组成元素:输入、状态、状态转移条件、输出分类:Mealy状态机:时序逻辑的输出不仅取决于当前状态,还与输入有关;Moore状态机:时序逻辑的输出只与当前状态有关;描述方式:1. 状态转移图:设计分析时使用,工具自动翻译的代码效率不高,适合规模小的设计;对于大规模设计,HDL更好;                    2. 状态转移表;                    3. HDL描述;设计步骤:1. 逻辑抽象,得到状态转移图:确定输入、输出、状态变量、画状态转移图;                    2.状态简化,得到最简的状态转移图:合并等价状态;                    3.状态编码:binary、gray、one-hot编码方式;                    4.用HDL描述;写法:一般有三种写法,他们在速度、面积、代码可维护性等各个方面互有优劣。      一段式:   只有一个always block,把所有的逻辑(输入、输出、状态)都在一个always block中实现;这种写法看起来很简洁,但是不利于维护。如果状态复杂一些就很容易出错。不推荐这种方法,但是在简单的状态机可以使用。       二段式:  有两个always block,把时序逻辑和组合逻辑分隔开来。时序逻辑里进行当前状态和下一状态的切换,组合逻辑实现各个输入、输出以及状态判断。这种写法不仅便于阅读、理解、维护,而且利于综合器优化代码,利于用户添加合适的时序约束条件,利于布局布线器实现设计。在两段式描述中,当前状态的输出用组合逻辑实现,可能存在竞争和冒险,产生毛刺。则要求对状态机的输出用寄存器打一拍,但很多情况不允许插入寄存器节拍,此时使用三段式描述。其优势在于能够根据状态转移规律,在上一状态根据输入条件判断出当前状态的输出,从而不需要额外插入时钟节拍。        三段式: 有三个always block,一个时序逻辑采用同步时序的方式描述状态转移,一个采用组合逻辑的方式判断状态转移条件、描述状态转移规律,第三个模块使用同步时序的方式描述每个状态的输出。代码容易维护,时序逻辑的输出解决了两段式组合逻辑的毛刺问题,但是从资源消耗的角度上看,三段式的资源消耗多一些,且输出比另外两种会延时一个时钟周期。应用:接口控制,协议转换和处理,以及处理器设计等等。我们以1101序列检测器为例:1101序列检测器Mealy状态机状态转移图
1101序列检测器Moore状态机状态转移图
我们以Mealy状态机为例一段式状态机(部分核心代码):
两段式状态机(部分核心代码):
三段式状态机(部分核心代码):
三种方式的状态机的写法,使用Quartus II的State Machine Viewer观察状态转移图都是:
Testbench:module ex3_tb;reg    clk;reg    rst_n;reg    in;wire   out;ex3 i_ex3(            .clk        (clk  ) ,            .rst_n      (rst_n) ,            .in         (in   ) ,            .out        (out  )          );                 initialbegin     clk = 1;     forever  #10 clk = ~clk;endinitialbegin     rst_n = 0;     in = 0;     #1000;     rst_n = 1;     in = 1;     #20;     in = 1;     #20;     in = 1;     #20;     in = 0;     #20;     in = 1;     #20;     in = 1;     #20;     in = 0;     #20;     in = 1;     #20;     in = 0;     #20;     in = 1;     #1000;     $stop;endendmoduleModelsim仿真结果:
有什么不对的地方欢迎大家批评指正!!!


采集

友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。