Intel® Quartus® Prime Software
Intel® Quartus® Prime Design Software, Design Entry, Synthesis, Simulation, Verification, Timing Analysis, System Design (Platform Designer, formerly Qsys)
17249 Discussions

VHDL State Machine: Bad State Transitions

Altera_Forum
Honored Contributor II
2,299 Views

Hi, I'm really hoping someone can help me as I'm at my wits end. I am running into a scenario where my state machine is transitioning into an invalid state. As far as I can tell, all of my paths between states are covered, but I must be doing something wrong. The states are setup to use one-hot encoding, btw. 

 

Here's the some VHDL that reproduces the problem. It basically reads data from a FIFO and tries to write it to USB. After running for some period of time (which varies), the "packet_state" value becomes 0x00 (an invalid state value). 

 

I've also attached a SignalTap screenshot showing the transition. I just can't understand why it happens. 

 

Any ideas or suggestions? 

 

Thanks! 

 

library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity USB_IO is port ( -- General -- main_clk: in std_logic; -- Primary clock: 50 Mhz -- Reset -- reset_n: in std_logic := '0'; -- USB TX FIFO -- fifo_usb_tx_bus: in std_logic_vector(23 downto 0); fifo_usb_tx_empty: in std_logic := '0'; fifo_usb_tx_rd: out std_logic := '0'; fifo_usb_tx_clr: out std_logic := '0'; -- FTDI FT2232 USB I/O -- ftdi_usb_txe_n: in std_logic := '0'; ftdi_usb_rxf_n: in std_logic := '1'; ftdi_usb_bus: inout std_logic_vector(7 downto 0); ftdi_usb_wr_n: buffer std_logic := '1'; ftdi_usb_rd_n: buffer std_logic := '1' ); end USB_IO; architecture rtl of USB_IO is -- Create separate in and out signals for the bidir port 'ftdi_usb_bus'. signal ftdi_usb_bus_in : std_logic_vector(7 downto 0) := "00000000"; signal ftdi_usb_bus_out : std_logic_vector(7 downto 0) := "00000000"; attribute syn_encoding : string; type usb_io_state_type is (usb_io_idle, usb_io_tx, usb_io_rx); attribute syn_encoding of usb_io_state_type : type is "onehot"; signal usb_io_state : usb_io_state_type := usb_io_idle; type packet_state_type is ( S1, S2, S3, S4, S5, S6, S7, S8 ); attribute syn_encoding of packet_state_type : type is "onehot"; signal packet_state : packet_state_type := S1; begin -- Infer tri-state buffers for our bidirectional pins. ftdi_usb_bus <= ftdi_usb_bus_out when ftdi_usb_rd_n = '1' else "ZZZZZZZZ"; ftdi_usb_bus_in <= ftdi_usb_bus; process(main_clk) begin if(rising_edge(main_clk)) then -- Default our outputs. fifo_usb_tx_clr <= '0'; fifo_usb_tx_rd <= '0'; ftdi_usb_wr_n <= '1'; ftdi_usb_rd_n <= '1'; if(reset_n = '0') then usb_io_state <= usb_io_idle; packet_state <= S1; fifo_usb_tx_clr <= '1'; else case usb_io_state is when usb_io_idle => packet_state <= S1; -- Look for incoming data first; then outgoing. if(ftdi_usb_rxf_n = '0') then usb_io_state <= usb_io_rx; elsif(fifo_usb_tx_empty = '0') then fifo_usb_tx_rd <= '1'; usb_io_state <= usb_io_tx; else usb_io_state <= usb_io_idle; end if; when usb_io_tx => if(ftdi_usb_txe_n = '0') then case packet_state is when S1 => ftdi_usb_bus_out <= X"AA"; packet_state <= S2; when S2 => ftdi_usb_bus_out <= X"AA"; ftdi_usb_wr_n <= '0'; packet_state <= S3; when S3 => ftdi_usb_bus_out <= fifo_usb_tx_bus(23 downto 16); packet_state <= S4; when S4 => ftdi_usb_bus_out <= fifo_usb_tx_bus(23 downto 16); ftdi_usb_wr_n <= '0'; packet_state <= S5; when S5 => ftdi_usb_bus_out <= fifo_usb_tx_bus(15 downto 8); packet_state <= S6; when S6 => ftdi_usb_bus_out <= fifo_usb_tx_bus(15 downto 8); ftdi_usb_wr_n <= '0'; packet_state <= S7; when S7 => ftdi_usb_bus_out <= fifo_usb_tx_bus(7 downto 0); packet_state <= S8; when S8 => ftdi_usb_bus_out <= fifo_usb_tx_bus(7 downto 0); ftdi_usb_wr_n <= '0'; packet_state <= S1; usb_io_state <= usb_io_idle; when others => ftdi_usb_wr_n <= '1'; packet_state <= S1; usb_io_state <= usb_io_idle; end case; end if; when usb_io_rx => -- Not yet implemented -- usb_io_state <= usb_io_idle; packet_state <= S1; end case; end if; -- reset end if; -- rising_edge end process USB_IO_Handler; end architecture rtl;
0 Kudos
5 Replies
Altera_Forum
Honored Contributor II
1,349 Views

Sorry to reply to my own post, but I just saw a similar thread which suggests that the bad state could be related to timing (perhaps with the ftdi_usb_txe_n input?). 

 

I'm trying to use the FTDI FT2232 USB chip in asynchronous mode. That may be the source of all of my problems....
0 Kudos
Altera_Forum
Honored Contributor II
1,349 Views

