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
[]