- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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;
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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....- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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; -------------------------------------------------------------- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.

- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page