I A High Speed Universal Serial Bus Controller Device Gaurav Jain Research Supervisor: Mr. Joseph N.Y. Aziz Research Professor: Prof. Roman Genov August 31, 2006 Intelligent Sensory Microsystems Laboratory Dept. of Electrical and Computer Engineering University of Toronto
22
Embed
A High Speed Universal Serial Bus Controller Deviceindividual.utoronto.ca/gauravjain/FinalReport_HighSpeed...communication protocol between the Host PC, the USB controller and the
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
I
A High Speed Universal Serial Bus Controller Device
Gaurav Jain
Research Supervisor: Mr. Joseph N.Y. Aziz Research Professor: Prof. Roman Genov
August 31, 2006
Intelligent Sensory Microsystems Laboratory Dept. of Electrical and Computer Engineering
University of Toronto
I
Table of Contents Introduction..................................................................................................................….. 1
Universal Serial Bus…………………….………………………………………………..1
Physical Component Specifications and Availability………………………..……3
The QuickUSB™ Library…………………………………………………………4
The Connector PCB…………………….………………………………………………...5
Schematic Diagram…………………………………………………………….…5
Pinout Description………….……………………………………………………..6
Layout Capture………………..…………………………………………………. 7
Communication and Code…………………..……………………………………………8
Sample Code……………………………………………………………………..9
Testing……………………………………………….…………………………………..15
PCB and Layout Recommendations……………………………………………………16
References……………………………………………………………………………….16
APPENDIX I – QUSB2 Pin Descriptions…………………………..…………………..18
APPENDIX II – QuickUSB Library Function List………………..…………………..19
APPENDIX III – QUSB2 Schematic Diagram……………..………………………….20
1
1 Introduction
My Project as a summer student at the Intelligent Sensory Microsystems Laboratory at the University of Toronto is to develop and implement a USB device controller that will accept data from a client, and transfer it to the host PC through a 480Mbit/s USB connection. This controller is specifically developed to work with the Field Programmable Gate Arrays (FPGA) catering to high-bandwidth real time data capture. The diagram below (Fig.1.1) displays the basic block diagram of the communication protocol between the Host PC, the USB controller and the FPGA module.
Fig.1.1 Communication block diagram between the Host PC and the FPGA module via
the USB Controller This report provides the necessary background in USB interfaces followed by the
comprehensive explanation of the project implementation making use of the various schematics and relevant software code. Finally, it brings out the various testing methodologies and the output results.
2 Universal Serial Bus (USB)
Universal Serial Bus (USB) is a serial bus standard to interface devices. USB protocol was designed to economically replace the many low-speed ports present in computers. A total of 127 devices or ‘nodes’, can be connected to a single USB port, organized in a ‘tiered star’ topology.
USB devices can operate at one of three different speeds: 1.5 Mbit/s (Low
Speed), 12 Mbit/s (Full Speed) and 480 Mbit/s (High Speed, also known as USB 2.0). More information on the USB can be found at www.usb.org.
HOST PC
USB
Controller
FPGA
Module USB 2.0 Parallel
2
3 The QuickUSB™ Chip
The QuickUSB™ QUSB2 Plug-In module made available by Bitwise Systems (www.quickusb.com) has been the basis of this project. The module consists of hardware parallel and serial ports that can be connected to the existing circuit design. The module comes with the QuickUSB™ Library which contains user-callable software functions that transfer data to and from the hardware ports over the USB. The functional description of the QuickUSB™ Plug-In module is provided below: 3.1 Physical Interface
The QuickUSB QUSB2 Plug-In Module is a 2” x 1 ½” circuit board that implements a bus-powered Hi-speed USB 2.0 endpoint terminating in a single 80-pin target interface connector. The mating connector is a Hirose FX8-80S-SV. Please refer to Appendix I for the Pin Description Table of QUSB2.
Fig.3.1 QUSB2 Functional Block Diagram The target interface consists of: • One 8 or 16-bit High-Speed Parallel Port (HSPP) • Up to five general-purpose 8-bit parallel I/O ports • Two RS-232 compatible ports • One I2C master port • One soft SPI master port supporting up to 10 slave devices • One FPGA configuration port (Altera PS or Xilinx SS)
We only deal with the HSPP for our functionality. However, the other ports can be used in future, as per the requirements.
USB 2.0
I2C
SPI (x10) RS-232 (x2)
Low-Speed Parallel (x3)
High-Speed Parallel (x2)
FPGA
QuickUSB™ QUSB2 Plug-In
Module
3
3.1.1 High-Speed Parallel Port
The high-speed parallel port is configurable as an 8 (WORDWIDE = 0) or 16 (WORDWIDE = 1) bit synchronous parallel port. It delivers a sustained data rate of up to 20 MB/s and a burst rate of up to 96MB/s for packets up to 512 bytes long. The high-speed interface consists of the data port FD [15:0], control lines CMD_DATA, REN, WEN, nREN, nWEN and GPIFADR [8:0]. The port can be used as a multiplexed command/data bus by decoding CMD_DATA (CMD = 0, DATA = 1 in the target logic. Reads are indicated by REN = 1/nREN = 0 and writes are indicated by WEN = 1/nWEN = 0. If the address bus is configured to be active, concurrent with reads or writes the GPIFADR bus contains the address of each data element read from or written to FD [15:0]. 3.2 Physical Component Specifications and Availability 3.2.1 List of Components on the QUSB2
The following table provides a complete list of the various different parts/components on the QUSB2 module relevant for the project use. Please refer to Appendix III for the schematic diagram. Part Name
Manufacturer's Name
Part Number
Source and Availability Link (as of August 31 2006) FORCE/ HEILIND ELECTRONICS 1755 units SAGER ELECTRONICS 1579 units
USB Sockets
Mill-Max
897-30-004-90-000000
DIGI-KEY CORPORATION 38 units
FX2 CLOCK (24 MHz)
ECS INC. INTERNATIONAL
ECS-240-20-5PDN-TR
DIGI-KEY CORPORATION 147 units
3.3V Regulator and VBUS Switch
Texas Instruments
TPS2150IPWP
DIGI-KEY CORPORATION 168 units
EZ-USB FX2LP(TM) USB Microcontroller
Cypress
CY7C68013-128AC
DIGI-KEY CORPORATION 3885 units
I2C EEPROM
Microchip Technology
24LC128-I/SN
DIGI-KEY CORPORATION 9581 units
4
3.2.2 Cypress EZ-USB FX2LP™ USB Microcontroller
Cypress’s EZ-USB FX2LP™⎢ is a USB 2.0 integrated microcontroller. It integrates the USB 2.0 transceiver, SIE, enhanced 8051 microcontroller, and a programmable peripheral interface in a single chip. The ingenious architecture of FX2LP results in data transfer rates of 56 Mbytes per second, the maximum allowable USB 2.0 bandwidth, while still using a low-cost 8051 microcontroller. The General Programmable Interface (GPIF) and Master/Slave Endpoint FIFO (8- or 16-bit data bus) provides an easy and glue- less interface. The block diagram of the Cypress microcontroller is provided below:
Fig 3.2.1 Block Diagram of Cypress EZ-USB FX2LP™ USB Microcontroller 3.3 The QuickUSB™ Library
The QuickUSB™ Library is included with the QUSB2 and provides the programming language interface to the QuickUSB Plug-in Module. The QuickUSB Library includes support for many popular programming languages including Visual C, Visual Basic, Delphi, C++ Builder and LabView. Please refer to Appendix II for a complete list of functions available in the QuickUSB™ library. A complete description of each library function is provided in the QuickUSB™ User’s Guide Note: The detailed communication protocol is described along with code examples in section 5 of this document under the heading Communication and Code.
5
4 The Connector PCB
The QUSB connecting header (Hirose FX8-80S-SV) is a high density, surface-mount connector. In order to facilitate the testing of the module, a printed circuit board (PCB) was designed from scratch, which brought out the high density pins to standard 8-pin headers. The PCB was designed on DXP 2004 (Altium Designer) software and fabricated on the LPKF ProtoMat C20 at the ECE Design Centre, University of Toronto. Therefore, the test setup includes the Connector PCB mounted on top by the QUSB2 module. The schematics and the layout of the PCB are provided below: 4.1 Schematic Capture
Fig.4.1 Schematic Capture of the Connector PCB
6
4.2 Pinout Description
Header Name Header Pin No(s).
QUSB2 Pin Description
QUSB2 Pin No(s).
[8..1] PA[7..0] [17,15,13,11,9,7,5,3] JP1
[16..9] GND (1,19,37,55,79)
[8..1] PB[7..0] / HSPP FD[7..0]
[35,33,31,29,27,25,23,21] JP2
[16..9] GND (1,19,37,55,79)
[8..1] PC[7..0] [53,51,49,47,45,43,41,39] JP3
[16..9] GND (1,19,37,55,79)
1 ResetB 4
2 CLKOUT 6
3 IFCLK 8
4 INT4 10
5 CTL0 22
6 CTL1/REN 24
7 CTL2/WEN 26
8 CTL3 28
JP4
[16..9] GND (1,19,37,55,79)
1 CTL4 30
2 CTL5 32
3 RDY0 40
4 RDY1 42
5 WAKEUP_B 74
6 SW_EN 76
7 VCC (2,20,38,56,80) 8 Not Used
JP5
[16..9] GND (1,19,37,55,79)
Table 4.2 Pinout Description of the Connector PCB
7
4.3 Layout Capture
Fig.4.3 Layout Capture of the Connector PCB Note: The PCB designed has the ringing effect on the pins. Hence, the current test setup includes soldered surface mount capacitors (56 pF) attached to the PORTB (HSPP) to remove any unwanted oscillations and stabilize the logic levels. More information is provided in the PCB recommendations section.
8
5 Communication and Code
The general procedure to communicate with the QuickUSB module follows four simple steps which are described below represented by a flowchart.
A complete and comprehensive description of all the QuickUSB Library API functions is provided in the QuickUSB User Guide.
Call QuickUsbFindModules to get a list of available
modules. The list is returned as NULL-delimited string. And then,
provide a way to select the required device by a means of a
device handle
Call QuickUsbOpen
and pass in the device name. A new device ID is returned on
success
Call the data transfer functions needed by your application. For
example:
QuickUsbReadData or QuickUsbWriteData
Call QuickUsbClose
to close the device connection passing in the device handle as
a parameter
Find
Open
Transfer
Close
9
5.1 Sample Code
The following section includes some of the sample codes written in order to test the module. The code is written and developed on Microsoft Visual C++ platform. 5.1.1 Sync Read Test //A sample program to test a stream of data coming into the PC via the QuickUSB module (Synchronized Read) //Author: Gaurav Jain, Summer Student, University of Toronto. //Date: 15.07.2006 //Last Revised: 29.08.2006 #include "stdafx.h" #include <stdio.h> #include <stdlib.h> #include <windows.h> #include <time.h> #include <conio.h> #include "quickusb.h" #define PACKET_LENGTH 512 //The number of bytes to be transferred
//at a time #define BUF_SIZE 512 //The size of the data array #define MEGA (1024 * 1024) int main() { char devName[16]; //Char array to store the device name unsigned char * data; //Buffer array to store the data int result; int errorResult; HANDLE hDevice; //Device Handler unsigned long length = PACKET_LENGTH; char * FileName; unsigned long byteswritten; FILE * outFile; //Output File Stream int shutdown = FALSE; DWORD start, finish; double elapsed_time; double bytecount = 0; int index; //Provide the output file name FileName = "example.txt"; //Trying to access the file and create one if not present outFile = fopen(FileName, "w+b"); if(outFile == NULL) {
10
printf("Unable to open the output file\n"); return 1; } // Allocate buffers data = (unsigned char*)malloc(BUF_SIZE); data[0] = '\0'; //Look for connected usb devices to QuickUSB result = QuickUsbFindModules(devName, 16); if(result == 0){ printf("Cannot find any connectted devices\n"); return 1; } //print out the device names(s) printf("%s\n", devName); //Open the QuickUSB device result = QuickUsbOpen(&hDevice, devName); if(result == 0){ printf("Device open failed\n"); return 1; } printf("Reading data\n"); // Get the current time start = GetTickCount(); //Read data into the PC //A simple while loop that will read the X (=10 in this case) number of blocks (Each 512 bytes long). int i =1; while (i < 11) { //Reading Data from the device result = QuickUsbReadData(hDevice, data, &length); printf("Reading Block Number %i\n",i); if(result == FALSE) { printf("Error occured\n"); return 1; } //Print out each byte to the output file stream for (unsigned int j =0; j < PACKET_LENGTH; j++ ){ byteswritten = fprintf(outFile, "%d\n", data[j]); if(byteswritten >= 0){ bytecount = bytecount++; }
11
} i++; } // Get the current time finish = GetTickCount(); elapsed_time = (double)(finish - start) / 1000; fclose(outFile); //Done writing, Close the file QuickUsbClose(hDevice); //Closing the device //Time calculations printf("Elapsed time %f seconds to transfer %f bytes.\n", elapsed_time, bytecount); printf("Average throughput %f Megabytes per second.\n", (bytecount / MEGA) / elapsed_time); Sleep(5000); // let the user see the stats free(data); //Deallocating the buffer return 0; } 5.1.2 Async Read Test #include "stdafx.h" #include <stdio.h> #include <stdlib.h> #include <windows.h> #include <time.h> #include <conio.h> #include "quickusb.h" #define MEGA (1024 * 1024) int main(int argc, char* argv[]) { char * FileName; FILE * outFile; unsigned char * buffer[256]; DWORD start, finish; HANDLE hDevice; unsigned long blocksize; unsigned long byteswritten; unsigned long error; unsigned long bytesread[256]; double bytecount = 0; double elapsed_time; int bufcnt; // buffer count int index;
12
int shutdown = FALSE; int result; int lastIndex; char nameList[128]; unsigned char transaction[256]; FileName = "testOuput.txt"; blocksize = 512; bufcnt = 6; if ((blocksize < 1) || (blocksize > (64 * 1024 * 1024))) { ProgramSyntax(); Sleep(5000); // let the user see the error return 1; } if ((bufcnt < 2) || (bufcnt > 253)) { ProgramSyntax(); Sleep(5000); // let the user see the error return 1; } outFile = fopen(FileName, "w+b"); if (outFile == NULL) { printf("Unable to open file %s for output\n", FileName); Sleep(5000); // let the user see the error return 1; } // Allocate buffers for (index = 0; index < bufcnt; index++) { buffer[index] = (unsigned char *)malloc(blocksize); if (buffer[index] == NULL) { printf("Unable to allocate buffer number %d\n", index); fclose(outFile); Sleep(5000); // let the user see the error return 1; } } // Find the QuickUSB modules in the system QuickUsbFindModules(&nameList[0], 128); // Open the first QuickUSB device result = QuickUsbOpen(&hDevice, (&nameList[0])); if (result == FALSE) { QuickUsbGetLastError(&error); printf("QuickUsbOpen error %d\n", error); fclose(outFile);
13
Sleep(5000); // let the user see the error return 1; } // Set QuickUSB I/O timeout to 100 seconds // This is required with a 64 Meg block size and 253 buffers.0 // This value should probably be calculated to something reasonable. result = QuickUsbSetTimeout(hDevice, 1000000); if (result == FALSE) { QuickUsbGetLastError(&error); printf("QuickUsbSetTimeout error %d\n", error); fclose(outFile); QuickUsbClose(hDevice); Sleep(5000); // let the user see the error return 1; } // Get the current time start = GetTickCount(); // Start up several asynchronous read commands printf("Starting up %d read requests.\n", bufcnt); for (index = 0; index < bufcnt; index++) { result = QuickUsbReadDataAsync(hDevice, buffer[index], &blocksize, &transaction[index]); if (result == FALSE) { QuickUsbGetLastError(&error); printf("QuickUsbReadDataAsync error %d index %d\n", error, index); fclose(outFile); QuickUsbClose(hDevice); Sleep(5000); // let the user see the error return 1; } } index = 0; while (TRUE) { // Wait for the next QuickUSB read operation to finish result = QuickUsbAsyncWait(hDevice, &bytesread[index], transaction[index], FALSE); if (result == FALSE) { QuickUsbGetLastError(&error);
14
printf("QuickUsbAsyncWait error %d index %d\n", error, index); fclose(outFile); QuickUsbClose(hDevice); Sleep(5000); // let the user see the error return 1; printf("exiting while"); } printf("done while"); // Did write function complete? if (bytesread[index] == blocksize) { bytecount += blocksize; } // Write the block to disk //byteswritten = fwrite(buffer[index], 1, blocksize, outFile); byteswritten = fprintf(outFile, "%X\n", buffer[index]); if ((shutdown == TRUE) && (index == lastIndex)) { break; } // Check if any key was pressed if (shutdown == FALSE) { if (_kbhit()) { shutdown = TRUE; printf("Program is shutting down, waiting for queued I/O to finish.\n"); } } // Start a new QuickUSB read if (shutdown == FALSE) { lastIndex = index; result = QuickUsbReadDataAsync(hDevice, buffer[index], &blocksize, &transaction[index]); if (result == FALSE) { QuickUsbGetLastError(&error); printf("QuickUsbReadDataAsync error %d index %d\n", error, index); fclose(outFile); QuickUsbClose(hDevice); Sleep(5000); // let the user see the error return 1; } } // Increment index index++; if (index == bufcnt) {
15
index = 0; } } // Get the current time finish = GetTickCount(); elapsed_time = (double)(finish - start) / 1000; fclose(outFile); QuickUsbClose(hDevice); for (index = 0; index < bufcnt; index++) { free(buffer[index]); } printf("Elapsed time %f seconds to transfer %f Megabytes.\n", elapsed_time, bytecount / MEGA); printf("Average throughput %f Megabytes per second.\n", (bytecount / MEGA) / elapsed_time); Sleep(5000); // let the user see the stats return 0; }
6 Testing
Major emphasis was put on the testing of the module during the project tenure. Tektronix™ Pattern Generator was used to generate regular waveforms and provide data coming into the QUSB2 module. The Pattern Generator clock was synchronized with the chip clock running on the same frequency of 48MHz (20.8333 ns) to avoid any timing problems. The 8051 Microcontroller clock was also set to 48MHz to acquire data as accurately as possible and avoid any duplication of data.
The transfer of data takes place in bursts of 512 bytes at a time and several such blocks are transferred during one read cycle. After much compliance testing it was observed from the output that some of those blocks had corrupted data. This was caused to the ‘Ringing Effect’ on the circuit. There was unwanted oscillation of voltage and current which caused the undesirable triggering of the logic levels in the circuit. The problem was fixed by soldering surface mount capacitors (~= 56 pF) in order to stabilize the logic levels and remove the oscillation.
The testing has revealed certain hardware issues for which the recommendations
have been provided in the next section.
16
7 PCB and Layout Recommendations
USB 2.0 high-speed setup is used to transfer data at 480 Mbps. This high-speed signaling requires a greater level of attention to component selection, supply decoupling, signal line impedance, and noise while designing PCBs.
The testing of current setup has revealed the ringing effect on the logic levels. The unwanted oscillations cause wrong data to be sampled. To prevent this, appropriate space for the capacitors need to be taken into consideration in the layout design. The current setup included soldered surface mount capacitors (56 pF) that stabilize the logical levels. For some PCBs, the exact capacitor value should be determined by trial and error.
Also, the data only transfers in blocks of 512 bytes in one read. So, if the user is
trying to read data any longer than 512 bytes, there will be skipped bytes that should be accounted for. The sample code provided reads data in several cycles, each reading only 512 bytes at a time.
2. Universal Serial Bus 2.0 Specification at http://www.usb.org/developers/docs/
3. QuickUSB User Guide available at www.quickusb.com
4. Digital Electronics Learning System Based on FPGA Applications
Camilo Quintans, M. Dolores Valdes, Mª Jose Moure, Luis Fernandez-Ferreira, Enrique Mandado Instituto de Electrónica Aplicada “Pedro Barrié de la Maza”, Universidad de Vigo (Spain) [email protected]
17
APPENDICES
18
APPENDIX I – QUSB2 Pin Descriptions
19
APPENDIX II – QuickUSB Library Function List QuickUSB Base API