Intel® Quartus® Prime Software
Intel® Quartus® Prime Design Software, Design Entry, Synthesis, Simulation, Verification, Timing Analysis, System Design (Platform Designer, formerly Qsys)
公告
FPGA community forums and blogs on community.intel.com are migrating to the new Altera Community and are read-only. For urgent support needs during this transition, please visit the FPGA Design Resources page or contact an Altera Authorized Distributor.
17268 讨论

VHDL State Machine: Bad State Transitions

Altera_Forum
名誉分销商 II
2,338 次查看

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 项奖励
5 回复数
Altera_Forum
名誉分销商 II
1,388 次查看

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 项奖励
Altera_Forum
名誉分销商 II
1,388 次查看

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 项奖励
Altera_Forum
名誉分销商 II
1,388 次查看

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 项奖励
Altera_Forum
名誉分销商 II
1,388 次查看

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 项奖励
Altera_Forum
名誉分销商 II
1,388 次查看

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 项奖励
回复