Close
0%
0%

Herring 6502 Computer

Modular 8-bit computer system based on the WDC 65C02 and a mix of modern hardware.

Similar projects worth following
Herring 6502 is a modular computer system I built based on the 65C02 CPU and related parts. Currently, I have boards for CPU, memory (RAM or ROM), serial port, GPIO, clock/decoder, and a bus monitor.

The software is a simple monitor/bootloader program that runs from ROM. It allows code to be loaded over the serial port into RAM and then executed. This removes the need to constantly flash ROM images. I have written cc65 configs and shell scripts to assist with this process.

The primary user interface is the serial port to a host PC.

Goals for this project include a more fully-featured software interface and enough hardware for the system to function as a standalone unit, i.e. keyboard/joysticks, storage, video output.

Component Boards

Backplane

Herring is designed as a passive backplane system. The backplane PCB provides DC input, a 5v regulator, a reset button and the system bus. Everything else is done on the individual boards.

CPU Board

Fits a 6502 CPU. Connects address and data buses as well as most of the CPU control lines directly to the system bus.

This board also provides a system clock in the form of an oscillator and address decoding / glue logic with a ATF16V8B GAL chip. The GAL takes in address and control lines from the CPU and outputs eight "decoder" lines that can be used as chip-select pins for the various peripheral boards.

Memory Board

Each memory board holds two 8KB or 32KB ROM or RAM chips. The size and type of each chip is configurable with onboard jumpers. Each memory chip can have its chip-select pin mapped to directly to A15 or one of the DEC lines to allow for a flexible memory map.

The base system is designed with a single 8KB ROM and 32KB RAM board installed. Technically, multiple memory boards can be installed in parallel to add additional ROM and RAM, but there is currently no memory banking, so one memory board seems sufficient for most applications.

GPIO Board

A 6522 VIA chip is used to provide 16 GPIO lines. These I/O pins are exposed on a 2x10 pin header, allowing jumper wire or ribbon cable connections to peripherals. Herring also makes use of the VIA for its timers.

Serial Board

A 6551 ACIA creates a simple UART for the system. This serial port can run at up to 230400 baud. An onboard 1.8432 MHz or 3.6864 MHz crystal provides the ACIA with a clock for its internal baudrate generation.

Multiple serial boards can also be installed in parallel. I'm currently using one for the console and one for experimentation with other serial peripherals. Each board can be assigned to a unique memory address range using the decoder GAL.

System Bus Pin Description

The system bus has changed slightly as new iterations of Herring have been built, but this is the up-to-date pinout for v1.5.

The system bus consists of a single 40 pin header. The pins are in order as follows:

1. VCC - 5v regulated input

2. GND - ground connection

3-10. Data pin 0 through data pin 7

11-26. Address pin 0 through address pin 15

27. /RES - system reset pin

28. CLK - system clock (oscillator is connected directly to this line)

29. RW - read/write pin on the 6502

30. /IRQ - interrupt request

31-38. /DEC0 - /DEC7, used for peripheral chip-select, driven by the GAL on the CPU board

