YATAC78 - The WWW TTL Computer

Retro computer made from 1978-era TTL logic chips. Internet capable with built in web browser and server

Public Chat
Similar projects worth following
The YATAC is designed using the Modified Harvard Architecture typically employed in digital signal processors (DSP). This highly streamlined architecture is used to support fast serial communication and graphics. An RS232 interface and SLIP client provides many connectivity options from dial-up modem to Ethernet. The YATAC supports a basic web server and text-based web browser. These can be used for downloading new programs to saving new programs "to the cloud".

YATAC78 - Yet Another TTL Archaic Computer (1978 or 78k available RAM)

  • Dual Processor CPU/GPU modified Harvard Architecture
  • 13.5MHz machine clock, 6.75MHz per processor (up to 10 CPU MIPS)
  • 256k ROM (128k for operating system), 128K RAM (78k for user programs)
  • 75 ALU functions, including: BCD support, multiply/divide, square root, trigonometry
  • 8-bit PCM Audio  with 4 voices, 20-10 kHz bandwidth
  • PS2 Keyboard interface built in
  • RS232 Serial Port USB data transfer and internet connectivity (up to 38400 baud)
  • Parallel Port for expansion (4 bits in, 8 bits out, 2 register strobes)
  • Bitmapped Graphics 2 resolutions at 60Hz: 15 color hi-res mode at 320x256 or 256 color low-res mode at 160x128 (double buffered)
  • Text Mode 640x400 native resolution at 75Hz. 4 fonts at 80x25 using 8x16 characters or 80x50 using 8x8 characters. 256 line buffer for smooth scrolling.
  • Chip Count 44 TTL plus a single ROM, RAM, PAL, RS232 driver, analog switch, and op-amp.
  • Target PCB size 2 stacked 18cm x 12cm 4-layer boards (25 chips per board)

The following gives a detailed overview of the system architecture and how the fast scheduling works. The system uses a 12.5 MHz clock and a typical instruction spans 4 clock cycles as follows:

  1. Load Instruction from ROM.
  2. Read data from source register or RAM.
  3. Perform an ALU function using the ROM as lookup table.
  4. Write data to register, accumulator, and optionally to RAM.

The alternating use of both ROM and RAM allows a second processor to be added to the system. Both processors use dedicated pipelines to cache data between the alternate program and data address spaces. One processor handles communication and general computational tasks (CPU) while the other is dedicated to the display and audio (GPU).

The following sequence of diagrams demonstrates the multiplexing of the CPU (shown in blue) and GPU (shown in red). In this example the GPU is operating in text mode and the CPU is executing the sequence described in the numbered list above.

In the first cycle the GPU reads the ASCII code point of a character from the RAM and stores the result in the GPU Cache (gc). The CPU addresses the ROM using the Program Counter (PC) and Page Register (Pg) to load the Instruction Register (I).

In the next cycle the context switches over and the CPU X and Y registers are used to address the RAM and load the CPU Cache (cc). Meanwhile the gc, along with the Scan Counter (SC), is used to address the ROM and load a character bitmap line in to the Character Register (C)

The GPU returns to the RAM where the H counter was moved to the next byte and loads the gc with text color values. The ROM is now configured as an ALU with a function specified in the instruction. The cc is combined with one half of the HL register and the result is stored in the Accumulator (A).

In the final cycle the value in A is written to the RAM. The font colors stored in gc are moved to the RAMDAC (P) and the bitmap loaded in to a shift register to start the next character render cycle.

Note: 8-bit ALU functions repeat the last two cycles to combine both halves of the HL register.

pld - 2.49 kB - 04/18/2019 at 04:49



Hand-drawn schematic of complete prototype design

Adobe Portable Document Format - 4.67 MB - 04/17/2019 at 16:07



Memory map showing both RAM and ROM address layout

Portable Network Graphics (PNG) - 107.14 kB - 04/17/2019 at 14:34


  • 13 × 74F574 Octal D-type Flip-flop with Tri-state Outputs
  • 7 × 74F163 Synchronous 4-Bit Binary Counter
  • 2 × 74F08 Quad 2-Input AND Gates
  • 3 × 74F00 Quad 2-Input NAND Gates
  • 2 × 74ALS139 Dual 2-line to 4-line Decoders

