50 MHz FPGA (Cyclone IV @ DE0-Nano) and 60 MHz input from FT2232H

clockclock-speedfpgaftdiintel-fpga

I want to read data from FT2232H used in an FT245 style synchronous FIFO mode (http://www.ftdichip.com/Support/Documents/DataSheets/ICs/DS_FT2232H.pdf p.27) with DE0-Nano FPGA board:

process(clk)
begin    
    if (rising_edge(clk)) then
        next_state <= current_state;

        case current_state IS
            when POLL_UNTIL_RXF_LOW =>
                if (rxf = '0') then
                    current_oe <= '0';
                    next_state <= WAIT_SET_RD_LOW;
                else
                    current_oe <= '1';
                end if;
                current_rd <= '1';

            when WAIT_SET_RD_LOW =>
                current_oe <= '0';
                current_rd <= '1';
                next_state <= SET_RD_LOW;

            when SET_RD_LOW =>
                current_oe <= '0';
                current_rd <= '0';                    
                next_state <= READ_DATA;

            when READ_DATA =>        
                if (rxf = '0') then
                    current_oe <= '0';
                    current_rd <= '0';

                    -- access data here
                else
                    current_oe <= '1';
                    current_rd <= '1';                        
                    next_state <= POLL_UNTIL_RXF_LOW;
                end if;

            when others =>
                null;
        end case;
    end if;
end process;

rd <= current_rd;
oe <= current_oe;

siwu <= '1';
wr <= '0';

This code doesn't work well: about 51% of my data gets lost. I think, this is happening because clk in this code is 60 MHz clock provided by FT2232H; however, the DE0-Nano has an on-board 50 MHz oscillator connected directly to one of the FPGA clock pins. Is it possible to read 60 MHz data with 50 MHz clocked FPGA at all? How do you do it?

Best Answer

This should be possible with some careful design.

Firstly as @Qui says you should generate a synchronised clock signal inside your FPGA at 60 MHz to allow you to read the data.

  1. Create a PLL which locks to the clock signal provided from your FT2232 and outputs a 60 MHz clock at a phase of 0 (synchronised). The FT2232 clock must be connected to a clock-capable input pin (see the device pinout and DE0-Nano user manual to find the pins).
  2. Use this clock signal as the logic clock for all of the code which reads the data lines to and from the FT2232. This in clock domain A.
  3. Write some logic which looks at the locked pin of the PLL. This indicates that the PLL has synchronised successfully. You shouldn't try to communicate with the FT2232 before the PLL locks.

You can then read your data as you have been, hopefully more successfully!

You then have two choices when it comes to using the data, you can either use the 60 MHz PLL output for all the rest of your logic (simple) or move the received data across a clock-domain boundary and process it with logic clocked at you 50 MHz board clock. In the first case just go right ahead, but if you need to use the 50 MHz then read on.

If you need your signals to be used in the 50 MHz clock domain (clock domain B) then you must be very careful in crossing the clock domain boundary or the same problem will happen as you have already experienced (that is effectively what you are doing). In general you must

  1. Separate your logic so that you know exactly which parts of the design are in which clock domain.
  2. Define the signals which are going to cross from one section to the other (A to B and B to A). If you can, make the signals relatively low-rate (compared to either clock), for instance by transferring a whole word at a time rather than serially.
  3. Synchronise any signals crossing the boundary to the new clock domain. Synchronising is required to prevent metastability. Using a dual-port FIFO is probably the simplest and most reliable way. See this question and this one.
  4. Simulate each clock domain's logic separately with dummy inputs to make sure they work before trying them both together.
  5. Simulate the whole design to make sure it works in the simulator.
  6. Define your timing constraints carefully before synthesising the design, if you do this well the tools should catch problems with the clock boundaries.
  7. Synthesise and test. A good, high bandwidth oscilloscope (150 MHz+) will help a lot in debugging signals from test pins when it comes to looking at whether clocks and signals are synchronised correctly.

Unfortunately I can't help you much with the last part as I don't use Altera tools.