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での観測波形
クリックで全体を表示
下記もご参照ください
- FT600関連製品特設ページ:https://www.hdl.co.jp/FT600/index.html
お問い合わせについて
開発ツールの使い方などは、弊社のサポート外とさせていただいております。
ご担当の代理店様などにお尋ねください。
ソースなどの提供は行っておりません。予めご了承ください。
[kw] TEC-FPGA 2016-04-22 FT600 EDA-009 EDX-009 USB-106
[]