在 VHDL 中实现状态机的替代方法



我已经看到许多状态机从Altera中实现如下:

ARCHITECTURE a OF state_machine IS
   TYPE STATE_TYPE IS (s0, s1, s2);
   SIGNAL state   : STATE_TYPE;
BEGIN
   PROCESS (clk, reset)
   BEGIN
      IF reset = '1' THEN
         state <= s0;
      ELSIF (clk'EVENT AND clk = '1') THEN
      CASE state IS
     WHEN ...

与此不同的是:

ARCHITECTURE a OF state_machine IS
   TYPE STATE_TYPE IS (s0, s1, s2);
BEGIN
   PROCESS (clk, reset)
      VARIABLE state : STATE_TYPE := s0;
   BEGIN
      IF reset = '1' THEN
         state <= s0;
      ELSIF (clk'EVENT AND clk = '1') THEN
      CASE state IS
     WHEN ...

以替代方式进行此操作的利弊(如果有的话)是什么?我只在一个地方看到了替代方案,我猜一定有一些很好的理由。

我喜欢将本地内容保留在本地,因此如果仅在进程中需要状态信息,我会使用变量。在这种情况下,我还想在进程内声明状态类型:

ARCHITECTURE a OF state_machine IS
BEGIN
   PROCESS (clk, reset)
      TYPE STATE_TYPE IS (s0, s1, s2);
      VARIABLE state : STATE_TYPE := s0;
   BEGIN
      ...

在极少数情况下,我需要从另一个进程(例如交互式状态机)访问 FSM 的状态,我将使用信号来存储状态。

信号与可变决定,如果通常是品味问题。一些开发人员认为变量是邪恶的,永远不会使用它们。其他人(像我一样)尽可能使用它们来保持本地事物。作为奖励,由于变量是比信号更轻量级的对象,因此它们的模拟速度也更快。

使用变量来保持状态意味着您无法使用波形查看器查看状态。

零时间模型中用于分支、增量周期不匹配的信号输入可能存在一些同步问题。

任何从状态派生的状态机输出在任何事件中都需要信号 - 每个并发语句都有一个进程等效项,VHDL 模拟器执行进程,进程通过信号进行通信。

想到的唯一优点是它将是一个更紧凑的模型(代码大小)并且执行速度更快。

我经常使用一个名为statevariable。 它使定义保持隐藏,仅对使用它的进程私有。如果一个进程中有 2 个通信状态机,则它们都可以具有一个名为 state 的变量。 有时效果很好。 其他时候令人困惑!

与许多代码样式问题一样,您必须决定最易读的执行方式。 没有功能理由不使用变量(任何类型的变量,而不仅仅是状态变量)。

您可以使用变量执行的另一件事是在进程结束时读取预期的下一个状态,这在需要减少输出延迟时非常有用。 同样,需要小心,因为您可能会无意中创建长逻辑链,这可能会减慢设计速度。

如果要确定在同一时钟周期中进一步在过程中进一步使用的部分和或中间乘积,则变量非常有用。 但是,如果变量不是每个时钟周期都驱动,则将推断出锁存器。 由于您希望在下一个时钟周期内"记住"状态,因此如果您使用没有辅助寄存器信号的变量,您将获得锁存器。 澄清...

  signal state_sig : state_type;
begin
process(clk, rst)
  variable state : state_type := s0;
begin
  if rst = '1' then
    state_sig <= s0;
  elsif rising_edge(clk) then
    state := state_sig
    case state is 
     when s0 =>
      if blah = '0' then
       state := s1;
      end if;
     ....
     ....
    end case;
  if state = s1 then state := s2; end if;
  state_sig <= state;
 end if;
end process;

在上面的示例中,您可以通过在注册状态变量之前修改状态变量来避免进入状态 s1。 一种更改状态机行为的快速而肮脏的方法。 但是,state_sig信号必须用于"记住"状态以避免锁存推断。

最新更新