首页 文章

用VHDL编码状态机

提问于
浏览
3

我正在研究用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;

我的问题在于每个状态机教程我都能够在每个上升沿(或类似的,但每个时钟一次)找到更改状态,并且此设备应该在IDLE中很多并且仅在USB_RXFN变低时转换到NEGOTIATING,留在谈判直到完成,留在RECEIVING直到整个图像被转移等...

我的方法中存在根本缺陷吗? CPLD是否完全不适用于此目的?或者是否可以保持一个状态超过一个时钟,并且教程只是为了简单而编写的?

2 回答

  • 3

    简而言之,您阅读的教程刚刚以简洁的方式编写 .

    在移动到另一个状态之前等待状态中的某个事件是完全可以的 . 这可以用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;
    
  • 3

    是的,您可以在转移到其他状态之前等待任何时间和/或输入您喜欢的组合 . 这是一个单一的流程示例 . 我更喜欢单个进程(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;
    

相关问题