USB Interface

This is curently just a slave interface, allowing a PC to talk to the project through a virtual COM port. It does not allow the project to use USB peripherals - that would require a lot more software development work.

Up till recently I have been quite happy to use the standard serial (RS232) and parallel (printer) ports of the PC. These are simple and easy to use for simple jobs. Most microcontrollers have a serial port that can talk to a PC through an RS232 level shifter. Printer port handshaking can be very simple and fast, and I used this for transferring data to my FPGA project.

Technology moves on, in the form of USB. Almost all computer users have some USB devices, but far fewer have made their own.

USB interfaces look a lot more work than simple serial ports and parallel ports. I do not look forward to the work of implementing one from scratch. Unfortunately it looks inevitable that almost all new PC peripheral products will have to use USB. Fortunately chip makers have produced chips that make it easy to implement USB peripherals.

Floortop PC and Win98

My scanner worked perfectly, but I have tried two card readers (An A-Tec CR-V10-U6 6-in-1, and a TwinMOS 7-in-1) and both crash as often as a ZX81. When they did, sometimes even ctrl-alt-delete did not work! I'm sure it is the driver software at fault. I hear software for the target device is a real headache, and is even more so for the PC.

Talking to others, consensus was that USB support doesn't even start to get reliable until Win98SE. Using Windows update, I upgraded to the latest drivers but this didn't help.

Laptop PC and WinXP

I changed over to a laptop in an effort to reduce the weight of stuff I have to shift when I move house. I can carry it to contract clients to do work on site if needed, and take it home to use over Christmas to stave off boredom. It isn't silent, but is certainly quieter. It came with WinXP installed, and has a built-in carder reader. It doesn't take CF cards, but given the number of pins needed to drive one this is forgivable. My external card reader works fine for this job.

USB interface in FPGA

It is possible to put USB interface logic inside the FPGA. There is an EDIF module publicly available but without VHDL source. I suspect this is non-trivial, consuming a third of an X2SC200. Thus it is probably simpler and more economical to use a dedicated USB chip.

The Cypress "EZUSB_80" chip might provide a suitable interface. Note that it is an 80-pin surface mount device.

USB chips

As expected, these are available in many forms. Here are a few

  Processor Core
Atmel 8051 (Flash ROM)
AVR (Mask ROM, or SRAM downloaded from off-chip serial EEPROM)
Cypress 8051 (8-bit).
M8 (8-bit).
CY16 (16-bit)
None - interface only (USB 1.0)
Microchip PIC (8-bit. Flash ROM)
FTDI None yet - interface only

The 8051 looks like it allows USB peripheral manufacturers to avoid writing code specific to a single chip-manufacturer's proprietary architecture.
I'm surprised Flash pioneers Atmel haven't used flash with their own core.

Intel Press - USB Design by Example is a book I bought as a first look into the subject. Includes a CD ROM. Example code is for the 8051. I felt the book a bit 'light' in that much of it seemed an advertisement for why one should migrate to USB and what kind of clever applications there were.

RS sell the Cypress development kits, the CY7C63613-SC, and several PIC micros with USB.

USB the hard way

The hard way is to use a chip that is a low-level USB interface and write driver software to handle the complex USB protocol. The benefit is to have tighter control of what goes on, at the expense of more work from the programmer and the CPU.

Carsten Strottman's Micro USB website looks a pretty good start on adding USB master/slave capability to old machines (Atari 800XL/XE, ST, Apple, C64).

Cypress make the SL811 used in the project above. It comes in PLCC28 or TQFP48 package.

USB the easy way

The easy way is to use a chip that does the low-level USB protocol and presents the user with a high-level interface.

FTDI make such chips, which are used by many companies around the world.

The FT232 provides an asynchronous serial interface.

The FT245BM provides a FIFO interface. This is much faster.

Nial Stewart
USB
VCC 1 2  
D00 3 4 D01
D02 5 6 D03
D04 7 8 D05
D06 9 10 D07
? 11 12 rd_n
wr 13 14 ?
? 15 16 si_wu_n
rxf_n 17 18 ?
? 19 10 GND
Nial Stuart Developments says they make USB interfacing a doddle. He made a USB interface for the BurchEd B5, with professional-standard PCB to the same specs and tolerances as BurchEd boards. This is based on the FTDI FT245BM which he says makes USB interfacing a doddle. The data sheet says the entire USB protocol is handled by the chip. It has a FIFO interface with 8 data lines and four handshake lines.

I plumped for the easy option, as I just want my laptop to be able to talk to my projects quickly.

I have ordered an FT245BM module with a DIP footprint for easy connection to 0.1" grid prototyping board. This was fairly cheap at £14. The chips were quoted at $5.75 one-off price.

