什么是状态机?简单来说,就是通过不同的状态迁移来完成一些特定的顺序逻辑。硬件的并行性决定了用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仿真结果:
有什么不对的地方欢迎大家批评指正!!!
用户1716124 2015-8-4 17:42