【问题标题】:Encoding state machines in VHDL用 VHDL 编码状态机
【发布时间】:2011-05-11 09:05:43
【问题描述】:

我正在研究用 VHDL 创建一个系统,该系统在通过 FTDI USB 转串行设备接收图像后过滤图像。作为其中的一部分,我相信我已经确定了我的 CPLD 应该处于的状态,但我之前从未在 VHDL 中创建过复杂的状态机,所以我质疑我的方法是否合理。目前,我的状态机的基本轮廓是这样的:

begin
    process(clk, reset, USB_RXFN, USB_TXEN)
    begin
        case state is
            when IDLE =>
            when NEGOTIATING =>
            when RECEIVING =>
            when FILTERING =>
            when TRANSMITTING =>
            when OTHERS  => -- this should never happen but go to IDLE
    end process;

我的问题是,我能够在每个上升沿(或类似的,但每个时钟一次)上找到每个状态机教程的更改状态,并且该设备应该经常处于空闲状态,并且只有在 USB_RXFN 时才转换到 NEGOTIATING变低,保持在 NEGOTIATING 直到完成,保持在 RECEIVING 直到整个图像被传输等等......

我的方法是否存在根本性缺陷? CPLD 是否根本不适合此目的?或者是否可以在一个状态下停留超过一个时钟,而教程只是为了简单起见而写成这样?

【问题讨论】:

    标签: vhdl fsm


    【解决方案1】:

    简而言之,为了简单起见,您所阅读的教程就是这样编写的。

    在移动到另一个状态之前等待某个状态的某个事件是完全可以的。这可以在 VHDL 中以多种方式表达,一种常见的方式是同时使用 StateNextState 信号,例如:

    architecture foo of bar is
        type StateType is (IDLE, NEGOTIATING, RECEIVING, FILTERING, TRANSMITTING);
        signal State : StateType;
        signal NextState : StateType;
    begin
        FSM: process(clk, reset)
        begin
            if reset='1' then
                State <= IDLE;
            elsif clk'event and clk='1' then
                State <= NextState;
            end if;
        end process FSM;
    
        STATES: process(State, USB_RXFN, USB_TXEN) -- ...
        begin
            NextState <= State; -- by default, stay in the same state (avoid a latch while you're at it)
            case State is
                when IDLE =>
                    if USB_RXFN='0' then
                        NextState <= NEGOTIATING;
                    end if;
                -- etc
            end case;
        end process STATES;
    end foo;
    

    【讨论】:

      【解决方案2】:

      是的,您可以等待任意时间和/或您喜欢的输入组合,然后再转移到另一个状态。这是一个单一的流程示例。我更喜欢单个进程(TomiJ 展示了一个经典的 2 进程状态机,我已经重用了其中的一些 - 感谢 TomiJ),因为它有点短,并且可以避免在您错过灵敏度列表中的信号时无意中推断出锁存器“非时钟”进程。

      architecture foo of bar is
      begin
          FSM: process(clk, reset)
              type StateType is (IDLE, NEGOTIATING, RECEIVING, FILTERING, TRANSMITTING);
              variable state, next_state : StateType;
          begin
              if reset='1' then
                  state := IDLE;
                  next_state := IDLE;
              elsif rising_edge(clk) then
                  case state is
                      when IDLE =>
                          if USB_RXFN='0' then
                              next_state := NEGOTIATING;
                          end if;
                      -- etc
                  end case;
                  -- Perform other logic based on state or next_state here
      
                  -- finally update state for next time
                  state := next_state;
              end if;
          end process FSM;
      end foo;
      

      【讨论】:

      • 看来我不能“接受”两个答案,所以我选择了另一个答案,因为它首先发布的简单优点,但无论如何我还是要感谢你的贡献。
      猜你喜欢
      • 2012-10-16
      • 1970-01-01
      • 2023-03-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-08-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多