If the incoming signals are asynchrnous, I suggest you synchronise them to the "main_clk" before trying to use them. Without doing that, you will be violating setup and hold times, and any signals that read them may become meta-stable.

0 Kudos
Altera_Forum
Honored Contributor II
1,349 Views

Metastability isn't required to get illegal states. Routing delay skew is sufficient, causing 99.9% (or so) of unexpected logic behaviour with timing violations. Synchronizing is the solution anyway.

0 Kudos
Altera_Forum
Honored Contributor II
1,349 Views

change your clk to 24Mhz and use this (LMK if it helps): 

-- ft2232d_fifo generation 

 

library ieee; 

use ieee.std_logic_1164.all; 

use ieee.numeric_std.all; 

use ieee.std_logic_unsigned.all; 

 

 

entity ft2232d_fifo is 

port ( 

clkin : in std_logic; -- 24 MHZ clock from oscillator 

resetn : in std_logic; -- global reset to reset everything 

usbtxen : in std_logic; -- TX FIFO empty (low means data can go into FIFO) 

usbrxfn : in std_logic; -- RX FIFO full (low means data can be read from FIFO) 

readfifodata : in std_logic; -- Read Enable 

writefifo : in std_logic; -- Write Enable 

usbrdn : out std_logic; -- strobe low-then-high to get data from FIFO 

usbwr : out std_logic; -- strobe high-then-low to write data into FIFO 

usbd : inout std_logic_vector(7 downto 0); -- bi-directional data bus to FIFO chip 

data_read : out std_logic_vector(7 downto 0); -- bi-directional data bus to FIFO chip 

data_write : in std_logic_vector(7 downto 0) -- bi-directional data bus to FIFO chip 

 

); 

end ft2232d_fifo; 

------------------------------------------------------------- 

architecture rtl of ft2232d_fifo is 

type USB_STATE_TYPE is (USBIDLE,USBGETBYTE,USBSAVEBYTE, 

USBRDDN,USBPUTBYTE,USBWOUT, 

USBWHLD); 

 

--signal USBState : std_logic_vector(4 downto 0); 

--signal USBIDLE : std_logic_vector(4 downto 0) := "00000"; 

--signal USBGETBYTE : std_logic_vector(4 downto 0) := "00001"; 

--signal USBSAVEBYTE : std_logic_vector(4 downto 0) := "10001"; 

--signal USBRDDN : std_logic_vector(4 downto 0) := "01000"; 

--signal USBPUTBYTE : std_logic_vector(4 downto 0) := "00010"; 

--signal USBWOUT : std_logic_vector(4 downto 0) := "00110"; 

--signal USBWHLD : std_logic_vector(4 downto 0) := "01100"; 

signal USBState : USB_STATE_TYPE; 

signal iswrite : std_logic; 

signal usbdone : std_logic; 

 

begin 

--usbrdn <= NOT USBState(0); 

--usbwr <= USBState(1); 

--iswrite <= USBState(2); 

--usbdone <= USBState(3); 

 

usb_rx_tx: process (resetn,clkin) 

begin 

if (resetn = '0') then 

USBState <= USBIDLE; 

usbrdn <= '1'; 

usbwr <= '0'; 

iswrite <= '0'; 

usbdone <= '0'; 

data_read <= (others => '0'); 

elsif (rising_edge(clkin)) then 

case USBState is 

 

when USBIDLE => 

usbrdn <= '1'; 

usbwr <= '0'; 

iswrite <= '0'; 

usbdone <= '0'; 

if(readfifodata = '1' AND usbrxfn = '0') then 

USBState <= USBGETBYTE; 

elsif(writefifo = '1' AND usbtxen = '0') then 

USBState <= USBPUTBYTE; 

else 

USBState <= USBIDLE; 

end if; 

 

 

when USBGETBYTE =>  

usbwr <= '0'; 

iswrite <= '0'; 

usbdone <= '0'; 

usbrdn <= '0'; 

USBState <= USBSAVEBYTE; 

 

when USBSAVEBYTE => 

usbwr <= '0'; 

iswrite <= '0'; 

usbdone <= '0'; 

usbrdn <= '0';  

if(readfifodata = '1')then 

data_read <= usbd; 

end if; 

USBState <= USBRDDN; 

 

when USBRDDN => 

usbrdn <= '1'; 

usbwr <= '0'; 

iswrite <= '0'; 

usbdone <= '1';  

if(readfifodata = '0' AND writefifo = '0')then 

USBState <= USBIDLE; 

end if; 

 

when USBPUTBYTE => 

usbrdn <= '1'; 

usbwr <= '1'; 

iswrite <= '0'; 

usbdone <= '0';  

USBState <= USBWOUT; 

 

when USBWOUT => 

usbrdn <= '1'; 

usbwr <= '1'; 

iswrite <= '1'; 

usbdone <= '0';  

USBState <= USBWHLD; 

 

when USBWHLD => 

usbrdn <= '1'; 

usbwr <= '0'; 

iswrite <= '1'; 

usbdone <= '1';  

if(readfifodata = '0' AND writefifo = '0')then 

USBState <= USBIDLE; 

end if; 

end case; 

 

end if; 

end process usb_rx_tx; 

 

usbd <= data_write when (iswrite) = '1' else "ZZZZZZZZ"; 

end rtl; 

-------------------------------------------------------------
0 Kudos
Altera_Forum
Honored Contributor II
1,349 Views

Using FT2232 in asynchronous mode with 24 MHz clock frequency does not solve the problem addressed in post# 2 to# 4. Synchroniszation is still required as long as FTDI internal and FPGA clock ar unrelated.

0 Kudos
Reply