一段式:将整个状态机写到1个always 模块里,在该模块中既描述状态转移,又描述状态的输入和输出。(always用时序逻辑也就非阻塞赋值)
解释:无须解释
特点:一段式描述方法不符合将时序和组合逻辑分开描述的 Coding Style(代码风格),而且代码冗长、不清晰,不利于附加约束,不利于综合器和布局布线器对设计的优化,所以不提倡用此方法。
二段式:核心思想是一个always 模块采用同步时序方式描述状态转移;另一个模块采用组合逻辑方式判断状态转移条件,描述状态转移规律和输入输出。(一个时序一个组合)
解释:时序逻辑里对CS复位及赋予NS的值,组合逻辑always里对NS赋值。
特点:虽然两段式FSM描述方法有很多好处,但是它有一个明显的弱点,就是其输出一般使用组合逻辑描述,而组合逻辑易产生毛刺等不稳定因素,并且在FPGA/CPLD等逻辑器件中过多的组合逻辑会影响实现的速率(这点与ASIC设计不同)。
三段式:第一个always模块同步时序方式描述状态转移(就是个简单的CS,NS,rst->CS),第二个always组合模块描述状态转移条件(case里边不停的if else if,用阻塞赋值方式,注意写成if(data)要比if(data==1'b1)简单很多),第三个always模块同步时序逻辑方式描述状态输出,万万注意,这里是case(NS)。(一个时序逻辑,一个组合逻辑,一个时序逻辑)
解释:个人一开始感觉三段式最不容易理解的就是时序输出模块case()里的NS了,不认真去想肯定是CS了啊,当前状态嘛,仔细查了资料后,发现确实应该是NS。原因是:第一个always和第三个always是时序模块,若第三个case里写CS,那么意味着:一个clk到来时,输出的是上一CS指示的输出,因为第一个always用的是非阻塞赋值,不是立即生效的。写成NS后,时钟沿到来后,CS被更新为现在NS所指示的状态,且同时状态输出调整为现在NS所指示的状态,如此,输出和状态的对应才是正确的。
特点:三段式描述方法与两段式描述相比,虽然代码结构复杂了一些,但是换来的却是使FSM做到了同步寄存器输出,消除了组合逻辑输出的不稳定性,而且更利于时序路径分组,一般来说,其在FPGA/CPLD 等可编程逻辑器件上的综合与布局布线效果更佳。