热度 27
2014-9-1 23:37
9875 次阅读|
1 个评论
什么是状态机? 简单来说,就是通过不同的状态迁移来完成一些特定的顺序逻辑。硬件的并行性决定了用 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 ) ); initial begin clk = 1; forever #10 clk = ~clk; end initial begin 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; end endmodule Modelsim 仿真结果: 有什么不对的地方欢迎大家批评指正!!!