View all 20 components

  • Internet

    Alastair Hewitt13 hours ago 0 comments

    This was always a stretch goal, but it looks very doable now the design is complete... and it wouldn't be the first TTL Computer on the Internet.

    What is the scope of Internet-enabled?

    Connectivity is via the RS232 port. This provides an ancient but still supported interface standard. There are plenty of inexpensive options to adapt to more modern serial standards. These include USB with an FTDI cable and Ethernet with a WizNet protocol adapter. Of course, dial-up would be the most authentic method using a standalone modem.

    The TCP/IP stack is a project in its own right. The current plan is to port something like uIP to the YATAC. There are other lightweight options out there, but just to be safe an 8k section of RAM has been reserved for the stack.

    The simplest server/client model would be TFTP. I plan to do better than this though and go straight to HTTP with a browser and web server. However, this would be the Tim Berners-Lee 1989 version of the Web: Text only browser and basic GET/POST (no MIME) for server. This still provides an easy way to upload and download programs via a web interface.

    The hardware text mode was specifically designed to render basic web pages. The 4 fonts are used with HTML as follows:

    • Standard font used to render text body.
    • Bold font used for <b> tags.
    • Italic font used for <i> tags.
    • Underline font used for <u> and <a> tags.

    There are 8 colors available, so links would be highlighted along with using the underline font. Headers would also be highlighted in a different color using the bold font.

    Pages can be up to 256 lines long and are rendered directly to the screen memory. Scrolling is achieved by updating one register on every screen refresh. Almost no additional CPU resources are required to display a page once loaded.

  • Redesign

    Alastair Hewitt4 days ago 4 comments

    So there's the easy problem (designing a computer out of TTL) and then there's the hard problem (make it work at 12.5 MHz).

    I was close, but not quite there. The RAMDAC was hitting the wall with a dot clock above 21 MHz. I have to simplify the logic that switched between the 16 and 8 colors in text mode. I have to take the ZX Spectrum approach and drop to 15 colors with a subtractive intensity rather than additive.

    The instruction decode looked good on paper but I forgot about the 10 ns propagation from the clock to output of the instruction register. I was able to find a solution but the entire decode path barely fits in the 80 ns machine cycle. Too much parasitic capacitance in a PCB layout and things will get glitchy once the chips reach a toasty 70 C.

    So I've been shuffling things around and doing some consolidation. I'm back to a solid design, but I will need to redraw the schematic. I'm not spending another weekend doing that by hand, so the next schematic will be a proper CAD drawing. But saying that, it's time to start building and verifying this thing will work at these speeds. Only then is it worth documenting the verified design.

    Not surprisingly the first thing to test is the clock and bus control state machine. After that the instruction decode and CPU state machine. I'll then be able to run a simple jump/loop program. It won't be Turing Complete, but if that program runs reliably at 12.5 MHz then everything else will work. I can then start on the fun stuff like adding RAM and the video output. Then the really hard problem (software).

  • Clocks, Scans, and Refresh Rates

    Alastair Hewitt04/10/2019 at 22:22 0 comments

    The previous log discussed the display columns. This one will cover the rows, but first the clocks:

    • Dot Clock (dclk) - 25.175 MHz
    • Machine Clock (mclk) - 12.588 MHz (1/2 dclk)
    • Processor Clocks (pclk/qclk) - 6.294 MHz (1/2 mclk, qclk is pclk inverted)
    • Extended Clocks (rclk/sclk) - 6.294 MHz (pclk/qclk shifted 90-degrees)
    • Text Clock (tclk) - 3.147 MHz (1/2 pclk)

    The dclk is the standard VGA dot clock and is used to latch the output of the first video DAC (VDAC1) and to shift the bits of the character buffer in text mode. This renders the text at the full 640 horizontal graphics resolution of VGA by displaying 80 columns of text using 8-bit wide characters (not the 9-bits of the 720 horizontal resolution VGA-400 text mode).

    The mclk is the native speed at which the hardware is clocked at. This is divided down again to generate the pclk at which each processor operates. Therefore each processor cycle includes two machine cycles. One machine cycle is used to access the ROM and the other to access the RAM. The GPU and CPU operate on opposite clocks to access both memories concurrently.

    The rclk is a delayed version of the pclk used by the CPU state machine. This provides a 40ns delay in which to perform the instruction decode and maintain the state across the edge of the 80ns machine cycle.

    The final clock is the tclk and is used by the GPU in text mode. Each column of text uses two bytes, so the GPU divides down the pclk to alternated between reading the ASCII code point and font/color bytes on each processor cycle.

    Each line of the display requires 200 process cycles as discussed in the previous log. This results in a horizontal scan frequency of 31.47 kHz. This is fixed in hardware and is the same for every video mode. At the end of each line the Scan Counter (SC) is incremented. This is a 4-bit counter that can count up to 16 lines. This serves two purposes:

    1. Index the character bitmap row to be rendered in text mode
    2. divide down the line count

    The lo-res text mode uses 16 lines for each character, so the whole of the scan counter is required for this. The hi-res text only needs 8 lines, so just the first 3 bits are used. The bits are also combined to create an ent signal for the vertical counter depending on the video mode as follows:

    • divide by 2 - hi-res graphics mode (repeat lines twice)
    • divide by 4 - lo-res graphics mode (repeat lines 4-times)
    • divide by 8 - hi-res text mode (8-bit character)
    • divide by 16 - lo-res text mode (16-bit character)

    This is what drives the vertical scan count, but the software must blank the display at the bottom of the screen, generate the V-Sync pulse, and then reload the V register to reset the counter to the top of the screen. The value loaded in to the V register can be moved up and down to perform a smooth scroll of a larger text area within the video RAM.

    Since the vertical sync timing is software defined it is possible to supported different screen sizes. The YATAC defines 4 screen heights and when combined with the 4 other video modes provide a total of 16 configurations for the display. Both the standard VGA-400 and VGA-480 modes are supported, allowing full compatibility with even the most ancient PS/2 CRT monitors. The other two modes are YATAC-specific custom defined: The YATAC-9x4 is a 419 line mode at 75 Hz and will map directly to HD/UHD 9:4 ratio displays (but at a much lower resolution). The YATAC-MAX is a 561 line mode at 56 Hz and renders the maximum number of lines in RAM (256) when using the hi-res graphics mode.

    The mode name, total lines and how they are made up are defined as follows:

    Mode NameTotal LinesFront PorchV-Sync Back PorchRefresh Rate
    YATAC-9x44191724075.10 Hz
    VGA-4004491223570.09 Hz
    VGA-4805251023359.94 Hz
    YATAC-MAX5611223556.09 Hz

    The screen refresh rate drops as the lines increase since the horizontal frequency is fixed. However,...

    Read more »

  • Counting to 200

    Alastair Hewitt04/10/2019 at 18:16 0 comments

    The GPU does the same thing over and over again: Count to 200. It does this regardless of the graphics mode. Each horizontal scan will read 200 bytes of the RAM at the processor clock rate of 6.25 MHz. What does change is what each byte represents.

    Even though the horizontal scan is 200 bytes long, it must also contain the border, overscan area, and sync timing. This extra stuff takes up 20% of the scan line, so only 160 bytes are typically displayed per line.

    The 160 bytes is mapped to columns as follows:

    ModeBits per ColumnColumns
    Hi-Res Graphics4320
    Lo-Res Graphics8160

    Each column in the graphics mode is directly mapped to a DAC. The hi-res 4-bit encoding is RGBI and the lo-res 8-bit encoding is RGB 3:3:2 (3-bits red and green, 2-bits blue). The text column contains two colors (foreground and background) and both use a 3-bit encoding of just RGB.

    The 16 bits of a text column span 3 bytes and consists of the font, code point of the character, and two colors. The following table shows how these are mapped given a column index of C:

    Font2 bits
    Code Point (ASCII)8 bits
    Foreground Color3 bits
    Background Color3 bits

    In addition to the 160 bytes per line for the conventional display area, an additional 4 bytes are added to the start and end of each line. These bytes would normally be set to a solid border color and are rendered along with the normal 160 bytes. These can be used to display content in the border, but this would only be visible on a CRT and wrap around the edge of the glass.

    The display RAM provides up to 256 rows for the display. The total RAM required is 42k bytes with the 168 bytes reserved for each line for the display. The way this is mapped may seem a bit odd until you see the reasoning behind it.

    The first column of the display (including the border) has an index of 56 (0x38 in hex). Remember we need to count to 200. A naive approach would be to start at 0 and count to 199 before returning to zero on the next clock pulse. If we start at 56 then the last index before reseting would be 255. The synchronous counter chips provide a signal (rco) that is generated on 255 and this can be used to reload the counter to 56. Therefore we count to 200, but without needing any additional logic gates (actually, one inverter)

    So why place the border where it is? And why is it the size it is? The (VESA) VGA spec does specify a border, but this would only be 2 bytes (8 VGA pixels). The extra 2 bytes is added so the screen border ends at 224 (0xE0). This is when the H-Sync pulse begins. A single 3-input AND gate can be used to define the start of this pulse. This is the H-Blank signal and defines when the horizontal output should be turned off. The H-sync pulse lasts for 24 bytes, so a pair of 2-input NAND gates can fully define this when combined with the H-Blank signal.

    Here's the detailed memory map of a line of video RAM:

    0011 10000x3856video RAM start
    0011 10010x3957back porch end
    0011 10100x3A58left border start
    0011 10110x3B59left border end
    0011 11000x3C60display start
    1101 10110xDB219display end
    1101 11000xDC220right border start
    1101 11010xDD221right border end
    1101 11100xDE222front porch start
    1101 11110xDF223front porch & video RAM end
    1110 00000xE0224H-Blank & H-Sync start
    1111 01110xF7247H-Sync end
    1111 10000xF8248back porch start
    1111 11110xFF255H rco, H-Blank end

  • Control Signals

    Alastair Hewitt04/10/2019 at 02:17 0 comments

    The following gives an overview of the control signals shown in the schematic. There are a lot of them! The table below details the 20 registers/buffers/counters used in the YATAC. Each requires one or both of an output enable (~OE) and latch enable (~LE). Listed are the names, machine context, data source (SRC), destination (DST), and the control signals used by each register.

    Register NameContextSRCDST~OE~LE
    Scan Counter
    GPU CachegcGPURAM
    X Index
    X Index
    Y Index
    Ei CPUserial
    CPU Cachecc CPURAM
    ALU FunctionfnCPUI0-2, I6
    AccumulatorA CPUROM
    HL RegisterHLCPU
    X Register
    Y Register

  • Brief Instruction Set Overview

    Alastair Hewitt04/08/2019 at 14:22 2 comments

    6 weeks in and the initial hand-drawn schematic is posted and the parts have been ordered. There have been requests for more information. I'll be filling in details as I move forward, but thought I would post a brief overview of the instruction set. The encoding of the instruction set has been shown in the project's background image since week 2, but hopefully this will help explain!

    There are two fundamental operations:

    • Load an operand - 2 bytes (instruction + operand), 1-2 cycle execution
    • Perform ALU function - 1 byte (instruction), 2-3 cycle execution

    The operand can be loaded to one of 8 registers:

    • A - accumulator
    • HL - 2-nibble accumulator
    • X - low address index
    • Y - high address index
    • V - vertical line counter (used by GPU)
    • E - expansion register (serial, system state)
    • PC - program counter (low program address)
    • Pg - page register (high program address)

    The last two registers (PC, Pg) can be loaded conditionally, based on the sign of the accumulator. The page register also has an option to toggle between one of two banks of 64k providing a 17-bit address range. There is also a zero-page option to leave the X index register in tri-state after loading to enable quick access to a zero page (0x1YYFF).

    The load operand typically takes 2 cycles to complete. The conditional load will complete in 1 cycle if the condition is not met (it does not need to load the operand). There is also a condition that always skips: NOP, so this can be defined with just one instruction byte (1 byte, 1 cycle).

    The YATAC uses the ROM as the ALU to perform binary operations between the 8-bit accumulator A and one of the 4-bit halves of HL. There are three sets of ALU functions:

    • FN8 - full 8-bit ALU functions: A = Fn(A, HL)
    • FN4 - 4-bit ALU functions: A = Fn(A, L)
    • FNH - unary ALU function: R = Fn(A)

    The FN8 set includes 8 functions like ADD, SUB, AND, OR, and requires 3 cycles (load instruction, first nibble, second nibble). The FN4 set includes the same 8 functions as FN8, but only performs the lower half of the nibble to complete in only 2-cycles. FN4 also includes 4 additional functions like MUL, DIV, and 4 sets of unary functions like INC, DEC, SQRT. The specific unary function within the set is defined by the 4-bit L register, specifying a total of 64 functions. The FNH is a special case targeting the last set of 16 unary functions specified by the H register.

    Both the FN8 and FN4 functions leave the result in A. FNH can specify one of 8 possible registers: the first 6 listed above, or one of 2 expansion registers (EX, EY) available via the parallel port. The ALU instructions also specify the source of the data to use and whether to write the result to the RAM. The default is A, but both X, E, or the upper RAM1, or lower RAM0 can be sourced.

    The very last unary function is a NOP, which passes the input to the output unchanged. This provides the ability to move data from A, X, E, RAM to one of the 8 possible registers. There is no specific MOV operation beyond this.

  • Design Complete

    Alastair Hewitt04/02/2019 at 18:18 5 comments

    However... complete doesn't mean finished. There will be continued iteration and refinement and then unknown problems to resolve during the prototype phase. After 37 days I have arrived at a design that should work and meet the current specification.

    So the final numbers are in with a total of 54 chips. These break down as follows:

    • 49 TTL
    • 2 Memory (ROM, RAM)
    • 1 RS232 line driver
    • 1 Analog Switch
    • 1 Op-amp

    The gates still need to be shuffled around a bit and I may be able to consolidate with one less TTL chip. It's just as possible that this process could push the count up by one, so the TTL chip count is plus/minus one at this point.

    [ UPDATE: The count was pushed up by one]

    I've also been working on some PCB layout ideas. I like the one-board approach of the Gigatron and it should be possible to cram the YATAC on to a board of similar size. I want to use a COTS enclosure though and this could become quite large and costly with a single PCB.

    What became more apparent with a completed design is the natural demarcation between the GPU and CPU. The GPU requires a similar number of chips to the CPU and it seems a logical way to split the design to layout two PCBs.

    The current plan is to place all the GPU logic, RAM, analog circuitry, clock generator, and connectors on one PCB. The CPU logic and ROM would be on a second PCB that mounts on top of the GPU using two headers. Each board would hold 27 chips in a target area of 18x12 cm. The entire assembly would then fit in a Polycase ZN-40.

    Next up is a BOM and then placing an order for the prototype.

  • Upgrades

    Alastair Hewitt03/25/2019 at 17:56 0 comments

    I’m now 4 weeks in to the project and still don’t have a finished design. I’m getting close though and have finalized the design for the GPU. I’ve added the chips to the components list to give an idea of the size and complexity of this section. The components list will be expanded in the future, so for now it just details the 20 chips used exclusively by the GPU (not shown are the RAM and ROM chips since these are equally shared by the CPU).

    The CPU design is tracking towards 25-30 TTL chips. I’m hoping to have this part of the design finished within the next two weeks. This means the final design will have somewhere between 45-50 TTL chips. Along with these are the RAM, ROM, RS232 line driver, analog switch (already listed and used to switch between video DACs), and an op-amp for a proper Sallen-Key filter used by the audio DAC. Including these brings the YATAC in line with a typical IBM PC video card of the early 80’s with over 50 chips.

    One of the biggest challenges with the design is the speed at which things need to operate. The last stage of the GPU uses the VGA dot clock of 25.175 MHz. This doesn’t pose too many issues since the control logic is fairly simple in this area. This clock is divided down to 12.5875 MHz and is used to switch the context of the address busses between the GPU to CPU. Each cycle lasts a little over 79 nS and only provides 12 nS each side of the 55 nS memory access to tri-state each address bus, set up a data latch, clock, then hold the data. This can be done, but requires a fully synchronous design and the fastest TTL chips available.

    Needless to say, I’ve made some upgrades to my test equipment before I attempt the prototype!

