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


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

  • Bit Banging SPI and Reading SD Cards

    Colin Maykish08/20/2022 at 21:33 0 comments

    In my continuing effort to avoid completing features, I've added another distraction: SD card storage. My real plan is to have SPI available for all kinds of peripherals (displays and network adapters come to mind), but I already had an SD breakout board and it seemed like the logical place to start.

    Adafruit SD breakout connected to 6502 through 6522 GPIO pins

    I did try to get SD cards working some time ago using the 6522 to bit bang the SPI protocol, but I was not successful. It's possible the hardware I was using at the time was faulty. I have two SD breakout boards, one from Adafruit, and a generic version from eBay. I was not able to get the clone working passed a certain point. Seems like it's worth paying a few bucks for the Adafruit version.

    One important note: a pullup resistor on the MISO line is apparently very important, even with the breakout boards. The card will fail to initialize without it.


    This time I ignored all concerns for speed and efficient code and wrote the SPI and SD libraries in C. It's still bit-banging SPI through the 6522. I'm able to initialize the card and read arbitrary sectors of data. There's currently no filesystem support other than some simple parsing of the FAT metadata in the first sector. I'll need to decide how much deeper into the FAT implementation I want to go. It would be nice to have file I/O, but worst case I can treat the SD card like a big serial EEPROM and read in raw data.

    ><(((°> run
    Setting up the SD card...
    Sending SD init command...
    SD card ready!
    Reading block: 0
    Block read complete: 0
    Disk Info:
    OEM: MSDOS5.0
    Bytes per sector: 512
    Sectors per cluster: 16
    Reserved sectors: 2304
    Sectors per FAT: 0
    Number of sectors: 30840
    Filesystem type: 
    Reading block: 0

    As always, the code is available on Github:

    Look for the spi.h and sd.h files.

  • VGA Graphics On The 6502 With An FPGA

    Colin Maykish08/18/2022 at 21:13 0 comments

    As much fun as it is to talk to an old CPU over a serial port, it's hard to beat graphics on a screen. I've had this VGA board built up for a while, but after getting it to the proof-of-concept stage, I got distracted and didn't do much else with it.

    Since getting the v2 PCBs, I've dusted it off and made some updates to get it running again. It's just an Upduino 3.0 FPGA connected straight to the system bus.

    Prototype "video card" for Herring

    Currently, I am maintaining two different Verilog modules: one for a double-buffered framebuffer mode where the CPU can write directly into video RAM and send a command to swap the buffers when it's ready and another that's text mode only. The text mode version has a built-in font in a character ROM and it behaves somewhat like a serial terminal. The CPU sends one character at a time over the data bus to a single memory-mapped address. The FPGA adds the character to its screen buffer and moves the cursor appropriately.

    Both versions run at 640x480@60Hz, but the actual size of the framebuffer is only 64x48 with 8 colors. This could be improved, but there are tradeoffs. The Upduino does not have a huge amount of block RAM and even if it did, it would be hard to map all of it into the CPU address space. It's also fairly short on pins. I'm already maxed out with just the address and data buses plus the control signals and the VGA outputs. Using more video RAM would require a different interface, command based and not straight memory mapping. This is something I'll explore further.

    Text mode displays a grid of 80x48 characters. Each character is 8x8 pixels. In comparison to framebuffer mode, text mode uses only two memory-mapped registers: one for data, and one for commands (e.g. clear screen). There is also no double buffering in this mode and it is currently limited to two colors (green and not green). It's also missing a few font characters, but the basics are there!

    Herring v2 using text mode graphics

    I was able to get printf() outputting directly to the text mode card so as soon as I build some kind of input device, Herring can be a run as a standalone system without being tethered to a PC by the serial port.

    One thing you may have noticed is the "3.3v only" sticker on the card. Herring runs at 5v and the Upduino (like most FPGAs) runs at 3.3v, but all of the components on Herring seem to run well enough at 3.3v if you keep the clock speeds down. For now, this is easier than adding buffers or level-shifters to all the FPGA lines. When I get this video card more polished, I'll add those buffers into the design and bump back up to 5v.

    My (questionable) Verilog code for both modes is in the Github repo: If you have suggestions, I'm all ears.

    Finally, here's a demo video of Herring running Conway's Game of Life in framebuffer mode. This is C code running on the 6502 and using the framebuffer as its output. No other processing is being done on the FPGA.

  • Herring v2!

    Colin Maykish08/11/2022 at 01:50 0 comments

    I finally got around to ordering the next iteration of PCBs. There are enough changes here that a new major version number was justified. As discussed in the log, the main focus was on consolidation and usability improvements.

    The backplane now has a 555 timer for a power-on reset circuit and a MCP2221A USB-to-serial chip on board. This is the change I'm most excited about. There is now a single USB connection on the backplane for power and serial. The Tx and Rx lines are routed on the bus so one of the ACIAs on the new I/O board can supply the console over the USB-serial adapter. Using USB with nothing but through-hole components is pretty cool. I've left a DC connector on there just in case. One of the switches selects which power source to use, USB or DC.

    The existing components boards have not changed significantly in function, but I have condensed the CPU, ROM, RAM and a decoder GAL onto one board and two of both the ACIA and VIA chips onto another. Tons of I/O packed into just two boards. This frees up the backplane slots for other experiments.

    As always with a redesign, I have bugs:

    Without thinking, I connected the reset line of the MCP2221A chip to the same reset connection that the CPU uses. Unfortunately, resetting the USB-serial chip seems to force it to enumerate on the host PC which kills the serial connection. This is annoying as every time the CPU reset button is pressed the serial console dies. The solution is simple: just disconnect that reset line from the CPU reset. It has an internal pullup and seems unnecessary for normal function. For now, I just removed the reset pin from the IC socket so that it doesn't make contact. The reset button now works as expected, keeping the console alive while the CPU resets.

    The other issue is more of a mechanical problem. The first socket on the backplane is too close to the other components and the capacitor is a bit too big so the component boards won't fit. Oh well, at least I combined the other boards, so I've got plenty of open sockets left to use.

    I'll fix both of these problems in the next version of the PCB, but I'll do some more testing to make sure there are no other changes.

  • 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: (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 (

    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
    CPUWDC W65C02S6TPG-14
    CPUCMD G65SC02PI-2
    ACIAHarris CDP65C51E1yesyesyesyes
    ACIAWDC W65C51N6-TPGnoyesyesno
    VIAWDC W65C22N6-TPG-14
    VIARockwell R65C22P2
    GALAtmel ATF16V8Bnoyesyesno
    ROMAtmel AT28C64B
    ROMAtmel AT28BV64B
    RAMAlliance AS6C62256

View all 7 project logs

Enjoy this project?



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

John Smith wrote 03/15/2023 at 18:15 point

Hi. Have you had a chance to complete the project and publish PCB gerbers?

  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