Quote:
1) Have an option for arbitrary clock division. This takes 2 or 3 regs for the divisor. Many small systems do not have clocks available. There may be only a 2 MHz master clock for the system, and the baud rate needs to be set against that.
2) Reserve a couple of registers for Tx, Rx fifo control.
3) Make the stop bits independent of the number of data bits. 1/1.5/2
4) It might be nice to have more byte sizes available, eg 4 to 12.
5) 6551 register compatibility would allow existing software to be ported more easily
I did consider including the ability to set an arbitrary divisor, rather than selecting from a table. However, this actually makes it more difficult to select
standard baud rates which users are more likely to find useful, particularly if they're interfacing to a PC which will be operating with one of the standard UART crystals. Providing a separate oscillator for the UART is a matter of an inexpensive, DIP-8 sized can, or for a slightly more compact solution a discrete crystal and three surface-mount passives. If a separate oscillator isn't feasible, then you could use the UART oscillator as the master clock for the system, rather than the other way around.
By way of example, the nearest divisor from 2MHz for 9600 baud is 16x13. This yields an error of 0.16%, which is acceptable. But 13 is a prime, so none of the higher standard speeds could be divided from a 2MHz source, unless the internal sampling clock was changed from 16x (which is used, for example, to eliminate false start bits and accurately align samples to the middle of bit periods).
One goal here was to use the same number of address slots as the 6551, so that a pin-compatible carrier board with essentially full functionality could be constructed. This would yield a drop-in replacement (in hardware terms) for which modifying the driver software is straightforward. Adding three of the features you mention would make it virtually impossible to achieve that goal - and the final feature effectively makes that goal mandatory. Design is a tradeoff, and I'm not here to build a Rolls-Royce. If you want one of those in UART form, use a 28L92.
I'll say more about stop bits, though. It's important to realise that on the wire, a stop bit uses the same level as line idle - so the receiver doesn't care whether it's intended as a stop bit or is a meaningless gap between characters. Stop bits are therefore mostly about meeting exotic timing constraints, usually in the receiver. These constraints almost always relate to electromechanical equipment, eg. 5-bit Baudot TTYs and 6-bit Selectrics. The Selectric is an instructive special case, as the serial interface to turn a Selectric into a printing terminal was very much an ex-post-facto modification, and the word format and baud rate were carefully tuned to avoid burning out a mechanical clutch which would start and stop the mechanism.
So for transmit, my design allows for 1.5 stop bits (permanently) for 5 and 6 bit words, and the more usual 1 stop bit for 7 and 8 bit words. These can be extended by one full bit in the transmitter by configuring "fixed parity" with the "mark" polarity (setting the "9th bit" to 1), so 2.5 bits can be selected for the smaller words, and 2 bits can be selected for the larger words. For the receiver, the extra half or full stop bit is accepted but not checked for; if "fixed parity" is selected, the first stop bit will be recorded in the "9th bit" flag, and the second one will be treated as the "real" stop bit.