View all 8 project logs

Enjoy this project?



Marcel van Kervinck wrote 04/05/2019 at 16:23 point

When I was contemplating the ALU and other random control logic for what later became known as the Gigatron, for quite a while I considered abusing the 74x48 7-segment decoder to build an instruction set around. But it's a slow chip, and also I couldn't get the instruction set quite right. After that phase I realised I really needed a ROM, but ROMs are very slow and it wouldn't fit in the critical path of a 6-8 MHz design. So that's where the diode-ROM came in, because that's fast. Interestingly, that was today exactly 2 years ago . I'm interested in what ROM speed are you planning to use?

  Are you sure? yes | no

Alastair Hewitt wrote 04/05/2019 at 18:58 point

Hi Marcel, thanks for your interest. The Gigatron is the main inspiration for this project, especially your work on generating VGA with TTL chips.

I read your article on using the diodes a few weeks ago. I was a bit worried discrete diodes wouldn’t switch fast enough, but it looks like this will work. I’m doing most of my instruction decode using discrete logic: This includes 8 chips of gates, 3 decoder chips, and 2 flip flop chips for state machines. There is one area where I decode 8 possible states and I plan to use a "diode ROM" for this.

Both the ROM and RAM are accessed at half the VGA dot clock (12.5875 MHz). I need to switch between three different contexts for the ROM address bus: program, ALU, and font bitmap. I have to determine what state I want next and then latch this so everything changes on a single clock edge. I don’t have time to determine the state after the clock edge because it takes up to 12ns to change the bus tri-state. This leaves me with just 65ns to access the ROM then latch the result before the next context switch.

