Breadboard color computer from TTL

"Just because"

Similar projects worth following
Can fewer than 40 old-skool simple TTL chips on a breadboard implement a 8-bits, multi-MHz 64-color computer? This is what we have now:

* 8-bits computer built out of 1970s TTL chips (74LS series)
* 34 chips are used for the CPU
* Only simple SSI and MSI chips, such as AND/OR, 4-bit adders, multiplexers and registers. Typically no more than 10-20 gates per IC.
* So no microcontroller and no relatively complex ALU chips are used (such as the 74181)
* 32 kB SRAM (70ns)
* Harvard architecture with program and data stored in EEPROM
* Runs at 6.3 MHz. It can probably be pushed to 8 MHz.
* RISC-like instruction set with pipelining: 1 instruction per clock cycle
* Instruction decoding partly done with diodes
* Comfortable instruction set: add, sub, and, or, xor, conditional jumps, several useful addressing modes, etc.
* Capable of generating VGA signals from software. Typically 160x120 pixels with 64 colors
* Designed and built on a solderless breadboard in roughly 6 weeks

This will be [Edit: is] a general purpose breadboard computer made out of TTL-grade logic chips and no CPU or microcontroller. It will have video out, at least 160x120 pixels in 16 colors [Edit: 6-bit / 64 colors in the current protoboard]. It should be capable of displaying arbitrary full-screen images and running games like Pac Man and Space Invaders. Ideally the project should stay under 30 chips, but definitely no more than 40. Can it be done?The project is not built yet. I will describe it as I make progress in the upcoming weeks. I don't work on it all the time and updates will be irregular. I have done some concept tests with video before, see my other projects on this site for that. Now is time for the big leap.

[Edit: see the video for the resulting capabilities ]

