FTDI社のUSB3.0ブリッジIC FT600の動作速度をEDA-009で測定しました

 FTDI社のUSB3.0ブリッジIC FT600の転送レートをEDA-009を用いて実際に計測しました。
EDA-009はALTERA社のCycloneVとFT600をクレジットカードサイズのボードに搭載したFPGAボードです。

 転送レートの理論値はデータ16bit幅・100MHz動作という仕様から、200MB/s (MByte/sec 以下同様)となっています。
アプリケーションで計測を行った結果、下記のようになりました。

  • 送信:約195MB/s
  • 受信:約180MB/s


クリックして全体を表示

 

計測の詳細については下記を参照してください。

 

設定

以下の設定で測定を行いました。

  • FT600の動作モード:245 FIFO, 100MHz
  • 測定範囲:0.1MB(104858 Byte)~50MB を0.1MB刻みで500点
  • 測定回数:100回を平均
  • D3XXデバイスドライババージョン:v1.1.0.0
  • 実験ボード:EDA-009

 

送信

 FT600からFPGAへデータを送信し、ステータスが送信完了となるまでの時間を測定します。FPGAではデータは読み捨てています。
アプリケーションの送信プログラムは下記のようにしました。

	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;

送信レートの観測結果をグラフ化したものが下記になります。約195MBに近づいています。

 ある一定量のデータが出力されると出力が一時中断します(RXFが上がる)。今回の観測では0x200, 0x400, 0x600 または 0x800 Wordsで中断が発生しました。
0x200 Words以下では中断しませんでした。これはFT600内部の出力バッファサイズと一致します。
中断時間は16~2186 clockとまちまちでした。

SignalTapでの観測波形

クリックで全体を表示

 

 

受信

 アプリケーションからの受信開始を受けてFPGAからFT600へデータを送信し、ステータスが受信完了となるまでの時間を測定します。
アプリケーションの受信プログラムは下記のようにしました。

	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;

 

受信レートの観測結果をグラフ化したものが下記になります。約180MBに近づいています。

 

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

SignalTapでの観測波形

クリックで全体を表示

 

 

下記もご参照ください

 

お問い合わせについて

開発ツールの使い方などは、弊社のサポート外とさせていただいております。
ご担当の代理店様などにお尋ねください。

ソースなどの提供は行っておりません。予めご了承ください。

 


[kw] 2016-04-22 FT600 EDA-009 EDX-009 USB-106


[]