To deal with this timing issue I have to use memory with 55ns or better access speed. The only ROM with this speed is one-time programable. I’ll use this when I have code worthy of "shipping", but for now I’ll be doing development using NOR flash. The fastest DIP version is 70ns (e.g. GLS27SF020) so I’ll need to drop my clock speed a little. Worse case is a screen refresh at 50 Hz instead 60 Hz during development.

  Are you sure? yes | no

Marcel van Kervinck wrote 04/05/2019 at 20:57 point

Ah great. How about the references to an 128K ROM for ALU functions? I also saw a memory map of that, or is that "out" already? Anyway, take your time to reflect and document, if for no other reason than for yourself. I found those "boring documentation cleanup tasks" after a design frenzy helped to improve the end result. [BTW. This is probably a 3-level deep post without Reply button. Threading works best by going back 2 steps and reply from there....]

  Are you sure? yes | no

Alastair Hewitt wrote 04/06/2019 at 01:39 point

(jumping back 2 steps) The same ROM is used for the both the program and ALU. The CPU instructions take more than one cycle. For example: the first cycle reads the instruction from the ROM, the next cycle reads from the RAM, then the ROM is used as an ALU to perform a function, and finally the RAM can be written to. The ALU only handles one nibble at a time, so the last two cycles would be repeated to do a full 8-bit operation.

  Are you sure? yes | no