[ Note: I don't maintain this "Project Details" section very often. See the blog for the real updates. ]

    Some concepts to ponder about before starting

    1. How many bits? 4, 8, 16, 32, ...
    2. Software-generated video or hardwired?
    3. Harvard or Von Neumann architecture?
    4. Single cycle or multi cycle? Pipelining?
    5. ALU chips or not?
    6. Sliced ALU or full width?

    A rule of thumb is that a minimalistic four bit system can be done in 10 chips, an eight bitter needs no more than 20 chips and going to 16 bits roughly doubles that again. Not all units double in chip count, but by extending the buses you will also have need for more addressing modes for it all to make sense. For example, a four bitter might work fine with a 256 word memory and absolute addressing, but with larger memories you'll need ways to construct addresses dynamically. Also, add more chips if extra functionality is required, such as high speed, a stack pointer, interrupts, a custom ALU or video.

    Simplest possible concept

    One concept, probably the simplest, is to replace the TrinketPro from the earlier breadboard VGA from TTL and SRAM with a minimalistic 4-bit TTL CPU. We will then get a working system with around 25 chips, or about 30 if we make a custom ALU. It will indeed be good enough for Pac Man and Space Invaders, but that will then also be the limit: no chance at all to have any fast scrolling, fast color changes, smooth moving objects, large objects, etcetera. Upgrading the CPU part to 8-bits won't bring much, because there will still be a communication bottleneck between the two parts. For any more exciting video we will need more complexity in the video part. If we do both, we certainly end up with more than 40 chips. It is absolutely interesting to try out this 25 chip concept (I would do it with a 74'181 ALU chip), because Space Invaders from such a small system can be very appealing. But first I want to explore another path.

    A more daring approach

    Lets look at it from another angle. If we look at the current video generation circuit it already contains many elements for a CPU: there are counters, ROM, RAM and buses. So the idea I'm going to pursue first is to extend the video part to gain full CPU capability: we will combine video with the CPU logic. The software will bit bang the sync and pixel signals at the right time. The dead time can be used for application code.

    I don't know how this choice is going to turn out, it might make the application software timing really complicated, but it has the potential to make more interesting video possible because all flexibility is now in software. It also requires the CPU part to be very fast.


    The ALU is the Arithmetic and Logic unit, or the inner calculator in a processor. For the ALU there is the option to use a 74'181 or to roll your own. I have several '181s lying around, so that is not the issue. But they have become hard to obtain, so duplicating this project becomes a bit more difficult if it requires them. Therefore I will do a custom ALU. We could still cut functionality, for example only do ADD and NAND. But I really don't like compromising the software in such extreme ways.

    Data paths and control signals

    Instruction table

    Notable prior art and thanks

    Lets not pretend...

    Read more »

    • ... and a blinking LED

      Marcel van Kervinck06/13/2017 at 22:44 2 comments

      Today I realised that no homebrew CPU project can claim completeness without a blinking light. Lacking free output pins (all 8 are used for video), I hooked up an LED to the unused address pin 15, and use that as alternative.

      I'm getting into some serious problems with breadboard fatigue in the EEPROM area. One of the ROM's just keeps popping out. The next phase is therefore to document the circuit in KiCad and convert it into a PCB.

      [ Spoiler: the display is an older selfie, as witnessed by the incomplete wiring and background. The on-screen LED is just a 3x2 pixel area turning red at the same time as the breadboard LED. The scrolling is smooth in real life, but due to mismatch with my phone, it may appear jumpy. ]

    • Self-awareness

      Marcel van Kervinck06/07/2017 at 07:38 0 comments

    • Undefined opcodes

      Marcel van Kervinck05/29/2017 at 04:54 0 comments

      From the assembler/disassembler it is easy to generate a complete instruction table. Most opcodes result in a valid instruction. Only memory writes while RAM is on the bus result in an undefined value ($??) being stored.

      I found out I had some undefined instructions that are actually very useful. They store a value in memory as well as in X or Y. Their existence is entirely accidental: Unlike AC and OUT, the X and Y registers are not "muted" while writing to memory. The purpose of muting is solely to provide all addressing modes to store instructions without destroying the contents of AC or OUT. As X and Y don't have addressing modes that AC and OUT already have as well, I didn't bother to give them an OR-gate that suppresses the enable signal to them ("you don't need these modes"). This omission turns out to be quite useful! Because X and Y are essentially "write-only" registers, each time you use them and you're not sure of their value you have to reload them. Now you can first do a computation, in AC, and then move the result both to X/Y and also back to memory. Both moves in the same clock cycle. With that, you can keep track of what is in X/Y, for example in the zero page. I suppose this will be used a lot. I already use it in the video loop.

      Now they are no longer undefined. They are part of the family.

    • On the move

      Marcel van Kervinck05/28/2017 at 14:06 0 comments

      First moving video output from my breadboard TTL color computer. Again, the test image is just initialised SRAM garbage with some lines drawn over it. Line 60 to 90 are scrolling 1 pixel per frame.

      The scrolling looks a bit jumpy in the recording, but that is just the mismatch between the camera and monitor frequencies. In real life it is stable and smooth.

    • Stable video with help of a canary

      Marcel van Kervinck05/27/2017 at 12:33 0 comments

      The control unit (CU) uses decoder IC's and diodes for decoding the operation and addressing modes. I'm toying with plain 1N4148 (silicon), 1N60 and BAT85 (both Schottky) diodes. Surprisingly, all seem to work pretty well. Here they are all mixed more or less randomly on the breadboard.

      The diodes between INS (74LS155) and INV (74LS240) form the operation decoding ROM matrix. The diodes connected to MODE (75LS138) pull the control lines for register loads and RAM address generation. The diode mess looks fragile, but in reality it all stays in place rather well.

      When combining diodes with TTL, there is only 400mV voltage drop to play with before entering undefined territory. Some of the diode logic outputs travel all the way across the circuit, which means that supply voltage and ground differences must be controlled over that distance. Also, 74LS requires 4.75V as absolute minimum, or no more than 5% drop.

      When I installed the supervisory MCP100 some weeks ago, I already noticed that I had to connect the 5V supply on the same segment in order to boot. If I connected it further away, it simply wouldn't release the reset. This means there is too much resistance between the segments, more than the equivalent of 250mV. A couple of extra bridges solves that. But to troubleshoot this, I found a useful second use for the MCP:

      First recall that the MCP keeps the reset line low for as long as the supply voltage is not stable above 4.75V. (Well, the MCP100-475DI/TO does that. In ordering these, every letter means something important). In my circuit it sits next to the reset button, as you can see here:

      You can spot the reset switch with its 10kΩ pull-up resistor. It controls pin 1, or /CLR, of the PC counter IC's (all four of them). The red LED is just lurking on the reset line as an indicator. The MCP is the three-legged black component that looks like a transistor. It has one leg on the reset line. The other two legs are on Vcc and GND. It is a clever and useful little device. Now it turns out you can make a super easy voltage tester from an MCP, an LED and a current limiting diode (330Ω), as follows:

      The "reset" leg is now connected to the LED and not to the circuit. If the LED is on, the voltage difference on the supply rails is stable above 4.75V. With this device it is easy to test the voltages everywhere, much easier than with a multimeter or scope. I call this the "canary" because of the yellow light, and because when the light goes out, it signals that that part of the circuit is in danger.

      With all voltages controlled, the video image is now stable. I'm still emitting uninitialised SRAM data, but to verify that I'm streaming from the right addresses, I let the CPU draw some lines across the screen, vertically and diagonally. All addressing modes and registers are now exercised, so this is a pretty good system test.

    • First pixels

      Marcel van Kervinck05/25/2017 at 16:25 0 comments

      160x120 in 64 colors, simply displaying uninitialised SRAM. A bit unstable, but a nice little step. All wiring is now connected. The next steps are to get stable signals, tidy up the wiring and make more interesting software.

    • Two birds with one stone

      Marcel van Kervinck05/21/2017 at 16:01 2 comments

      An Atari joystick will do as input device for the games I have in mind. But the breadboard computer has the potential to run a BASIC. For that, keyboard input would be great. USB is out of the question, and even PS/2 looks a bit involved. A simple matrix keyboard would be a better starting point.

      Also, at some point I'll need an enclosure to keep dust out and to be able to bring it to places.

      Today, I might have stumbled upon the solution for both problems.

      [ Edit: to the millions of voices that suddenly cried out in terror: it had a broken PLA chip ]

    • Homebrew CPU webring

      Marcel van Kervinck05/21/2017 at 08:40 0 comments

      My breadboard TTL color computer is now included in David R. Brooks' Homebrew CPU webring. How cool is that!

      In the meantime I have figured out how to mix video with application code. Next week we'll have a 5-day holiday, and if there are some rainy days in there I expect to get some animated output from this thing by then.

    • First video out

      Marcel van Kervinck05/13/2017 at 18:23 0 comments

      It seems I have reached the base camp. The el-cheapo 7-inch LCD monitor on the right is connected to the output port of my breadboard TTL computer. The computer is now running at 6.3MHz and runs a software loop that generates a VGA test signal. The colors look a bit off, and still not all wiring is done and tidied up, but the mountain top is definitely in sight.

      As far as I can check with the oscilloscope, the signals are behaving nicely according to the VGA industry standard 640x480 at 60Hz. Yellow is the vertical sync and light blue is the horizontal sync.

      The disassembly of the code:

      0000 0009  ld   $09 ; setup for 10 lines vertical front porch
      0001 a001  suba $01 ; next line in vertical blank
      0002 c200  st   [$00]
      0003 0200  nop
      0004 0008  ld   $08 ; entry point for starting a new frame, inside the first hsync
      0005 ec05  bne  $05
      0006 a001  suba $01
      0007 0200  nop
      0008 18c0  ld   $c0,out ; end of first hsync in frame
      0009 0055  ld   $55
      000a ec0a  bne  $0a
      000b a001  suba $01
      000c 0100  ld   [$00]
      000d ec01  bne  $01
      000e 1880  ld   $80,out ; new hsync start
      000f 000a  ld   $0a
      0010 ec10  bne  $10
      0011 a001  suba $01
      0012 18c0  ld   $c0,out ; hsync end
      0013 0054  ld   $54
      0014 ec14  bne  $14
      0015 a001  suba $01
      0016 1840  ld   $40,out ; vsync start
      0017 0200  nop
      0018 0200  nop
      0019 0200  nop
      001a 1800  ld   $00,out ; hsync during vsync
      001b 000a  ld   $0a
      001c ec1c  bne  $1c
      001d a001  suba $01
      001e 1840  ld   $40,out ; hsync end
      001f 0056  ld   $56
      0020 ec20  bne  $20
      0021 a001  suba $01
      0022 1800  ld   $00,out ; hsync during vsync
      0023 000a  ld   $0a
      0024 ec24  bne  $24
      0025 a001  suba $01
      0026 1840  ld   $40,out ; back porch
      0027 0054  ld   $54
      0028 ec28  bne  $28
      0029 a001  suba $01
      002a 18c0  ld   $c0,out ; 33 lines black
      002b 0200  nop
      002c 0200  nop
      002d 0020  ld   $20
      002e 1880  ld   $80,out
      002f a001  suba $01
      0030 c200  st   [$00]
      0031 0009  ld   $09
      0032 ec32  bne  $32
      0033 a001  suba $01
      0034 18c0  ld   $c0,out
      0035 0055  ld   $55
      0036 ec36  bne  $36
      0037 a001  suba $01
      0038 0100  ld   [$00]
      0039 ec2f  bne  $2f
      003a 1880  ld   $80,out
      003b 000a  ld   $0a
      003c ec3c  bne  $3c
      003d a001  suba $01
      003e 18c0  ld   $c0,out
      003f 0055  ld   $55
      0040 ec40  bne  $40
      0041 a001  suba $01
      0042 0200  nop
      0043 00e0  ld   $e0
      0044 1880  ld   $80,out
      0045 a001  suba $01
      0046 c200  st   [$00]
      0047 0009  ld   $09
      0048 ec48  bne  $48
      0049 a001  suba $01
      004a 18c0  ld   $c0,out
      004b 0004  ld   $04
      004c ec4c  bne  $4c
      004d a001  suba $01
      004e 18d5  ld   $d5,out ; first colors
      004f 0003  ld   $03     ; 9 clock delay
      0050 ec50  bne  $50
      0051 a001  suba $01
      0052 18d7  ld   $d7,out ; second color bar
      0053 0003  ld   $03
      0054 ec54  bne  $54
      0055 a001  suba $01
      0056 18dd  ld   $dd,out ; third color bar
      008a 18ea  ld   $ea,out ; last color bar
      008b 0003  ld   $03
      008c ec8c  bne  $8c
      008d a001  suba $01
      008e 18c0  ld   $c0,out ; back to black (front porch)
      008f 0200  nop
      0090 0100  ld   [$00]
      0091 ec45  bne  $45     ; repeat for 480-256 = 224 lines
      0092 1880  ld   $80,out ; hsync start
      0093 a001  suba $01
      0094 c200  st   [$00]
      0095 0009  ld   $09
      0096 ec96  bne  $96
      0097 a001  suba $01
      0098 18c0  ld   $c0,out ; hsync end
      0099 0004  ld   $04
      009a ec9a  bne  $9a
      009b a001  suba $01
      009c 18ea  ld   $ea,out ; second half of screen (256 lines)
      009d 0003  ld   $03
      009e ec9e  bne  $9e
      009f a001  suba $01
      00e1 0008  ld   $08
      00e2 fc04  bra  $04 ; to new frame
      00e3 c200  st   [$00]

    • Fibonacci

      Marcel van Kervinck05/11/2017 at 00:33 2 comments

      With the ALU verified and the RAM connected, today the breadboard determined that the first 8-bit Fibonacci number is 144.

      0000 0000  ld   $00    ; outer loop
      0001 c200  st   [$00]  ; a=0
      0002 0001  ld   $01    ; b=1
      0003 fc0a  bra  $0a
      0004 0200  nop         ; (pipelining)
      0005 0100  ld   [$00]  ; inner loop
      0006 c202  st   [$02]  ; tmp=a
      0007 0101  ld   [$01]
      0008 c200  st   [$00]  ; a=b
      0009 8102  adda [$02]
      000a c201  st   [$01]  ; b+=tmp
      000b 1a00  ld   ac,out ; emit next Fibonacci number
      000c f405  bge  $05    ; repeat if bit7 is still 0
      000d 0200  nop         ; (pipelining)
      000e fc00  bra  $00    ; start over again
      000f 0200  nop         ; (pipelining)

      The inner loop runs 12 times (1, 1, 2, 3, 5, .... 89, 144). The entire thing takes 110 ticks. Both are exactly as expected. It can be done faster but I didn't optimise the assembly to maintain my sanity.

      I also hooked up a cute little MCP100-475 to the program counter reset line. This gives a controlled reset during power up. The circuit is now 90% wired. Only the high memory address control and some diodes are missing for full functionality.

    View all 22 project logs

    Enjoy this project?



    f4hdk wrote 05/26/2017 at 11:34 point

    I like it! 

    Every homebrew computer should have video output, even made with TTL!

    Have you seen my project? It is quite similar (custom CPU architecture, video output) even if I used an FPGA  instead of TTL components.

    It's fully documented and open source. 

    And welcome on the "homebrew CPU Webring" !

      Are you sure? yes | no

    Marcel van Kervinck wrote 05/26/2017 at 13:52 point

    Nice! FPGA's are a step up for me. Clearly the TTL and the RAM size are limiting my video resolution, but it is also cute in its own way.

      Are you sure? yes | no

    Peabody1929 wrote 04/01/2017 at 18:46 point

    Consider one or two AMD2901 or a single CY7C115/116/117 -> More computer, fewer chips.

      Are you sure? yes | no

    Marcel van Kervinck wrote 04/02/2017 at 20:09 point

    Thanks. I can find the first. I do have ALU chips available, I just don't feel like using them in this build. Do you have data sheets for the second series? I have trouble finding out what it is. Some memory? I plan on using 62256 for RAM and 2x AT28C256 for ROM, with a possibility to extend the memory using the AT27C1024.

      Are you sure? yes | no

    Big Boy Pete wrote 03/31/2017 at 18:19 point

    Good luck Marcel.

      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