39. BE - Bus enable pin on the 6502, pull low to allow another bus master (currently this is not a feature I've implemented)

40. GND - ground connection

  • Iterating On the PCB Designs

    Colin Maykish03/15/2022 at 03:04 0 comments

    I've been mostly happy with the hardware design of Herring, but I want to make some minor changes:

    1. The reset button must be pressed after power on for the system to reliably initialize. This is not a great experience. It would be better if the system could reset fully when power is applied.

    2. There are a few small fixes I want to make on the backplane. The first is to remove the regulator and replace it with a direct 5v power connection. USB would be ideal. Even better would be to have an on-board USB-to-serial chip, allowing a single USB connection for serial and communications.

    3. Replace some single-chip boards with combination boards to save backplane slots.

    My secondary goal is to preserve the system header pinout as much as possible to maintain at least some backward compatibility with the existing PCBs.

    Here are the new PCB designs I'm working on. First is the new backplane:

    As mentioned, the biggest difference here is the addition of a 555 power-reset circuit and a MCP2221A USB-to-serial chip. The added USB-B socket can now provide power and serial to the host PC with a single cable. Since the actual UART chip will still be on a daughterboard, I've had to sacrifice two of the decoder pins on the system bus for the TX and RX lines that feed this converter. Finally, there's a DC adapter for regulated 5v input just to leave the option open. The second switch selects between power from USB or the DC input.

    Next up is what I'm calling the core system board. It's a mashup of the old CPU board and the two slot memory boards.

    Not much to say about this one. It's the CPU, two memory ICs with selectable size and write-enable, and the oscillator and GAL. The GAL is responsible for selecting the on-board memory, but it also connects to the decoder lines on the system bus.

    Finally, the new "I/O" board:

    Again, this is just a combination of two VIAs and two ACIAs with an additional GAL. This GPIO lines from both VIAs are connected to the 40-pin ribbon cable header. One of the ACIAs has a breakout header and the other is connected to the system bus directly to feed the USB-to-serial adapter on the backplane. This single board is equivalent to four boards of the previous design.

    I'm still working on some accessory boards to go along with these and the designs need to be double checked, but I'm planning to order the first batch this week.

  • Software Development For the Herring 6502 with cc65

    Colin Maykish02/02/2022 at 20:00 0 comments

    I want to briefly go through the process I've taken to setup a development environment and write software for the Herring computer. Early on in the project I decided I wanted to write most of the software in C. I learned enough 6502 assembly language to get my board working and to aid with debugging, but an assembly deep-dive was not where I wanted to focus my efforts. Obviously assembly code can be much faster than anything written in C, but if I was after speed, I wouldn't be building a 6502 computer in the first place.

    C Compiler

    The cc65 toolset provides some GNU-like applications for compiling software. There's a compiler, an assembler, and a linker. These tools operate roughly like their bigger brothers with some specific options and settings for the 6502. They also provide a subset of the C standard library which is a huge productivity boost.

    I first created a linker config file which is basically a description of the computer's memory map so the linker knows where to put the different pieces of your compiled code. Available here: https://github.com/crmaykish/herring-6502/tree/main/firmware/config (There are actually two linker config files which I'll explain shortly.) After that, it's necessary to create a `crt0.asm` file. This is a small bit of assembly that sets up the stack, initializes memory and then calls `main()`. At that point, C takes over and you're ready to go.

    Writing a Monitor/Bootloader

    Compiling C is a great start toward more efficient software development, but one bottleneck is constantly having to flash and reinstall ROM chips to test changes. I built a monitor application that runs from the ROM. It functions as a system monitor (peek, poke, memdump, etc) as well as a serial bootloader. Using the `load` command, additional programs can be transferred over the serial port and written directly into an unused portion of RAM. When the transfer is complete, the `run` command tells the 6502 to jump to the entry point of this application. This is why there are two linker configs and crt files defined. One is for the monitor (or any application that runs from ROM) and the other is for programs that are meant to be loaded into RAM and executed from there, i.e. everything else.

    In short, the bootloader code rarely changes, but I can constantly load and run new code over the serial port with a few commands.

    A Terrible Transfer Protocol

    A quick word on the serial transfer details: it's trivially simple, but it has been extremely reliable so far. When the `load` command is given, the monitor goes into a listening mode and it stores every byte it receives over the serial port into increasing locations in RAM starting at $1000 (the monitor application is given the first 4K of RAM, see the linker configs for more detail). When the monitor sees three magic bytes ($DE) in a row, it stops the transfer and returns to the prompt. The application is now in RAM and can be executed with the `run` command. When an application in RAM returns from `main()`, it gives control back to the monitor (assuming it exited cleanly). I wrote a tiny Go application to run on the PC which implements this "protocol" and is responsible for transferring the compiled application files (https://github.com/crmaykish/ctt).

    This method of reading every byte directly from the serial port with no handshaking or checksum is a total hack. I had every intention of implementing xmodem or something more robust, but I have not had a good reason to do so. This hack works shockingly well.

    Development Workflow with Make

    To summarize, my development workflow looks something like this:

    1. Flash the monitor to ROM (only necessary if there are changes to the monitor code)

    2. Write C code for another application

    3. Compile this application against the RAM configuration

    4. Use the bootloader to transfer this application into RAM

    5. Run the application from RAM

    6. Jump to step 2

    To make this all a bit cleaner, I wrapped up the compilation steps...

    Read more »

  • Improvements to the CPU and Memory Boards

    Colin Maykish12/15/2021 at 23:40 0 comments

    I just assembled the newest batch of PCBs based on my latest changes to the design. My goal is to condense some of the component boards together to save a bit of room on the backplane, either to allow a smaller backplane or just to leave more room for experiments.

    Three boards were in the most need of an update: the CPU, the memory, and the clock/decoder boards.

    My CPU board previously contained the 65C02 CPU and not much else. I experimented with some different configurations of the PHI2 and PHI2O clock signals, but settled on just using the oscillator clock across the whole system and ignoring the PHI2O output signal from the 65C02 entirely. I think this also in the design recommendations for the latest WDC chips anyway - should have listened.

    Since there was so much room on the CPU board, I moved the GAL and clock oscillator on there as well. The only reason for these being separated originally was to allow an FPGA to do the address decoding and glue logic, but I'm happy with the performance (and price) of the ATF16V8B GAL for this purpose.

    The new memory board is really just a doubled-up version of the existing memory board. It has two slots for DIP-28 RAM or ROM chips with jumpers to configure each one individually. The two chips can be any combination of 8KB or 32KB ROM or RAM and multiple boards can installed simultaneously. The chip enable for each chip is driven by the onboard jumpers and the address decoder lines so memory layout is pretty flexible. For now, though, I will stick with the 8KB ROM and 32KB RAM on one board as this is enough for all the code I've been running. One note: there is no memory banking, so there's still a limit of 64KB total memory (including I/O space). I think I've decided bank switching is out of scope for this project anyway.

    These boards are getting pretty close to what I'd consider the final design for Herring. I have a few more small tweaks to the system bus layout. There is another round of PCBs in the mail already to address these final issues and, more importantly, make them all the same color.

    In the meantime, I'm cleaning up the schematics and documentation with plans to release everything after a final review.

  • Overclocking and Undervolting the 65C02 Family

    Colin Maykish12/09/2021 at 00:15 0 comments

    Herring Backplane 3.3v

    Until recently, I have been maintaining two versions of the Herring system - one with 5v-compatible components and another for 3.3v. The backplane regulates the 12v DC input so it's easy enough to install a 5v regulator in one and a 3.3v with the same pinout in another (I'm using LM1117 and LD33V respectively).

    My reasoning for the distinction was that finding 5v compatible ICs seemed a lot easier since the 6502 was originally a 5v part, but having a native 3.3v system makes interfacing with modern hardware like FPGAs and microcontrollers a lot simpler - no need for level shifters all over the place.

    Some of the modern components in the 6502 family made by WDC support either voltage natively as long as you have the S variant (in theory, the N are 5v only), so I picked up the W65C02S CPU and the W65C22S VIA chips. Parallel SRAM chips also commonly support a wide enough voltage range to work in either case. The main sticking point I had was finding ROM chips that advertised 3.3v support. It turns out my preferred 8KB ROM chips, the Atmel AT28C64B have lower voltage alternatives in the form of the LV and BV varieties (e.g. AT28BV64B). Either one of these will work at 3.3v. The trouble is actually buying them. I couldn't find any DIP packages for sale anywhere. I ended up buying the SO-28 versions on eBay and attaching them to DIP adapter PCBs.

    The other problem is these low voltage versions are significantly slower. The LV version has 250ns access time compared to 150ns for the standard C version. Not a problem at the moment, but it's a potential issue in the future if I really want to push clock speed.

    Low voltage ROM chip with DIP-28 adapter PCB


    Other 5v-only parts include the ATF16V8B GAL that I'm using for address decoding and the 1602 LCD display.

    This brings me to the point of this post: almost all of these "5v" parts work just fine at 3.3v. At least at 4 MHz, the 5v versions of the ACIA, VIA, ROM, and the GAL chips all function perfectly fine at 3.3v. I would imagine the upper limit for clock frequency will be lower when running everything at 3.3v, but I'm not overly concerned with pushing the speed. For what it's worth, I've had the native 3.3v components running at 8 MHz with good stability (some CPUs can do this and others can't, but that's a different post).

    Almost all of these components work well outside of their voltage and frequency ratings. My ACIA chips for example are rated at 1 MHz (CDP65C51E1) and they run great at 8 MHz. I'll continue to experiment and try to determine the bottlenecks where I can and I'm planning on using the 5v system as a baseline if stability problems ever arise. One of my goals for this project is to develop some custom video and control hardware using an FPGA and running a native 3.3v system really makes this a lot nicer.

    The only component that does not support 3.3v at all is the LCD Display. This is not due to the logic levels, but the LEDs that light the characters are just too dim when powered at 3.3v. There are 3.3v versions of the 1602 LCDs, but they're a little harder to find. The LCD board is a low priority anyway. With a functional serial monitor and VGA development coming along, there's not much need for it.

    For reference, here is a list of components I've confirmed working at 3.3v. Some of these advertise support for 3.3v. Others don't. This is more or less a complete list of ICs I've tested in Herring. One note: the GAL doesn't actually work at 8 MHz, so the 8 MHz testing was done with an FPGA as the address decoder and clock generator.

    TypeComponentNative 3.3v
    3.3v @ 2 MHz
    3.3v @ 4 MHz
    3.3v @ 8 MHz
    CPUWDC W65C02C02S8P-10
    yesyesno
    no
    CPUWDC W65C02S6TPG-14
    yesyesyesyes
    CPUCMD G65SC02PI-2
    noyesnono
    ACIAHarris CDP65C51E1yesyesyesyes
    ACIAWDC W65C51N6-TPGnoyesyesno
    VIAWDC W65C22N6-TPG-14
    noyesyesyes
    VIARockwell R65C22P2
    noyesyesno
    GALAtmel ATF16V8Bnoyesyesno
    ROMAtmel AT28C64B
    noyesyesyes
    ROMAtmel AT28BV64B
    yesyesyesyes
    RAMAlliance AS6C62256
    yesyesyesyes

View all 4 project logs

Enjoy this project?

Share

Discussions

Peabody1929 wrote 12/06/2021 at 18:34 point

Great Idea!  It looks like a 6502 version of RC2014.  Do you plan to publish/upload schematics for the backplane, processor, memory, etc?  I would like to build a system.

  Are you sure? yes | no

Colin Maykish wrote 12/06/2021 at 19:15 point

Thanks, it's very much inspired by the RC2014 and other similar projects. The build in the latest photos is what I've been calling v1.4. It has some known bugs in the hardware that I'm in the process of fixing. I'd be happy to share schematics and Gerber files for v1.5 once I've had a chance to validate the new designs. Some of the v1.5 PCBs are being manufactured at the moment, so it shouldn't be too long before I have an update.

  Are you sure? yes | no

Similar Projects

Does this project spark your interest?

Become a member to follow this project and never miss any updates