VHDL 2 进程状态机和输出初始化

VHDL 2 process state machine and output initialization

所以Altera提供了一个2进程状态机的例子a this link.

我有点喜欢这种风格,但我不明白的是,如果 'input' 保持在 '0',则永远不会触发第二个进程,因为状态永远不会改变,并且 'output'因此从未分配或初始化......或者是吗?

我的理解是,敏感度列表信号之一(本例中的 'state')需要进行转换,这在此处永远不会发生。

有人可以澄清一下这是怎么回事吗?

代码如下:

ENTITY state_machine IS
   PORT(
      clk      : IN   STD_LOGIC;
      input    : IN   STD_LOGIC;
      reset    : IN   STD_LOGIC;
      output   : OUT  STD_LOGIC_VECTOR(1 downto 0));
END state_machine;
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 s0=>
               IF input = '1' THEN
                  state <= s1;
               ELSE
                  state <= s0;
               END IF;
            WHEN s1=>
               IF input = '1' THEN
                  state <= s2;
               ELSE
                  state <= s1;
               END IF;
            WHEN s2=>
               IF input = '1' THEN
                  state <= s0;
               ELSE
                  state <= s2;
               END IF;
         END CASE;
      END IF;
   END PROCESS;

   PROCESS (state)
   BEGIN
      CASE state IS
         WHEN s0 =>
            output <= "00";
         WHEN s1 =>
            output <= "01";
         WHEN s2 =>
            output <= "10";
      END CASE;
   END PROCESS;

END a;

编辑: 澄清一下,我的问题是:在我看来 'output' 将处于未定义状态,直到 'input' 转换为“1”。考虑到这是 Altera 的官方示例,这不是不好的做法吗? 顺便说一下,在这里初始化 'output' 的正确方法是什么?使用异步重置 ?

...it looks to me that 'output' will be in a undefined state until 'input' transitions to '1'.

否(见下文)。在模拟开始时,output 将立即取值 "00",即使复位未断言并且 input.

上没有转换也是如此

Isn't that bad practice, considering this is an official example from Altera ?

不,这段代码没问题。由于重置,状态寄存器 (state) 可以正确初始化,并且 output 组合取决于 state。该模型在仿真和硬件中都将按预期运行。

And by the way, what would be the proper way of initializing 'output' here ? With async reset ?

您不使用重置来初始化组合的输出。复位(异步或同步)用于初始化寄存器(state,在您的示例中)。

敏感度列表只是语法糖。具有敏感列表的进程等效于相同的进程,没有敏感列表,并且具有 wait on <sensitivity-list>; 作为 last 语句。示例:

PROCESS (state)
BEGIN
  CASE state IS
     WHEN s0 =>
        output <= "00";
     WHEN s1 =>
        output <= "01";
     WHEN s2 =>
        output <= "10";
  END CASE;
END PROCESS;

相当于:

PROCESS
BEGIN
  CASE state IS
     WHEN s0 =>
        output <= "00";
     WHEN s1 =>
        output <= "01";
     WHEN s2 =>
        output <= "10";
  END CASE;
  WAIT ON state;
END PROCESS;

因此,这个进程(和所有进程一样)在模拟开始时被触发,并为 output 赋值。在您的特定情况下,此值将为 "00",因为 state 的初始值是其枚举类型的最左边的值,即 s0。总而言之,output 被初始化为 "UU"U 是枚举类型最左边的值 std_logic),并且在第一个模拟步骤之后(在 T=0 时) , 它取值 "00".

注意:这段代码很好,很好地代表了摩尔状态机的编码(不是 Mealy,正如其他答案所说:输出仅取决于当前状态)。但它有(至少)两个小问题:

  1. 它对单驱动信号使用std_logic解析类型,这不是一个好主意。 std_ulogicstd_ulogic_vector 会更好也更安全。
  2. 它使用名称 inputoutput,虽然不是语言的保留字,但应避免:它们是 std.textio 中定义的标准输入和输出流。