ADC readout and USB2.0 data transfer with an FPGA

Recently I bought the Altera DE0 Development and Education FPGA board from Terasic. This board has a Cyclone III FPGA and some periphery on board. Also two expansion header to connect own hardware are brought out. The board gives me finally the chance to also do some FPGA developments at home. Even if it’s not the most powerful FPGA it is enough to play around and has an affordable price of around 100$.
As probably a lot of people have realized I like to play with ADCs and read them out into the computer. It’s my kind of “Hallo World” program when playing with electronics. I’m also trying to increase the speed of my readout when moving from one architecture to the next one. Or maybe for faster readout I need to change architecture :P.
The good part with the FPGA is that one has a real time platform and can avoid some hassle one gets when for example using a microprocessor like a Raspberry Pi running an operations system (see Raspberry Pi as an Oscilloscope @ 10 MSPS).
The DE0 Development board does not contain a USB interface for data read out. The only option to read out the data is to use the serial interface or the JTAG interface. Both are not very fast.
Therefore I decided to equip my FPGA with a USB 2.0 interface to be able to transfer with high speed the data into the PC.
This is not only important for me for this ADC project but also for some other projects I have in mind for the future.

As a USB 2.0 chip I picked the FT232H Single Channel Hi-Speed USB to Multipurpose UART/FIFO IC from FTDI (Future Technology Devices International). The chip provides a USB2.0 interface to several protocols like RS232, FT1248, SPI, FIFO …
I bought the development board UM232H for this chip which is a tiny board one can put on a breakout board.

Since I want to interface a fast ADC I took the AD9057 from Analog Devices which is available for different speed up to 80 MSPS. I have the 40 MSPS version to begin with. The ADC has a resolution of 8 bits.

Since ADC, USB controller and FPGA need to be connected I developed some circuits to do so.

Starting with the USB controller, which was put on a break out board and interfaced via some level shifter/buffer with the FPGA. The USB controller is run in FiFo mode which requires some setup in the EEPROM.

As can be seen in the drawing a 74HC4050 buffer was used to buffer RXF, TXE, RD, WR, OE and the 60 MHz clock from the USB interface and a 74HC245 bi direction level shifter was used to buffer the 8 bit for the data transfer line. A bidirectional buffer in needed since the 8 pins are used as an in and output.
I have the buffer and level shifter there to protect the FPGA since the 3.3 V of the FPGA and the 3.3V of the USB interface are not the same source. I don’t want to put on the FPGA pins the 3.3V of the USB controller, so it’s for protection.
And in fact I discovered that the 60 MHz signal pin is higher than 3.3 V when idle.
So the buffers are strongly recommended!

The next step was the design of the ADC PCB. The ADC comes as a SMD and therefore needs to be soldered. For this the CAD program Eagle was used and a PCB was created and etched.

This gives also the possibility to make a nice flat cable contact in order to connect nicely with the FPGA board. It should be noted that there is a 50 Ohm termination which can be connected by a jumper and is optionally. With unconnected jumper the input has a high impedance, with connected jumper there is 50 Ohm termination. This connection is probably not optimal but it is an easy option to switch impedance.

Etched and soldered the PCB looks like this:

With this all hardware is available to be connected to the FPGA.
What is missing is the design code for the FPGA connecting all the parts together. The code is written in VHDL.
Which will be described in the following. For the design the Altera Quartus II development framework was used and a control part for the USB device and for the ADC were designed. All parts are glued together forming a picture like this:

Several parts can be found in the schematic:
FreqDiv: This is a frequency divider to produce the clock frequency for the ADC from the local clock (50 MHz) on the D0 board.

ADCRead: This basically reads the 8 bits from the ADC on every raising edge of the clock.

FiFo: This is a FiFo from the Altera IP MegaWizard. It has two separate clock inputs, one for the write clock and one for the read clock. The FiFo is needed at this stage since we need to synchronize two different clock domains. We have on the writing side the clock of the ADC and on the reading side we have the clock of the USB controller (60 MHz) see data sheet for further information.

FiFo_USB_CONTROL: Does the interfacing between the USB controller and the FIFO, in order to tell the FiFo when to read from it, to check if data is available and to interface the State Machine of the USB interface.

The state Machine was tested for writing to the USB controller only, so I’m not 100% sure if the read is working or not.

On the PC side a readout can be performed by using the official libftd2xx library from FTDI or by using the open source library libftdi which comes with most Linux distributions.
I use the libftdi open source library since I have a better performance when reading from the USB interface. I could read up to 44 MBytes/second when reading from the interface.
The library comes with a nice example for performance testing:stream_test.c
After compilation the code can be run with the commandstream_test -n out.txt
which will write the read data into the out.txt file and will show the speed of readout.
It can be necessary to modify the code

if (ftdi_usb_open_desc(ftdi, 0x0403, 0x6014, descstring, NULL) < 0)

in order to set the right device. This is also a good starting point for further development.

With all devices in place everything looks like:

In order to test if the ADC is working properly a sine wave was generated by using a DAC and an Arduino and send to the ADC connected with the FPGA. The sine wave has approximately a amplitude of 1Vpp which is the range of the ADC.
After readout from the FPGA the bytes from the ADC are dumped in a file. Then each bytes is converted into an integer and plot by gnuplot. Since the ADC is 8 bit the sine wave oscillates between 0 and 255.

Share this:

Like this:

7 comments on “ADC readout and USB2.0 data transfer with an FPGA”

I am trying to develop the VHDL code for ltc2314 to FPGA (spartan 6) to USB (FTDI mini module) to LabVIEW (FTDI driver). I am just starting FPGA coding not easier to grasp your state machine. Would it be possible for you to send me commented version of the code. I will acknowledge your help if I am successfull in finishing my board develpment
Thanks & best regards
Yogita

G21 is the 50 MHz clock pin connected to the oscillator. The clock is divided to change the sample rate of the ADC. This is done by simply holding a logic low for a certain amount of 50 MHZ pulses and a logic high for a certain amount. Simple counting. By this you can divide the clock. I think in the pic the clock of the ADC is 25 MHz had just a quick look in the code.

Thanks for answers. How do you calculate the sample rate? by default the sample rate of AD9057 are 40, 60 and 80 MSPS. What is your desired sample rate in this project? Does it work based on one sample per one hz? Could you please help me with your calculation.
And one more, in your vhdl code:
g_DIV : integer := 50000
.
.
.
elsif(rising_edge(clk)) then –syncrone reset
–if(nrst_in=’0′) then
–tmp<=x"00000000"; — on reset set to 0
–q_out<='0';
–else
tmp<= tmp + 2;
–end if;

if(tmp=g_DIV) then –we devide
tmp<=0;
q_out<=not q_out;
end if;

What is the output frequency? Is adc sampling rate equal to this?
Thanks