Fitting the module

FTDI module
USB
BID <-- 1 24 D00
GND 2 23 D01
!RESET --> 3 22 D02
!RESET <-- 4 21 D03
GND 5 20 D04
3V3 out <-- 6 19 D05
GND 7 18 D06
SLEEP <-- 8 17 D07
SND/WUP --> 9 16 !RD
VCC_IO --> 10 15 WR
VCC_Ext --> 11 14 !TXE
VCC_Port <-- 12 13 !RXF
The module arrived and I looked to see how I could fit it to project. At this point the prototyping boards are very cramped, and there is no place left to fit the module. Seems no alternative but to add another board to the project. It is a socketable item, but the socket raises the height too much. I would have to solder it in directly.

I have managed to mount it in a socket, by removing the printer-port connector and making a small cut-out for the USB socket. The third PCB cannot fit as close as the FPGA board (0.6 inch pitch). Instead, it has to be 0.7 inches pitch. This will still fit in the case without shorting on the metal case.

Several devices use the data bus, it may be wise to wire them all in at once.

  • USB module
  • CPU in PLCC44 package (65C02,65C16, 63C09?)
  • 65C22 in PLCC44 for Atom/BBC operation
  • 16C552 in PLCC68, and RS232 comms.
  • RAM and ROM on same bus?
  • 68C50
  • 6551
  • 65C816
  • BBC BASIC
  • Joysticks
  • SD card
  • Compact flash card
  • SIO

In practice I don't have time to do all these at once, so I just fitted the USB module.

Interfacing

The handshaking lines are slightly misnamed.

!TXE (active low Transmission buffer Empty) is more like 'active high Transmission buffer Full'.
!RXF (active low Reception buffer Full) is more like 'active high Reception buffer Empty'.

USB_Tx_nStrobe --> WR Transmission buffer
USB_Tx_Wait <-- !TXE
USB_Rx_nStrobe --> !RD Reception buffer
USB_Rx_Wait <-- !RXF

Both are logic 1 after reset, when both buffers are made empty. It is better to think of them as active-low signals that indicate you can write to the Tx buffer, or should read from the Rx buffer. The target sees them both high at first, indictating 'don't read' and 'don't write'. When connected to the USB master, the USB_Tx_Wait pin goes low, indicating 'okay to write'.

I made these signals readable in d7 and d6. The read and write routines are very simple:

usb_rdch:
	bit	USB_STATUS		; D7 <-- BUSY, D6 <-- ACK
	bmi	usb_rdch		; high = wait
	lda	USB_DATA		; get the data byte
	rts
usb_wrch:
	bit	USB_STATUS		; D7 <-- BUSY, D6 <-- ACK
	bvs	usb_wrch		; high = wait
	sta	USB_DATA		; get the data byte
	rts

The chip is rated to 1 Mbyte/sec, but the 6502 cannot approach this speed through software handshaking. However it should be just about as fast as the slave printer port method.

PC software

Fairly simple, download the drivers from the FTDI site and uncompress them into a temporary directory. When the detects the USB module as new hardware and prompts for installing drivers, just direct it to the temporary directory.

Next, run HyperTerminal and connect to the newly-available COM5.

VHDL code

This is a bit tricky because the data bus is on the video RAM side. Originally I had just the RAM dual-ported, but to get the USB module sharing this local bus I had to dual-port the I/O space as well!

I modifed the code so that the ROM may also be on the local bus. I have not actually made it so because it would mean a lot of re-wiring. If needed, the ROM could simply be copied to the RAM chip.

Results

I wrote a little BASIC program to poll the USB module and print the characters to the screen. I installed the FTDI drivers, opened a virtual COM port (COM5), and typed away. The text appeared correctly. I wrote a similar program to try sending text to the PC, but got garbage back. This seems to be due to the data bus not being held long enough after the falling edge of the write pulse. So I made a little kludge to the VHDL code which fixed this.

I then went on to re-vector the Atom character I/O to point to the new routines. This worked moderately well for hand-typed communications.

When I cut-and-pasted program sources, characters at the start of lines would often be missed. I suspect this is because the Atom is pretty quick at receiving text into its buffer, but slower when it comes to parsing the buffer after the end-of-line character. This happens with other BASIC interpreters as well.

In practice this is not a big problem right now, because the main need is for loading test programs and not catching the text output.

In future this problem ought to be tackled. The solution may require the PC-side software to wait for the 'ready' prompt after each line to indicated the line has been parsed. I leave this for a later date. In the mean time I set the line delay to be 50 milliseconds, which seems enough time to allow parsing.

Several devices use the data bus, it may be wise to wire them all in at once.