当需要定义一个状态机时,首先要绘制一张状态图。状态图可用来显示状态、状态间的转换和状态机的输出。图1 显示了Moore 状态机的状态图(左)和Mealy 状态机的状态图(右)。

虽然有许多状态机是使用图1 所示的状态图方法进行设计的,但另外还有一种描述状态机行为的方法,这就是算法状态图法。ASM 图(图2)在外观上更加接近软件工程流程图。它由三个基本部分构成:
1. 状态框。它与状态名称有关,并包含Moore 状态输出列表。
2. 决策框。如果检验某条件为真,则进行下一状态的判断。
3. 条件输出框。让状态机根据当前状态和输入描述Mealy输出。

实现Moore 状态机还是Mealy 状态机,取决于状态机需要实现的功能,以及特定的反应次数要求。两种状态机之间的最大差别在于状态机如何对输入做出反应。在输入和设置的适当输出之间,Moore 状态机一般有一个时钟周期的延迟。这就意味着Moore 状态机无法对输入变化立即做出反应,这点在图3中可以清楚地看到。而Mealy 状态机则能够立即对输入做出反应,这通常意味着:实现相同的函数,Mealy 状态机比Moore状态机需要更少的状态。Mealy 状态机的不足之处就是在与另一个状态机进行通信时,如果输出出乎意料地严重依赖于其它事件的序列或时序,就可能会发生紊乱情况。
使用VHDL 这样的高级语言,可以轻松地直接从状态图实现状态机。VHDL 支持多种枚举类型,方便您定义实际的状态名称。举例如下:

• 可以避免组合过程中信号覆盖不完全造成的闭锁风险。
• 状态机的输出与时钟保持同步。
• 通常比双进程实现方案更容易调试。
状态机编码
状态变量存储在触发器中,使用下一时钟边缘上的下一状态进行更新(即使没有状态变化也是如此)。如何使用触发器来表示状态值具体取决于状态的数量和是否选择用某种特定的方法来管理综合工具。状态编码最常见的三种类型是:
• 顺序码——状态编码遵循传统的状态二进制序列。
• 格雷码——除了状态编码使用格雷码,且状态编码串之间只有一个位变化外,其它基本与顺序编码方法类似。
• 独热码——这种方法在状态机中为每一种状态分配一个触发器。只有一个触发器当前设置为高位,其余均设置为低位。故称为“独热”。
顺序编码和格雷编码都需要一定数量的触发器,可以通过下列等式来确定:
• 顺序:少于5 种状态。
• 独热:5-50 种状态。
• 格雷:多于50 种状态。
TYPE state IS(idle,led_on,led_off);
SIGNAL current_state:state:=idle;
ATTRIBUTE syn_encoding STRING;
ATTRIBUTE syn_encoding OF current_state:
SIGNAL IS “sequential”;
其中“sequential”也可以是“gray”和“onehot”。您还可以通过结合使用“safe”属性来确保在状态机进入非法状态时能够恢复到有效状态。
另外,您也可以使用syn_encoding 属性直接定义状态编码的值。例如,假设您想要使用下列状态编码法来对三态状态机进行编码:Idle = “11,” led_on = “10,” led_off = “01(与较传统的顺序“00”、“01”和“10”不同)。
前面给出的等式可确定状态机实现方案所需的触发器数量。由于不是所有的状态机都是2 的幂次方,因此某些状态在设计中将不会用到。实现状态机的工程师必须负责确保未使用的状态在设计中得到妥善处理。可以采用几种适用于多种设计的基本技巧来实现这一目标。对于高度可靠的安全关键型设计,则需要采用其它更高级的技巧。
不过对于大多数应用来说,只需要确保状态机能够妥善地处理未使用的状态并在进入非法状态时能够正确地恢复。要做到这一点有两种主要的方法。第一种方法是使用综合工具实现一个安全的状态机。综合工具通常会插入额外的逻辑,用于检测非法状态并将状态机返回到有效状态。第二种方法是加强对实现逻辑的控制,声明所有2 的幂次方状态机的状态,并使用另一属性来确保即便是在没有入口条件下,2 的幂次方状态机的状态也不会被优化掉。这意味着除非出错(单粒子翻转等),状态机内部的任何条件都不会进入状态。下面的代码显示了通过使用属性以防止清除未使用的状态。
SIGNAL IS “TURE”;
安全高效的状态机设计对于任何使用FPGA的工程师而言都是一项重要技能。选择Moore 状态机、Mealy状态机还是混合机取决于整个系统的需求。无论选择哪种类型的状态机,充分掌握实现方案所需的工具和技巧,将确保您实现最佳解决方案。