为什么不在 VHDL 中使用双进程状态机?

问题描述 投票:0回答:4

当我学习如何用 VHDL 表达有限状态机时,它采用的是双进程架构。一个进程处理时钟/复位信号,另一个进程处理更新状态和输出的组合逻辑。下面是一个例子。

我见过这种风格受到批评(例如,参见评论和对这个问题的回答),但从未有过任何细节。我想知道这背后是否有客观原因。

是否存在避免这种风格的技术原因? Xilinx 的合成器似乎将其检测为状态机(您可以在输出中看到它,并验证转换),但其他人是否会为此苦苦挣扎,或者生成质量较差的实现?

这不是惯用的 VHDL 吗?记住避免基于意见的答案;如果不惯用,是否有广泛使用的使用不同风格的教学资源或参考资料?惯用风格也可以存在,因为,例如。有些错误通过正确的风格很容易发现,或者因为代码结构可以更好地表达问题域,或者因为其他原因。

(请注意,我并不是要求不同风格的定义或演示,我想知道是否有客观原因专门避免两进程实现。)

示例

一些示例可以在 Free Range VHDL (p89) 中找到。这是一个超级简单的例子:

library ieee;
use ieee.std_logic_1164.all;

-- Moore state machine that transitions from IDLE to WAITING, WAITING
-- to READY, and then READY back to WAITING each time the input is
-- detected as on.
entity fsm is
    port(
        clk    : in std_logic;
        rst    : in std_logic;
        input  : in std_logic;
        output : out std_logic
    );
end entity fsm;

architecture fsm_arc of fsm is
    type state is (idle, waiting, ready);
    signal prev_state, next_state : state;
begin
    -- Synchronous/reset process: update state on clock edge and handle
    -- reset action.
    sync_proc: process(clk, rst)
    begin
        if (rst = '1') then
            prev_state <= idle;
        elsif (rising_edge(clk)) then
            prev_state <= next_state;
        end if;
    end process sync_proc;

    -- Combinatorial process: compute next state and output.
    comb_proc: process(prev_state, input)
    begin
        case prev_state is
            when idle =>
                output <= '0';
                if input = '1' then
                    next_state <= waiting;
                else
                    next_state <= idle;
                end if; 
            when waiting =>
                output <= '1';
                if input = '1' then
                    next_state <= ready;
                else
                    next_state <= waiting;
                end if;
            when ready =>
                output <= '0';
                if input = '1' then
                    next_state <= waiting;
                else
                    next_state <= ready;
                end if;
        end case;
    end process comb_proc;
end fsm_arc;

(请注意,我现在无法访问合成器,因此其中可能存在一些错误。)

vhdl idioms fsm
4个回答
5
投票

我总是推荐单进程状态机,因为它避免了初学者非常常见的两类基本错误:

  1. 组合过程的敏感度列表中缺少项目会导致模拟行为异常。它甚至可以在实验室中使用,因为大多数合成器不关心灵敏度列表。
  2. 使用组合结果之一作为输入而不是注册版本,导致无时钟循环或只是长路径/跳过状态。

不太重要的是,组合过程降低了仿真效率。

不太客观,我发现它们更容易阅读和维护;它们需要更少的样板,而且我不必使敏感度列表与逻辑保持同步。


1
投票

我看到的唯一两个客观原因是摩尔状态机情况下的可读性和模拟效率(主要输出仅取决于当前状态,而不取决于主要输入)。

可读性:如果将单个流程输出和下一个状态计算合并在一起,则可能比针对单独关注点的单独组合流程更难以阅读/理解/维护。

模拟效率:在 2 过程解决方案中,您的组合过程将在每次主要输入和/或当前状态变化时触发。这对于计算下一个状态的过程部分有意义,但对于计算输出的部分则不然。后者仅应在当前状态发生变化时触发。


0
投票

参考文献中有对此的详细描述。 [1]如下。首先,FSM 被分为 3 类(第一次这样做),然后对每一类进行彻底检查,并提供许多完整的示例。您可以在第 107-115 页找到 1 类(常规)有限状态机问题的确切答案;第 185-190 页适用于 2 类(定时)机器;第 245-248 页介绍了 3 类(递归)状态机。 Moore 和 Mealy 版本的模板分别在三个类别中进行了详细描述。

[1] V. Pedroni,硬件中的有限状态机:理论与设计(使用 VHDL 和 SystemVerilog),麻省理工学院出版社,2013 年 12 月。


0
投票

我总是想知道为什么有人会使用流程。 并发语句总是更加简洁,并且通常会导致更好的综合。 例如,问题中提供的代码需要 58 行。 仅使用 37 行代码即可指定相同的电路,如下所示:

library ieee;
use ieee.std_logic_1164.all;

-- Moore state machine that transitions from IDLE to WAITING, WAITING
-- to READY, and then READY back to WAITING each time the input is
-- detected as on.
entity bad_fsm is
    port(
        clk    : in std_logic;
        rst    : in std_logic;
        input  : in std_logic;
        output : out std_logic
    );
end entity bad_fsm;

architecture fsm_good of bad_fsm is
    type state is (idle, waiting, ready);
    signal current_state, next_state_i, next_state : state;
    signal idle_next, waiting_next, ready_next : state;
begin
    -- Create flip-flops and and handle reset
    current_state <= next_state when rising_edge(clk);    
    next_state <= idle when rst = '1' else next_state_i;
    
    -- Next state logic
    with current_state select next_state_i <= 
        idle_next when idle,
        waiting_next when waiting,
        ready_next when others;

    idle_next <= waiting when input = '1' else idle;
    waiting_next <= ready when input = '1' else waiting;
    ready_next <= waiting when input = '1' else ready;
    
    -- Output logic
    output <= '1' when current_state = waiting else '0';
end fsm_good;
© www.soinside.com 2019 - 2024. All rights reserved.