Friday, March 11, 2011

USB inside an FPGA

I'm working on updating the MHZ100Q project, and for a low-cost USB interface I want to put all of the USB functions inside the FPGA. So externally the interface consists of a connector and 3 resistors - can't get much lower cost than that.
I found 3 open source USB implementations:
1) opencores.org has the usb1_funct and usb_phy Verilog projects, which implement a USB device controller and physical layer (transceiver) respectively.
2) Joris has implemented the USB Communication Device Controller (CDC) protocol in VHDL. CDC devices basically look like an RS232 serial port to the host PC. This one is intended for use with an external PHY chip, and supports both full-speed(12MB/s) and high-speed(480MB/s) operation. Source is available on his website at www.xs4all.nl/~rjoris/fpga/usb.html .
3) Robert E. Jenkins of Johns Hopkins has published the USBF_IFC VHDL core, which includes both controller and PHY functions. It's set up for a XESS board, and is available at www.xess.com/projects/FPGA-USB-V2/readmeusb-v2.php .

Evaluation


I ported all 3 to my custom PCB, and did a brief evaluation.
1) The opencores modules went together easily, and Linux sees the USB device. I didn't implement any data transfers to/from the USB device, but it looks easy to do.
2) I decided to use the Joris controller with the opencores soft PHY instead of an external chip. That limits me to full speed, but saves parts. After a bit of hacking around to get the signals and polarities right, the combination worked great. (Mixing VHDL and Verilog wasn't a problem). His test program gave about 10 megabytes/second transfer rates, which is just about the maximum possible rate for a full-speed device. I've posted my files to demo this combination on my website at www.sensicomm.com/main/downloads/index.shtml (the specific file is 110310cdc_usb.tgz).
3) USBF_IFC took a bit of hacking to get it to run on my board. As stated on the project web page, it was a project for lab classes and still has some quirks.

I've been using USBF_IFC for several months now to test my hardware, but going forward I'm planning to use the Joris core. It's operation seems solid, being able to treat it as a serial device is nice for writing host software, and I can go to high speed if I add an external PHY in the future.