FTDI社のUSB3.0ブリッジIC FT600の転送レートをEDX-009を用いて実際に計測しました。
EDX-009はXILINX社のKintex-7とFT600をクレジットカードサイズのボードに搭載したFPGAボードです。
転送レートの理論値はデータ16bit幅・100MHz動作という仕様から、200MB/s (MByte/sec 以下同様)となっています。
アプリケーションで計測を行った結果、下記のようになりました。
- 送信:約190MB/s
- 受信:約175MB/s

以下計測の詳細です。
設定
以下の設定で測定を行いました。
- FT600動作モード:245 FIFO, 100MHz
- 測定範囲(送信):100kB(102400 Byte)~20,000kB を100kB Step (200点)
- 測定範囲(受信):100kB(102400 Byte)~10,000kB を100kB Step (100点)
- 測定回数:10回を平均
- D3XXデバイスドライババージョン:v1.1.0.0
- 実験ボード:EDX-009
送信レート観測
PCアプリケーションからFPGAへデータを送信し、ステータスが送信完了となるまでの時間を測定します。
観測結果は下図のようになりました。転送量が増えるにつれて190MB/sに近づいています。

6000 Byteを送信したときの観測波形をいくつか示します。サンプリングクロックは200MHzです。
ある一定数(512/1024/2048 Bytes)送信した際にRXFが上がり転送が一時中断するようです。中断時間は数clock~500clockなどまちまちでした。
FPGA受信波形1

クリックして拡大
FPGA受信波形2

クリックして拡大
FPGA受信波形3

クリックして拡大
受信レート観測
PCから受信を要求し、FPGAからPCへデータを送信、ステータスが送信完了となるまでの時間を測定します。
観測結果は下図のようになりました。約175MBに近づいています。

4096 Byteを受信するとしばらく待たされます。(TXEが上がる)これはFT600の受信バッファサイズに等しいです。
FPGA送信波形

クリックして拡大
PCアプリ - 送信プログラム例
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);
FPGA - 受信ステートマシン例
clkは200MHzです。FIFOへの書込処理が含まれています。
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;
PCアプリ - 受信プログラム例
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);
FPGA - 送信ステートマシン例
clkは200MHzです。FIFOからの読込処理が含まれています。
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;
下記もご参照ください
- FT600関連製品特設ページ:https://www.hdl.co.jp/FT600/index.html
お問い合わせについて
開発ツールの使い方などは、弊社のサポート外とさせていただいております。
ご担当の代理店様などにお尋ねください。
ソースなどの提供は行っておりません。予めご了承ください。
[kw] TEC-FPGA 2016-11-08 FT600 EDA-009 EDX-009 USB-106
[]




