Forum Discussion

Altera_Forum's avatar
Altera_Forum
Icon for Honored Contributor rankHonored Contributor
13 years ago

FT2232H 245 Synchronous FIFO Mode problem

Hello

Im very new to FPGA's and am still learning so please be kind if the problem is obvious :)

i have a FT2232H set to 245 Synchronous FIFO Mode.

i have a program on the pc using the d2xx drivers sending exactly 512 bytes.

the problem is when the fpga receives these 512 bytes and places them into a ram block module i am using, every time i send the 512 bytes it seams to read in 2 empty bytes first then reads in the correct 512 offsetting every thing by 2 bytes. then the next frame i send every thing is offset by 4 bytes then 6 and so on

my code is very simple

it has 2 buffers that are 3072 bytes (im only using 512 at the moment)

it fills one then once that is full it swaps to the next one and fills that one.

another bit of code is reading the none filling buffer and cycling the data to a dot matrix display (this part of the design is ok and can be ignored)

below is the timing diagram for the 245 FIFI

http://img580.imageshack.us/img580/5303/ft2232htiming.jpg

i have attached my code. all dot matrix display update code can be ignored. the problem lies in the FIFO section.

apart from these extra 2 bytes every frame (causing the buffer to be offset by 2 bytes every frame) it seams to behave correctly.

CLK = 50mhz

fifo_clk = 60mhz from FT2232H

im not sure if its a timing fault or a fault in my state machine.

i have attached my verilog file

any help would be much appreciated or just to be pointed in the right direction :)

its so close to working just this one little problem!

