Happy New Year to everyone reading this much belated status update! I apologize for the radio silence, but I took a break from this project over the summer. I came back to it en force in late November, taking advantage of my holiday time off to really sink my teeth into it again. Quite a few things changed, so let’s dive right into it.
My first goal when coming back to the project was to get the new build booting to a serial console. To make this easier I threw together a bus analyzer using a Raspberry Pi and some MCP23017 I2C I/O expanders that I had in my parts bin. With two of them, plus some Python code, I was able to have the RPi monitor the CPU buses while pulsing the system clock. This severely cut down the time it took for me to find the various wiring mistakes, and it was useful enough that I hope to someday create a more permanent version of it for future builds.
At this point I had a booting system, but it was not very stable. I partly solved this by switching (no pun intended) to a better bench power supply. The big change, though, was getting rid of all of the discrete logic, which brings us to…
The COLE System Controller
The CSC is the core of the system and is responsible for managing the system buses. It’s implemented on a Xilinx XC9572XL CPLD, and it’s responsible for:
- Bank address latching
- High address line generation (A16-A18)
- Chip selection for RAM, ROM, and I/O
- IRQ aggregation
In the previous build, the bank address was latched by a 74ACT73, which remained open (transparent) during Φ2 low, but closed and latched the bank address on the Φ2 rising edge. This is the design recommended by WDC in their application notes for the 65816.
When I first implemented this design in the CSC it made the system even more unstable. However, by switching my design to latch the bank address on the Φ2 rising edge the system suddenly became rock solid I don’t know the reason for this, but since it works I am going to leave it as-is. The only real downside to this design is that my address decoding is not as fast as it could be, and thus I would need faster RAM and ROM for any given clock speed.
With the system booting reliably I next turned my attention to getting video into a working state again. The new video controller is called the TIVI, or (TI)ny (V)ideo (I)nterface, and is implemented on a TinyFPGA.
The TinyFPGA is a wonderful and inexpensive piece of hardware, but it does suffer from one major problem: a lack of user-accessible I/O pins. There are far too few pins available to connect it to any sort of external RAM. Fortunately, the TinyFPGA has 16 KB of on-chip dual-port block RAM. which is just enough for text and basic graphics.
Since the video RAM is on-chip the TIVI chip operates like many old-school CRTC chips, and provides registers for reading and writing video RAM. This isn’t as bad as it sounds; through the use of an auto-incrementing address register the CPU can read/write contiguous chunks of video RAM at full speed.
The output from the TIVI is an analog VGA signal with a resolution of 640×400 pixels, at a refresh rate of 85 Hz. I chose this mode because it uses a 31.5 MHz pixel clock, which the TinyFPGA’s PLL can synthesize exactly. Standard 640×480, by contrast, uses a 25.175 MHz clock, but the closest value the PLL can generate is 25 MHz. While it’s close, and it sort of works with my LCD monitor, it is technically out of spec.
Due to the small amount of available VRAM the TIVI can’t output an actual 640×400 image. The current design implements two video modes:
- 80×25 text, with 8 background and 16 foreground colors, hardware blink, a programmable hardware cursor, and a programmable font.
- 160×100 graphics in 6-bit color.
The text mode uses an 8×16 font stored in the high 4K of VRAM. The BIOS loads the font from ROM at startup, and when switching from graphics mode back to text mode.
Down the road I would like to try adding hardware scrolling, at least for text mode. I may also add a higher res mode such as 320×200, but this is not a priority for me.
The Speed Force
In this new build the TIVI generates the system clock by dividing its 63 MHz master clock by a programmable divisor. The default value is 24, which produces a system clock of 63/((24+1)*2) = 63/50 = 1.26 MHz. I chose this value because breadboard builds aren’t the best for grounding and noise, and 1.26 MHz is an easily attainable target in these conditions.
With the TIVI chip now accessible by the CPU I was able to twiddle the divisor after boot and see how fast I could push the system. So far I have had good success running with a divisor as low as 4, which equates to a system clock of 6.3 MHz! This exceeds my original design goal by a whopping 20%. It may be able to run a bit faster, but the next lower divisor produces 7.87 MHz, which instantly freezes the system.
The COLE Input Controller
The CIC is an ATmega 328p that handles all user input, including the keyboard, the mouse, and both game pads. It connects to the rest of the system via SPI. It’s similar to the 8042 keyboard controller in IBM PCs; it handles the low-level communications with devices, freeing the CPU for other tasks. It also manages the system’s RESET and NMI signals. This includes the initial power-on reset function previously handled by a dedicated IC.
Unlike my previous build the CIC does not do PS/2 scan code conversions, nor does it manage the LEDs automatically. Instead, raw PS/2 scan codes are fed to the CPU, which is now responsible for key mapping and LED management. It does, however, watch for some special key sequence and act upon them. Pressing Ctrl-Alt-Delete will reset the system, and Ctrl-Alt-Break will toggle the NMI line. Since the CIC handles these directly they are guaranteed to work even when the rest of the system is non-responsive.
My original build used two 6522 VIAs. One was dedicated to receiving data from the CIC, plus a bit-banged SPI implementation. The second VIA was reserved solely to the user port. There were a couple of problems with this design, however.
First, there was no way to send data to the CIC. This meant the BIOS couldn’t change key repeat rates, mouse resolution, or the keyboard LED states.
Second, the bit-banged SPI was really slow, and very CPU intensive.
Fortunately for me I stumbled upon André Fachat’s SPI/65B project, a VHDL rewrite of Daryl Rictor’s 65SPI hardware SPI controller. Daryl’s original design is wonderful, but it is written in ABEL, which is no longer supported by the Xilinx tools. André rewrote Daryl’s implementation in VHDL, with a few bug fixes and enhancements.
I was able to upload André’s design to an extra CPLD, and after a few minor tweaks I finally had working hardware SPI. This has now replaced one of the VIAs in my build, leaving just the user port VIA.
For maximum compatibility the SPI interface is running at 5V via a small level shifter. The CPLD itself is 5V tolerant, so the level shifting is only necessary on the output signals.
With the final hardware design finally coming together, it’s almost time to start work on a PC board design. I would like get the first (and hopefully only) PCB design done and built by this spring.
There’s a lot of hard work ahead, but I’m looking forward to it!