我正在研究用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是否完全不适用于此目的?或者是否可以保持一个状态超过一个时钟,教程只是为了简单而编写?
答案 0 :(得分:3)
简而言之,您阅读过的教程就是为了简单起见而编写的。
在移动到另一个状态之前等待状态中的某个事件是完全可以的。这可以用VHDL的多种方式表达,一种常见的方法是同时拥有State
和NextState
信号,如:
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;
答案 1 :(得分: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;