在VHDL中实现FSM

Sam*_*Sam 6 vhdl fsm

只是想知道我是否在VHDL中实现有限状态机是否需要说明所有输出在每种可能的状态?即使我知道某些输出不会从一个状态改变到另一个状态,我知道状态的顺序也会是相同的顺序吗?

例如,在此(强制)示例中:

entity test is
    port (
        clk : in std_logic;
        a : in std_logic;
        b: out std_logic;
        c: out std_logic;
    );
end test;

architecture Behavioral of test is

type executionStage is (s1,s2,s3);
signal currentstate, nextstate: executionStage;

begin
    process (clk)
    begin
          if(rising_edge(clk)) then
                 currentstate <= nextstate;
          else 
                 currentstate <= currentstate;
          end if;
    end process;

    process(currentstate)
    begin
        case currentstate is
            when s1 =>
                if (a = '1') then
                    b <= '1';
                    c <= '0';
                else
                    b <= '1';
                    c <= '1';
                end if;

                nextstate <= s2;

            when s2 =>
                -- b doesnt change state from s1 to here, do I need to define what it is here?
                if (a = '1') then
                    b <= '1';
                    c <= '1';
                else
                    b <= '1';
                    c <= '0';
                end if;

                nextstate <= s3;

            when s3 =>
                if (a = '1') then
                    b <= '0';
                    c <= '0';
                else
                    b <= '1';
                    c <= '1';
                end if;

                nextstate <= s1;
        end case;
    end process;
end Behavioral;
Run Code Online (Sandbox Code Playgroud)

根据我的理解,如果我不这样做,那么锁存器会被创建吗?

这个例子并不是什么大问题,但如果我的机器输出超过10个且超过10个状态,那么我的VHDL文件开始看起来非常混乱,我相信复制和粘贴它一定是不好的做法.同样的事情一遍又一遍.有没有更好的方法呢?

编辑:我可以为输出定义'默认'状态吗?IE将b设置为所有进程之外的1,然后只定义它在case语句中的0是什么?那会有用吗?

Tom*_*ila 7

是的,如果您只在该过程的某些分支中驱动要组合的信号,您将推断锁存器.

但是,您可以通过在case语句之前为其分配值(但在同一进程中)来为信号定义"默认"状态.例如:

process(currentstate, a)
begin
    b <= '1';
    c <= '1';
    case currentstate is
        when s1 =>
            if (a = '1') then
                c <= '0';
            end if;

            nextstate <= s2;

        when s2 =>
            -- b doesnt change state from s1 to here, do I need to define what it is here?
            if (a /= '1') then
                c <= '0';
            end if;

            nextstate <= s3;

        when s3 =>
            if (a = '1') then
                b <= '0';
                c <= '0';
            end if;

            nextstate <= s1;
    end case;
end process;
Run Code Online (Sandbox Code Playgroud)


Phi*_*ppe 7

您的示例代码有三个问题:

端口列表中的最后一个端口不应该有分号:

port (
    clk : in std_logic;
    a : in std_logic;
    b: out std_logic;
    c: out std_logic -- no semicolon here!!!
    );
Run Code Online (Sandbox Code Playgroud)

在您的注册过程中,您不应该有"其他"声明.虽然这可能会被工具所接受,但它会让您的VHDL设计人员感到困惑.

process (clk)
begin
    if(rising_edge(clk)) then
        currentstate <= nextstate;
    end if;
end process;
Run Code Online (Sandbox Code Playgroud)

在组合逻辑中,灵敏度列表应包含您读取的所有信号:process(a, currentstate).在这种特殊情况下(再次),事情可能会很好,但如果您的敏感度列表不正确,您必然会推断锁存或导致其他问题.

至于你的问题:

  1. 是的,您需要为组合过程中的每个信号分配一个值(对于每个状态).
  2. 正如Tomi所提到的,您可以通过在流程开始时分配默认值来轻松完成此操作.
  3. 但您也可以在一个单一的同步过程中编写整个状态机.这样,您就不必为每个状态中的每个信号分配值.