Marcel van Kervinck wrote 04/06/2019 at 09:47 point

Got it! Good luck with the build! One or two PCB, both have their tradeoff. The Gigatron is very sparsely populated with wide spacing. You might fit your design in a similar size, and the PCB costs aren't really that steep.

  Are you sure? yes | no

Geri wrote 03/08/2019 at 16:20 point

Hi, i following your projects and i am impressed with your works, especially the SUBLEQ implementation. I suggest you to try creating an FPGA based implementation to run my operating system: 

Running this operating system will put you in the next league as this is a multitasking-multiwindowing, smp capable operating system, and creating a hardware thats capable to run something like that gives the followers magnitude bigger impression. The example emulators are attached in the zip file to guide you in the process. Feel free to contact me in e-mail for information if you dont understand something. 



  Are you sure? yes | no

agp.cooper wrote 03/07/2019 at 01:11 point

Great computer specification! Perhaps your are aiming a little too high for ~30 TTL chips?


Have a look at some of the other TTL designs on Hackaday to get an idea of specifications and chip count. You may be disappointed what others have achieved.

Have a look at the Apollo181 ( which has a 65 chip count and uses the 74181 ALU (yuck!) for an example of what can be done in 4 bit.

Its pretty impressive for 65 chips!


If you want something simpler (to get started) have a look at the TD4:

1) Breadboard version:

2) ATMega 328p "ROM" version:

3) And a schematic:

I have built the TD4 and have PCB designs on EasyEDA (, you can get them made and posted to you.

Regards AlanX

  Are you sure? yes | no

roelh wrote 03/06/2019 at 08:18 point

Hi Alastair !  I'm looking forward to your schematics and instruction set....  I have similar plans...

  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