0

I'm working on a project which needs to collect data from FPGA. I'm using an FTDI FT2232H UART/FIFO IC. According to the datasheet, the chip can transfer up to 40 Mbytes/s in single-channel synchronous FIFO mode. However, when I use the Linux system (Ubuntu 20.04), the transfer speed I get is only 10 Mbytes/s.

This is the C++ code I use:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/time.h>
#include "ftd2xx.h"
#include <iostream>
#include <chrono>
#define BUF_SIZE 0x10

#define MAX_DEVICES 1000
#define OneSector 8
int main(int argc, char *argv[]){
    system("sudo rmmod ftdi_sio");
    system("sudo rmmod usbserial");
    system("setserial /dev/ttyUSB0 low_latency");
    system("setserial /dev/ttyUSB1 low_latency");

    FT_STATUS ftStatus;
    FT_HANDLE ftHandle0;
    FT_HANDLE ftHandle1;
    UCHAR Mask = 0xFF;
    UCHAR Mode;
    UCHAR LatencyTimer = 2; //our default setting is 16
    int retCode = EXIT_FAILURE;
    DWORD libVersion = 0;
    static FT_PROGRAM_DATA Data;
    char *BufPtrs[3]; // pointer to array of 3 pointers
    char Buffer1[64]; // buffer for description of first device
    char Buffer2[64]; // buffer for description of second device
    
    BufPtrs[0] = Buffer1;
    BufPtrs[1] = Buffer2;
    BufPtrs[2] = NULL; // last entry should be NULL

    UCHAR rxBuffer[65536] = {0};
    // memset(rxBuffer,0,1028);
    DWORD byteCount;
    auto start = std::chrono::high_resolution_clock::now();
    auto stop = std::chrono::high_resolution_clock::now();
    auto duration = std::chrono::duration_cast<std::chrono::microseconds>(stop - start);
    double mbps;
    double secondsElapsed;
    // DWORD devIndex = 0; // first device
    // char Buffer[64]; // more than enough room!

    DWORD RxBytes = 8;
    DWORD BytesReceived;
    DWORD numDevs;
    // char RxBuffer[OneSector];
    ftStatus = FT_GetLibraryVersion(&libVersion);
    if (ftStatus == FT_OK)
    {
        printf("D2xx Library version = 0x%x\n", (unsigned int)libVersion);
    }
    else
    {
        printf("Error reading library version.\n");
        return 1;
    }

    ftStatus = FT_ListDevices(BufPtrs,&numDevs,FT_LIST_ALL|FT_OPEN_BY_DESCRIPTION);
    if (ftStatus == FT_OK) {
    // FT_ListDevices OK, product descriptions are in Buffer1 and Buffer2, and
    // numDevs contains the number of devices connected
    if(numDevs<=0){
        goto exit;
    }
    printf("%s\n", Buffer1);
    printf("%s\n", Buffer2);
    printf("Number of ports: %d\n", numDevs);
    }
    else {
    // FT_ListDevices failed
    }
    ftStatus = FT_Open(0, &ftHandle0);
    if(ftStatus != FT_OK) {
        printf("FT_Open(%d) failed\n", 0);}
    else{
        printf("Port 0 FT_Open succeeded.  Handle is %p\n", ftHandle0);}
    
    
    Data.Signature1 = 0x00000000;
    Data.Signature2 = 0xffffffff;
    Data.Manufacturer = (char *)malloc(256); /* E.g "deponce" */
    Data.ManufacturerId = (char *)malloc(256); /* E.g. "FT" */
    Data.Description = (char *)malloc(256); /* E.g. "USB HS Serial Converter" */
    Data.SerialNumber = (char *)malloc(256); /* E.g. "FT000001" if fixed, or NULL */
    if (Data.Manufacturer == NULL ||
        Data.ManufacturerId == NULL ||
        Data.Description == NULL ||
        Data.SerialNumber == NULL)
    {
        printf("Failed to allocate memory.\n");
        retCode = 1;
        goto exit;
    }
    ftStatus = FT_EE_Read(ftHandle0, &Data);
    if(ftStatus != FT_OK) {
        printf("FT_EE_Read failed\n");
        retCode = 1;
        goto exit;
    }
    printf("FT_EE_Read succeeded.\n\n");
    printf("Signature1 = %d\n", (int)Data.Signature1);          
    printf("Signature2 = %d\n", (int)Data.Signature2);
    printf("Version = %d\n", (int)Data.Version);
    printf("VendorId = 0x%04X\n", Data.VendorId);               
    printf("ProductId = 0x%04X\n", Data.ProductId);
    printf("Manufacturer = %s\n", Data.Manufacturer);           
    printf("ManufacturerId = %s\n", Data.ManufacturerId);
    Mode = 0x40;
    if(FT_SetBitMode(ftHandle0, Mask, Mode) == FT_OK){
        printf("set bit mode succeeded\n");}
    else{
        printf("set bit mode failed\n"); retCode=1; goto exit;}
    
    ftStatus = FT_SetLatencyTimer(ftHandle0, LatencyTimer);
    FT_SetUSBParameters(ftHandle0, 0x40000, 0x40000);
    FT_SetFlowControl(ftHandle0, FT_FLOW_RTS_CTS, 0x0, 0x0);
    FT_Purge(ftHandle0, FT_PURGE_RX);
    ftStatus = FT_SetTimeouts(ftHandle0, 500, 500);
    if(ftStatus == FT_OK){std::cout<<"set FT_SetTimeouts success."<<std::endl;}
    start = std::chrono::high_resolution_clock::now();
    for(int i = 0; i < 16384; i++){
        std::cout<<i<<std::endl;
        if(FT_Read(ftHandle0, rxBuffer, 65536, &byteCount) != FT_OK || byteCount != 65536) {
                        printf("Error while reading from the device. Exiting.\r\n");
                        goto exit;
                    }
    }
    std::cout<<std::endl;
    stop = std::chrono::high_resolution_clock::now();
    duration = std::chrono::duration_cast<std::chrono::microseconds>(stop - start);
    std::cout << "Read 1GB from the FTDI in : "
    << duration.count()/1000000. << " seconds" << std::endl;
    mbps = 1024 / (duration.count()/1000000.);
    printf("Average read speed: %0.1f Mbps.\r\n", mbps);
    exit:
        return retCode;
}

Here is the VHDL code:

library IEEE;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
entity test_syn_fifo is
port
(
    CLK60M: in std_logic;
    CLK50M: in std_logic;
    TXE   : in std_logic; 
    DATA  : buffer std_logic_vector (7 downto 0):="00000000";
    WR    : buffer std_logic:='1';
    );
end entity;

architecture Behavioral of test_syn_fifo is
    begin
    process(CLK60M,TXE, WR)
    begin
        if(CLK60M ='1'and CLK60M'event)then
            if(TXE='0')then
                DATA <= DATA+1;
                WR<='0';
            else
                DATA <= DATA;
                WR<='1';
            end if;
        else
            DATA <= DATA;
            
        end if;
    end process;

end Behavioral;

Could you give me some suggestions on how to speed up in the Linux?

wovano
  • 4,543
  • 5
  • 22
  • 49
  • Thanks for your patient reply, after some research, I found that it's been a well-known problem since 2018 https://github.com/0x6a77/JD2XX/issues/9 – deponce ye Jan 02 '23 at 09:29
  • You can create an answer with a summary of the problem and a link to that Github issue. It is allowed to answer your own question and you could even mark the answer as accepted so others will be able to find this solution as well in the future. – wovano Jan 02 '23 at 09:44

0 Answers0