VHDL状态机差异(用于合成)

VHDL状态机差异(用于合成),vhdl,state-machine,Vhdl,State Machine,我正在上一堂嵌入式系统设计课,我的一个同学,上了另一门课,声称另一门课的讲师不会让他们实现这样的状态机: architecture behavioral of sm is type state_t is (s1, s2, s3); signal state : state_t; begin oneproc: process(Rst, Clk) begin if (Rst = '1') then -- Reset

我正在上一堂嵌入式系统设计课,我的一个同学,上了另一门课,声称另一门课的讲师不会让他们实现这样的状态机:

architecture behavioral of sm is
    type state_t is (s1, s2, s3);
    signal state : state_t;
begin
    oneproc: process(Rst, Clk)
    begin
        if (Rst = '1') then
            -- Reset
        elsif (rising_edge(Clk)) then
            case state is
                when s1 =>
                    if (input = '1') then
                        state <= s2;
                    else
                        state <= s1;
                    end if;
                    ...
                    ...
                    ...

            end case;
        end if;
    end process;
end architecture;
architecture behavioral of sm is
    type state_t is (s1, s2, s3);
    signal state, next_state : state_t;
begin
    syncproc: process(Rst, Clk)
    begin
        if (Rst = '1') then
            --Reset
        elsif (rising_edge(Clk)) then
            state   <= next_state;
        end if;
    end process;

    combproc: process(state)
    begin
        case state is
            when s1 =>
                if (input = '1') then
                    next_state <= s2;
                else
                    next_state <= s1;
                end if;
                ...
                ...
                ...

        end case;
    end process;
end architecture;
sm的架构行为是
类型状态为(s1、s2、s3);
信号状态:状态t;
开始
oneproc:进程(Rst、Clk)
开始
如果(Rst='1'),则
--重置
elsif(上升沿(Clk))然后
案例状态为
当s1=>
如果(输入='1'),则

状态单一工艺形式更简单、更短。这本身就降低了它包含错误的可能性

然而,它还消除了困扰另一方组合过程的“不完整敏感度列表”问题,这一事实应使其成为明确的赢家,而不考虑任何其他因素

然而,有如此多的文本和教程建议相反,没有正确地证明该建议的合理性,或者(至少在一种情况下,我找不到atm)在单一流程表单中引入愚蠢的错误,并以该错误为理由拒绝整个想法

唯一一件(AFAIK)单一进程表单做得不好的事情是输出不计时。这些都是(IMO)糟糕的实践,因为它们在最好的时候可能是比赛,只有在你真的不得不这样做的情况下,才可以通过一个单独的组合过程来处理输出

我猜这背后本来有一些实际的原因;也许是20世纪90年代中期的一种合成工具,它不能可靠地处理单一的过程形式,并将其纳入讲师从中学习的原始文档中。就像那些被摧毁的非标准
std\u logic\u arith
库一样。所以这个神话一直延续下去

如果这些讲师看到了现代合成工具可以传递的东西:整数、枚举、记录类型、循环、函数和过程更新信号,他们可能会大发雷霆(Xilinx ISE现在可以使用这些工具。某些版本的Synplicity在函数方面有问题,但接受带有Out参数的相同过程)


还有一条评论:我更喜欢
如果Rst='1',那么
而不是
如果(Rst='1'),那么
。它看起来不像线噪声(或C)。

Ugh。我个人讨厌双进程状态机。他可能是个老家伙,20年前这是最可靠的方法。这些工具理解您的方式,我个人更喜欢这种方式

我同意布赖恩的看法。单进程状态机的唯一问题是不能有未计时的输出,如果输入到输出需要0延迟,这是一个问题。否则,一个流程模型有助于最小化错误,因为它清楚地将输出与状态关联起来

我在学校里学过两个过程模型,但我发现一个过程模型是业界普遍接受的。我相信,在学校使用双过程模型的理由是,它让学生了解相对于寄存器的组合逻辑的位置是如何根据代码的编写方式(IMO在开始时非常重要)以及它对他们的设计意味着什么而变化的。然而,仅仅强迫您使用两个流程模型而不做任何解释并不能实现这一点

第一种方法看起来更简单,因为一切都是定时的,引入闩锁的风险更小(没有?)

是的,第一种方法中的所有东西都是时钟没有机会引入闩锁。它可能会引入触发器,但这没关系

第二种方法可以引入真正的异步锁存器,即使在最好的情况下,我使用的后端FPGA工具也不能很好地处理这些锁存器,并且在某些体系结构中根本不受支持,因此必须使用门或查找表来构建


此外,如果在第二个过程中灵敏度列表错误,则模拟结果可能与合成结果不同!这是因为合成器(出于我放弃尝试理解的原因)将灵敏度列表视为包含了您读取的所有信号(完全忽略过程中的VHDL语言规范),而模拟器将完全按照您所说的操作。

您的同学完全正确。这里的问题是你的问题不完整。您同事的代码比您的代码好的原因是,人们通常在同一个过程中定义输出值和下一个状态值,如下所示(这与您自己的代码相同,只是添加了输出值,这会导致“坏”代码):

elsif(上升沿(clk))然后
案例状态为
当s1=>
--定义输出:

outp1在第一种情况下,您将
Clk
放入敏感列表,但在此过程中从未读取过它。@Wisatbff感谢您指出这一点。再进一步,只写
如果Rst,则写
?它甚至更干净(更好的信号/噪声比)是的,绝对如此,如果你能定义Rst信号的类型!人们常常忘记布尔值也是可合成的。不幸的是,你可能会遇到这样的情况,特别是像Rst这样的外部连接是std_逻辑,或者编码标准坚持必须是std_逻辑,然后你必须进行显式比较。我也喜欢布尔信号,但是我想指出的是,
如果Rst那么…
将起作用,即使
Rst
是vhdl2008中的
std_逻辑类型。令人惊讶的是,这个技巧可以清理一些表达式。啊,但是你怎么知道是正逻辑还是负逻辑惯例适用呢?布尔值很简单:true总是true,false总是false。其他逻辑信号并非如此:复位特别容易实现为负逻辑(也称为“低电平”)。你可能会认为这个名字(reset\n)表示修道院
 elsif (rising_edge(clk)) then
    case state is
        when s1 =>
            --define outputs:
            outp1 <= ...;
            outp2 <= ...;
            ...
            --define next state:
            if (input = '1') then
               state <= s2;
            else
               state <= s1;
             end if;
          when s2 =>
             ...
          ...
        end case;
    end if;