15 Replies

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Thank you very much for your reply.

    I have a bad problem with FT232H which is very similar to FT2232H, but only 1 channel instead of 2.

    I have a data loss every 510 bit (tested on Win7 and Win8.1) and more in other cases.

    In sw I use this code with C# .NET library (v1.0.14.0) to read data

    Pseudocode:

    OpenBySerialNumber("FTXE2X2D");
    SetBitMode(0xFF, FTD2XX_NET.FTDI.FT_BIT_MODES.FT_BIT_MODE_RESET);
    Thread.Sleep(10);
    SetBitMode(0xFF, FTD2XX_NET.FTDI.FT_BIT_MODES.FT_BIT_MODE_SYNC_FIFO);            
    Purge(FTD2XX_NET.FTDI.FT_PURGE.FT_PURGE_RX)
    --Cycle
      Read(dataBuffer, 1024, ref numBytesRead);   
    --End cycle
    Close();

    *Data loss even with SetFlowControl(FTD2XX_NET.FTDI.FT_FLOW_CONTROL.FT_FLOW_RTS_CTS, 0, 0);

    I have tried to change buffer size (1024 in pseudocode) with other values. If buffer size is 1 no errors, in other case I have a lot of errors (about 0.016% data loss with buffer = 1024 bytes)

    Timing of FT232H are:

    http://imagizer.imageshack.us/v2/xq90/13/7cmg.png

    In VHDL I have this simple code:

    library ieee;
    use ieee.std_logic_1164.all;
    use ieee.numeric_std.all;
    entity ft232h_tx is
        port 
        (        
            FT_CLK    : in std_logic;                            -- 60 MHz FT232H clock
            nTXE        : in std_logic;                            -- Can TX
            nRXF        : in std_logic;                            -- Can RX
            nRD        : out std_logic;                            -- Read
            nSIWU        : out std_logic;                            -- Send Immediate / WakeUp
            nOE        : out std_logic;                            -- Output enable
            nWR        : out std_logic;                            -- FIFO Buffer Write Enable
            ADBUS        : out std_logic_vector(7 downto 0)    -- Bidirectional FIFO data
        );
    end entity;
    architecture rtl of ft232h_tx is
        signal counter : unsigned (7 downto 0) := "00000000";    
    begin
        -- don't read
        nOE <= '1';
        nSIWU <= '1';
        nRD <= '1';
        
        process(FT_CLK, nTXE)
            variable state : std_logic := '0';        
        begin    
            if (rising_edge(FT_CLK)) then
                if(nTXE = '0') then
                    if(state = '1') then
                        nWR <= '0';
                        -- last data not valid if nTXE goes LOW
                        ADBUS <= std_logic_vector(counter);
                        counter <= counter + 1;
                    end if;
                    state := '1';
                else
                    nWR <= '1';
                    state := '0';                            
                end if;
            end if;        
        end process;
    end rtl;
    

    That is a simply counter that continuously count up to 255 and so send 0,1,2..,254,255,0,1,2...,254,255 to pc

    and in SDC file I have set these constraints:

    create_clock -name "FT_CLK" -period 16.67ns 
    set_input_delay -clock { FT_CLK } -min 9ns nTXE
    set_input_delay -clock { FT_CLK } -max 0ns nTXE
    set_output_delay -max -clock "FT_CLK"  7.500ns }]
    set_output_delay -max -clock "FT_CLK"  7.500ns }]
    set_output_delay -max -clock "FT_CLK"  7.500ns }]
    set_output_delay -max -clock "FT_CLK"  7.500ns }]
    set_output_delay -max -clock "FT_CLK"  7.500ns }]
    set_output_delay -max -clock "FT_CLK"  7.500ns }]
    set_output_delay -max -clock "FT_CLK"  7.500ns }]
    set_output_delay -max -clock "FT_CLK"  7.500ns }]
    set_output_delay -max -clock "FT_CLK"  7.500ns 
    set_output_delay -min -clock "FT_CLK"  0ns }]
    set_output_delay -min -clock "FT_CLK"  0ns }]
    set_output_delay -min -clock "FT_CLK"  0ns }]
    set_output_delay -min -clock "FT_CLK"  0ns }]
    set_output_delay -min -clock "FT_CLK"  0ns }]
    set_output_delay -min -clock "FT_CLK"  0ns }]
    set_output_delay -min -clock "FT_CLK"  0ns }]
    set_output_delay -min -clock "FT_CLK"  0ns }]
    set_output_delay -min -clock "FT_CLK"  0ns 

    With signaltap I have take this screenshot:

    http://imagizer.imageshack.us/v2/xq90/30/e0pc.png (https://imageshack.com/i/0ue0pcp)

    But I can not find the error.. :(
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Hello

    Its been a while seen i placed with this stuff hehe, I ended up going with a STM32F04 micro instead of the ftdi/fpga

    Here is my code, hopefully if helps you out :)

    I am sending data the opposite direction, from the pc to the fpga.

    .c

    
    FT_SetBitMode(ftHandle, 0xff, 0);
    Sleep(10);
    FT_SetBitMode(ftHandle, 0xff, 0x40);
    FT_SetLatencyTimer(ftHandle, 16);
    FT_SetUSBParameters(ftHandle,0x10000, 0x10000);
    FT_SetFlowControl(ftHandle, FT_FLOW_RTS_CTS, 0x0, 0x0);
    FT_Purge(ftHandle, FT_PURGE_RX);
    Sleep(10);
    

    fpga

    
    // *****************************
    // FT2232H Synchronous 245 FIFO
    // *****************************
    always @(posedge fifo_clk)
    begin
        case(fifo_state)
            0:  begin // wait for rxf to go low (byte available)
                    if(rxf==0)
                    begin
                        oe=0;
                        fifo_cnt=0;
                        fifo_state=1;
                    end
                end
            1: begin
                    rd = 0;
                    fifo_state=2;
                end
            2: begin
                    // keep reading data untill rxf goes high
                    if(rxf==1)
                    begin
                        rd = 1;
                        oe = 1;
                        fifo_state=0;
                    end else 
                    begin
                        // check frame preamble bytes
                        if(preamble_state<3)
                        begin
                            wr_addr = 0;
                            if(preamble==data_in)
                                preamble_state=preamble_state+1;
                            else
                                preamble_state=0;
                        end else
                        if(preamble_state==3)
                        begin
                            // command byte (unused)
                            preamble_state=4;
                        end else
                        begin
                            // frame data bytes
                            wr_addr = wr_addr + 1;
                            // read in 2048 bytes (full frame)
                            if(wr_addr == 2048)
                            begin
                                wr_addr=0;
                                preamble_state = 0;
                                // swap to next buffer
                                buf_ready=!buf_ready;
                            end
                        end
                    end
                end
        endcase
    end
    

    The fpga side of things a little bit more complex that you might need it as im checking the first three bytes in my packet to keep every thing in sync, if they are wrong it will discard the packet, you can chop this bit of code out if you want. It was for basic error checking and frame sync.

    The above code is just the logic for reading in the bytes from the ftdi, give me a shout if you want the full source. It is sort of mixed in with the full project though hehe.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    So USB data can be corrupted by design by FT232H and we have to implement a CRC check over it?

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Its usually ok but in my project i was streaming video frames at a very high fps and if some thing went wrong (very rare) It would screw up the image alignment, So in my case a needed to put in the simple frame header checking just to make sure I new where I was in case there was a little rare glitch.

    Im sure you will not need this for sending some data from the fpga to the pc occasionally.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    With great FTDI support I have solved problem TXE signal can go HIGH on falling edge of clock and so it must not be checked only on rising edge.

    Working code:

    library ieee;
    use ieee.std_logic_1164.all;
    use ieee.numeric_std.all;
    entity ft232h_tx is
       port 
       (      
          FT_CLK   : in std_logic;                     -- 60 MHz FT232H clock
          nTXE      : in std_logic;                     -- Can TX
          nRXF      : in std_logic;                     -- Can RX
          nRD      : out std_logic;                     -- Read
          nSIWU      : out std_logic;                     -- Send Immediate / WakeUp
          nOE      : out std_logic;                     -- Output enable
          nWR      : buffer std_logic;                  -- FIFO Buffer Write Enable
          ADBUS      : out std_logic_vector(7 downto 0)   -- Bidirectional FIFO data               
       );
    end entity;
    architecture rtl of ft232h_tx is
       signal counter : unsigned (7 downto 0) := "00000000";
       signal state : std_logic := '0';
    begin
       
       -- don't read
       nOE <= '1';
       nSIWU <= '1';
       nRD <= '1';
       
       process(FT_CLK, nTXE)      
       begin   
          if (rising_edge(FT_CLK)) then
             if(nTXE = '0') then
                if(state = '1') then
                   --nWR <= '0';
                   ADBUS <= std_logic_vector(counter);
                   counter <= counter + 1;
                end if;
                state <= '1';
             else
                --nWR <= '1';
                state <= '0';                     
             end if;
          end if;      
       end process;
       nWR <= '1' when nTXE = '1' else 
              '0' when (nTXE ='0' and state = '1');
       
    end rtl;

    Thanks to all