Here is a demo of measuring transfer rate of FTDI's USB3.0 bridge IC FT600 using an EDX-009.
EDX-009 is an FPGA board which has XILINX's Kintex-7 and FT600をon its credit-card size board.
Transfer rate of FT600 can be calculated as 200MB/s by its 16 bit data width and 100 MHz transfer frequency. An app acts actual trasfer tests and here is a result:
- Transmit : 190MB/s (average)
- Receive : 175MB/s (average)

Please refer to below for more details.
Setup
This test was done with settings below.
- FT600 bus protocol : 245 FIFO at 100MHz
- Data amount (Tx) : 100kB(102400 Byte) to 20,000kB, 200 points in 100kB step
- Data amount (Rx : 100kB(102400 Byte) to 10,000kB, 100 points in 100kB step
- Trials for average : 10
- D3XX device friver version : v1.1.0.0
- Test board : EDX-009
Transmit Rate
Periods are timed between after writing data to the FT600 and asserting of complete signal by an API. The FPGA receives data wasting off of them. Here is the graph of result. It gets closer to 190MB.

Here is some waveforms of FPGA when it received 6000 byte data. Sampling clock is 200MHz.
It shows that the FT600 suspended transmitting after some blocks of data (512/1024/2048 Bytes) by asserting a RXF signal. Period of the suspend is not fixed and around a few to 500 clocks.
Waveform of FPGA receives data (1)

Click to enlarge
Waveform of FPGA receives data (2)

Click to enlarge
Waveform of FPGA receives data (3)

Click to enlarge
Receive Rate
Periods are timed between requesting to receive data to the FT600 and being informed of completion. Here is the graph of result. It gets closer to 175MB.

The FT600 suspended receiving data after getting 4096 Bytes by asserting an TXE signal. This number is equal to FT600 internal buffer.
Waveform of FPGA transmit data

Click to enlarge
Transmit - Application code example
OVERLAPPED vOverlappedWrite = {0};
vOverlappedWrite.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
ftStatus = FT_WritePipe(ftHandle, 0x02, buff, bytesToWrite, &bytesTransferred, &vOverlappedWrite);
if (ftStatus == FT_IO_PENDING)
{
// Poll until all data requested ulBytesToWrite is sent
do
{
// FT_GetOverlappedResult will return FT_IO_INCOMPLETE if not yet finish
ftStatus = FT_GetOverlappedResult(ftHandle, &vOverlappedWrite, &bytesTransferred, FALSE);
if (ftStatus == FT_IO_INCOMPLETE)
{
//AddReport(String().sprintf(_T("FT_IO_INCOMPLETE (%d)"), num_incomp));
AttachReport(".");
num_incomp++;
continue;
}
else if(ftStatus != FT_OK)
{
AddReport(String().sprintf(_T("WritePipeAsync()::FT_GetOverlappedResult. (0x%X)"), ftStatus));
CloseHandle(vOverlappedWrite.hEvent);
return -1;
}
else //if (ftStatus == FT_OK)
{
break;
}
}
while (1);
}
CloseHandle(vOverlappedWrite.hEvent);
Transmit - FPGA state machine example
The clk is 200MHz. This state machine writes data to the FPGA internal FIFO memory.
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity H_FT600_S245_RX_V3 is
port
(
clk : in std_logic;
reset : in std_logic;
act : in std_logic;
rcv_cmp : out std_logic;
rcv_length : out std_logic_vector(15 downto 0);
fifo_data : out std_logic_vector(15 downto 0);
fifo_wrreq : out std_logic;
be : in std_logic_vector(1 downto 0);
rxf : in std_logic;
oe : out std_logic;
rd : out std_logic;
data : in std_logic_vector(15 downto 0)
);
end entity;
architecture rtl of H_FT600_S245_RX_V3 is
-- Build an enumerated type for the state machine
type state_type is (idle,s0,s1,s2,s3,s4,s5,s6,t0,t1,e0,e1);
signal state : state_type;
signal rcv_length_reg : std_logic_vector(15 downto 0);
signal rxf_r : std_logic;
signal oe_r : std_logic;
signal rd_r : std_logic;
begin
rcv_length <= rcv_length_reg;
process (clk, reset, rxf, act)
begin
if reset = '1' then
state <= idle;
oe <= '1';
rd <= '1';
rcv_cmp <= '0';
rcv_length_reg <= X"0000";
oe_r <= '1';
rd_r <= '1';
fifo_wrreq <= '0';
elsif (rising_edge(clk)) then
rxf_r <= rxf;
oe <= oe_r;
rd <= rd_r;
case state is
when idle =>
rcv_length_reg <= X"0000";
rcv_cmp <= '0';
fifo_data <= X"BEEF";
fifo_wrreq <= '0';
oe_r <= '1';
rd_r <= '1';
if rxf_r = '0' and act = '1' then
state <= s0;
else
state <= idle;
end if;
when s0 =>
state <= s1;
when s1 =>
state <= s2;
when s2 =>
oe_r <= '0';
state <= s3;
when s3 =>
state <= s4;
when s4 =>
rd_r <= '0';
state <= s5;
when s5 =>
state <= s6;
when s6 =>
state <= t0;
---------------------------------------
when t0 =>
if rxf_r = '0' then
fifo_data <= data;
fifo_wrreq <= '1';
oe_r <= '0';
rd_r <= '0';
rcv_length_reg <= rcv_length_reg + 1;
state <= t1;
else
fifo_data <= X"DEAD";
fifo_wrreq <= '0';
oe_r <= '1';
rd_r <= '1';
rcv_length_reg <= rcv_length_reg;
state <= e0;
end if;
when t1 =>
state <= t0;
---------------------------------------
when e0 =>
rcv_cmp <= '1';
state <= e1;
when e1 =>
rcv_cmp <= '0';
state <= idle;
end case;
end if;
end process;
end rtl;
Receive - Application code example
overlappedRead.hEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
if(FT_InitializeOverlapped(ftHandle, &overlappedRead) == FT_OK)
{
ftStatus = FT_ReadPipe(ftHandle, 0x82, buff, bytesToRead, &bytesRead, &overlappedRead);
if(ftStatus == FT_IO_PENDING){
while(1){
ftStatus = FT_GetOverlappedResult(ftHandle, &overlappedRead, &bytesRead, FALSE);
if(ftStatus == FT_IO_INCOMPLETE){
//AddReport(String().sprintf(_T("FT_IO_INCOMPLETE (%d)"), num_incomp));
AttachReport(".");
num_incomp++;
continue;
}else if(ftStatus != FT_OK){
AddReport(String().sprintf(_T("ReadPipe()::FT_GetOverlappedResult. (0x%X)"), ftStatus));
CloseHandle(overlappedRead.hEvent);
break;
}else{ //ftStatus == FT_OK
result = 0;
break;
}
}
}
//----------------------------------------
if(FT_ReleaseOverlapped(ftHandle, &overlappedRead) != FT_OK){
AddReport("Error, ReadPipeAsync()::FT_ReleaseOverlapped");
result = -1;
}
}else{
AddReport("Error, ReadPipeAsync()::FT_InitializeOverlapped");
}
CloseHandle(overlappedRead.hEvent);
Receive - FPGA state machine example
The clk is 200MHz. This state machine also reads data from the FPGA internal FIFO memory.
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity H_FT600_S245_TX_V6 is
port
(
clk : in std_logic;
reset : in std_logic;
act : in std_logic;
fifo_data : in std_logic_vector(15 downto 0);
fifo_rdreq : out std_logic;
fifo_empty : in std_logic;
be : inout std_logic_vector(1 downto 0);
txe : in std_logic;
wr : out std_logic;
data : inout std_logic_vector(15 downto 0);
dbg_data : out std_logic_vector(15 downto 0)
);
end entity;
architecture rtl of H_FT600_S245_TX_V6 is
-- Build an enumerated type for the state machine
type state_type is (idle,s0,s1,s2,t0,t1,e0);
signal state : state_type;
signal fifo_rdreq_w : std_logic;
signal txe_r : std_logic;
signal wr_r : std_logic;
begin
fifo_rdreq <= fifo_rdreq_w and not txe;
process (clk, reset, txe, fifo_data)
begin
if reset = '1' then
state <= idle;
be <= (others=>'Z');
data <= (others=>'Z');
dbg_data <= X"0000";
wr <= '1';
wr_r <= '1';
fifo_rdreq_w <= '0';
elsif (rising_edge(clk)) then
txe_r <= txe;
wr <= wr_r;
case state is
when idle =>
wr_r <= '1';
data <= (others=>'Z');
be <= (others=>'Z');
fifo_rdreq_w <= '0';
if txe_r = '0' and act = '1' then
state <= s0;
else
state <= idle;
end if;
---------------------------------------------
when s0 =>
state <= s1;
when s1 =>
fifo_rdreq_w <= '1';
state <= s2;
when s2 =>
wr_r <= '0';
state <= t0;
--------------------------------------
when t0 =>
if txe_r = '0' then
fifo_rdreq_w <= '1';
wr_r <= '0';
data <= fifo_data;
be <= "11";
dbg_data <= fifo_data;
state <= t1;
else
fifo_rdreq_w <= '0';
wr_r <= '1';
data <= (others=>'Z');
be <= (others=>'Z');
dbg_data <= X"EEEE";
state <= e0;
end if;
when t1 =>
state <= t0;
----------------------------
when e0 =>
state <= idle;
end case;
------------------------------------------
end if;
end process;
end rtl;
Contact us
We hope you find this demonstration informative.
Please let us know if you notice any mistakes.
Please be forewarned that we do not offer sample design files.
[kw] FT600 EDA-009 EDX-009 USB-106
[ ]

