2

我在 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 ...

以替代方式进行操作的优点(如果有)和缺点是什么?我只在一个地方看到了替代方案,我猜这肯定有一些很好的理由。

4

4 回答 4

2

我喜欢将本地的东西保持在本地,所以如果只在进程中需要状态信息,我会使用一个变量。在这种情况下,我还想在进程中声明状态类型:

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

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

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

于 2013-09-17T06:54:20.833 回答
1

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

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

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

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

于 2013-09-15T20:50:21.690 回答
1

我经常使用一个variable叫做state. 它使定义隐藏,只对使用它的进程私有。如果您在一个进程中有 2 个正在通信的状态机,那么它们都可以有一个名为state本地的变量。有时效果很好。其他时候很混乱!

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

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

于 2013-09-16T12:29:22.060 回答
-1

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

  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 信号来“记住”状态以避免闩锁推断。

于 2014-07-31T12:57:55.087 回答