1、状态机最好用时序输出,这样时序性能好。在这种情况下:
(1)为了不延时,使用NextState做触发。
这样是保证了在输入改变后的上升沿,输出会反映输入的变化。
从输入改变到这一个上升沿这个过程是不可避免的,在做状态机时序设计的时候要考虑这一点。
(如果是组合输出的话,输入会立即反映到输出上来。但是,决定状态转移的输入还是会延迟到上升沿才起作用,这是因为State这个变量是时序的。如果State也做成组合的,那么就做成了一个异步状态机,异步状态机实现复杂)
总结一下:
在一个状态下,对一个时序输出,那么它能看到的输入是上一个时钟沿的输入;对一个组合输出,那么它能看到的输入是当前的输入。
(2)第一个状态(通常是Rst或者IDLE)在程序的开始是进入不进去的,导致信号初始值没法赋。这样就需要一个冗余的状态,用于让信号尽快进入原计划的第一个状态,否则信号初始值长时间不确定会比较危险。
2、case里面的default的处理。
在default里面,要将信号的值保持,而不要将所有信号都复位。因为下载到板子里之后,很多信号会有抖动,如果case没有覆盖所有二进制的可能时,很容易触发default。如果default是将所有信号复位的话,那么这个信号就变成0了。如果这个信号可以在后来自行回复自己的值,那么没有关系。但是很多信号都没有这个自动回复的功能。举例说明:
这个情况的影响对于状态机的第二个进程影响还不是很大,因为虽说default将NextState变为了IDLE(复位了),但是State并没有发生变化,所以NextState仍然可以回复到正常的值,并不影响整个状态机的运转。
但是这个情况对于第三个进程就影响很大了。因为这里面除了有一些output之外,还会有一些内部寄存器的信号。这些信号一般是在很多分支中要保持值不变,然后只有在少数情况下要改变的。这时,假如default触发了,那么这个值就复位了,直到下一次进入少数赋值情况时才会被改写为正确的值,这对于结果的影响就很大了。特别是,采用组合输出的时候,这种影响是致命的。
结论:
第二个进程中,要求default的情况下,将NextState置为IDLE
第三个进程如果是组合逻辑触发,要求default的情况下,在某些状态下有“输出保持不变”这种行为(也即A=A这种语句)的这种信号,要求将其值不变而不是复位。对于没有“输出保持不变”这种行为的信号,将其复位或者保持值不变都可以,有特殊要求的除外(比如说要求这个信号最多Assert一个周期,那么default就必须得复位,不能保持值不变)。
注:以上所说default是指“为了减少latch的default”,也即,没有明确功能的default。有明确功能的default中,当然是根据功能指其中信号的值了。
3、第三个进程(OutPut进程)最好要时序
某一个程序,功能仿真没错误,时序约束也都满足。但是最终执行结果不对。将输出改为时序后,一切正常。并且后仿真都通过了。看来输出进程为时序为最佳选择。
将组合输出改为时序输出必须注意时序的调整。时序输出会导致在该状态下“看到”(也就是读取的)的输入是上个时钟沿的,并不是最新的。
状态机
第二个进程:
决定NextState的值,进而下一个时钟沿,State也会变化。
对于用于判断State的信号:
若进程为时序的,那么用到的是它刚进入此状态(State == 某一个常量)那个时刻的值;通常,在没有违反时钟约束的情况下,也就是上一个时钟的最后一刻的值。
若进程为组合的,那么实际上其决定行作用的是,用到的是它进入状态后(State == 某一个常量)最后一刻的值。
第三个进程:
对于用于判断和输出的信号:
若进程为时序的,那么用到的是它刚进入此状态那个时刻的值;通常,在没有违反时钟约束的情况下,也就是上一个时钟的最后一刻的值;
若进程为组合的,那么用到的是它进入状态后最后一刻的值。
从时序图提炼状态机:
关键是找好状态。
l 先从逻辑上大致分一下状态。
l 根据输入的不同分不同情况,做时序图。
l 看看不同情况下的输出是否都能用这一个状态来概括,不可以再添加子状态或者在同一个状态中使用信号进行区分。
安全状态机:
1、状态转移时,要能够在有限的步骤内转移到IDLE
(1)State要有Default,Default中转移到IDLE,防止State信号出错
(2)在某一个状态中,其转移到其他状态的条件
本文探讨了状态机设计的一些关键点,包括时序输出的重要性、case语句中default的处理以及输出进程应为时序。强调了在default中保持信号值不变的策略,以及如何避免信号抖动对状态机的影响。同时,提到了状态机的安全状态转移策略,确保能够有限步数内回到IDLE状态。

3万+

被折叠的 条评论
为什么被折叠?



