Close
0%
0%

Weird CPU

A minimal 8 bit TTL CPU using 1970s technology

Similar projects worth following
Weird CPU (WCPU) was the name given to it by a fellow DIY CPU designer.

The WCPU is a fully functional 8 bit CPU.

It is weird because it has only one instruction (Move).

It currently sits on my mantle shelf running a light chaser program.

It was built using 41 track strip-board and standard LS-TTL components from a 1970s LS-TTL databook. To keep with the theme it uses 2x 2114 RAM chips and 2x 74S571 fusible link PROM chips. The PROMs hold the monitor (front-panel) program.

It uses a "front-panel" like the Altair 8800 for input and output (i.e. programming).

So how does a one instruction CPU work? Basically all instructions are found in memory locations. Want to ADD two numbers:
1 Move Memory A (say 0x00) to Register P (0xF8)
2 Move Memory B (say 0x01) to Register Q (0xF9)
3 Move ADD Register (0xF8) to Memory C (Say 0x02)

Registers P (0xF8), Q (0xF9) and ADD (0xF8) are memory locations that access the adder hardware.

AlanX

Weird CPU

It is a big project so I will not try to write it up in one go.

Front Panel Interface

The front panel consists of:

  • A reset switch (left top IO row).
  • An 8 bit Data Input/Output (top row of 8 LEDs and 8 momentary contract switches)
  • An 8 bit Address Input/Output (bottom row of 8 LEDs and 8 momentary contract switches)

The front panel:


Using the Front Panel

  • Obviously the front panel works in binary!
  • The Data IO (i.e. top row of switches and LEDs) will display the contents of the address location from memory (RAM, ROM or hardware).
  • The switches toggle the state of the matching LED. Changing the Data will change the memory location (if it can be changed).
  • When powered up or reset the monitor program will set the Address IO (i.e. bottom row of swtiches and LEDs) to 0x80 (i.e. b10000000), the start of the programmable RAM (of 120 bytes).
  • To execute the program, set the Address IO to 0xFF (i.e. b11111111) and then change any bit of the Data IO to run.


Memory usage:

AddressNameComment
0x00-0x5FMonitor subroutineCalled on reset
0x60-0x71Delay
subroutine
Called with 0xF0 equal to the delay (ms)
and 0xF1 equal to the return address
0x72-0x7FConstantsConstants used by the Monitor and
Delay subroutines
0x80-0xEFProgrammable RAM
0xF0TMP/DELAYSubroutine parameter
Delay subroutine (address 0x60) delay (ms)
User temporary variable (V0)
0xF1RETURNReturn address from subroutine
User temporary variable (V1)
OxF2ADDRUser temporary variable (V2)
0xF3DATAUser temporary variable (V3)
0xF4FETCHUser temporary variable (V4)
0xF5DEPOSITUser temporary variable (V5)
0xF6RPTRUser temporary variable (V6)
0xF7JUMPUser temporary variable (V7)
0xF8-0xFFHardware instructionsSee hardware instructions below


CPU hardware instructions:

AddressWrite ReadComment
0xFF JMPReservedJump unconditional
0xFE JCReservedJump on carry
0xFDJEQReservedJump on P=Q (not implemented)
0xFCJGTReservedJump on P>Q (not implemented)
0xFBRegDRegDData IO
0xFARegARegAAddress IO
0xF9RegQNANDALU: Write P Register / Read "P NAND Q"
0xF8RegPADDALU: Write Q Register / Read "P ADD Q"


Programming Example

A binary counter:

  0X95, 0XF3,  //  P0: 0X80  _1 -> V3
  0X94, 0XF2,  //      0X82  _255 -> V2
  0XF3, 0XF9,  //  L0: 0X84  V3 -> Q
  0XF2, 0XF8,  //      0X86  V2 -> P
  0XF8, 0XFB,  //      0X88  ADD -> D
  0XF8, 0XF2,  //      0X8A  ADD -> V2
  0X94, 0XF0,  //      0X8C  _255 -> DELAY
  0X92, 0XF1,  //      0X8E  L0 -> RETURN
  0X93, 0XFF,  //      0X90  _96 -> JMP
  0X84, 0X60,  //      0X92  Const,   Const
  0XFF, 0X01   //      0X94  Const,   Const
In the above code you will note that the simple assembler (an Excel macro) written for the Weird CPU can handle labels (e.g. "P0:"), constants (e.g. "_1") and has a number of built in aliases (e.g. "P" for Register P etc).

As there is only one instruction "move from fetch address to deposit address", constants (e.i. "Const") need to be stored somewhere. In this case the assembler adds the constants to the end of the program.

Interpreting the code:

CodeLabelComment
P0: 0X80 _1 -> V3P0:Move Constant 1 to Variable 3
0X82 _255 -> V2Move Constant -1 to Variable 2
L0: 0X84 V3 -> QL0:Move Variable 3 to Register Q
0X86 V2 -> PMove Variable 2 to Register P
0X88 ADD -> DMove ADD to Data IO (P ADD Q)
0X8A ADD -> V2Move ADD to Variable 2
0X8C _255 -> DELAYMove Constant 255 to DELAY (V0)
0X8E L0 -> RETURNMove Address L0: to RETURN (V1)
0X90 _96 -> JMPMove 0x60 to JMP (Jump to subroutine)
0X92 Const, ConstConstant L0:, Constant P0:
0X94 Const, ConstConstant -1 or 255, Constant 1


Clock Speed

The clock frequency is 1 MHz (should be good to 24 MHz if the RAM could keep up). This equates to 8 us per instruction.

Designs

The designs have been uploaded in DIYLC format. DIYLC is an excellent free software for manual PCB design and is excellent for strip-board design.

Update

Added the monitor and two demo programs to the file list.

The programs use an Excel macro (Ctrl-M) to assemble the code (in hex).

Regards AlanX

PROM_PROGRAMMER.png

PROM Programmer Driver

Portable Network Graphics (PNG) - 29.27 kB - 07/31/2017 at 13:22

Preview
Download

ino - 12.36 kB - 08/08/2016 at 08:26

Download

1_CPU_IOBoard.png

Print to scale image of the IO Board design

Portable Network Graphics (PNG) - 246.16 kB - 07/31/2016 at 00:33

Preview
Download

2_CPU_Timing&MemoryBoard.png

Print to scale image of the Timing and Memory Board design

Portable Network Graphics (PNG) - 218.87 kB - 07/31/2016 at 00:33

Preview
Download

3_CPU_ProgramCounterBoard.png

Print to scale image of the PC Board design

Portable Network Graphics (PNG) - 216.33 kB - 07/31/2016 at 00:33

Preview
Download

View all 24 files

  • Programming the Weird CPU

    agp.cooper08/04/2016 at 04:11 0 comments

    Programming the Weird CPU

    I have uploaded three xlsm files (they contain a macro (ASM) so you need to enable macros to run them).

    The three files are:

    • Monitor.xlsm
    • Program8BitConter.xlsm
    • ProgramLEDChase.xlsm

    The basic layout is the same:


    Here is where you enter your code:

    Assembler for the front panel panel here:

    C Code for Arduino here:

    CPU reference information (note aliases used by the macro are listed in the Aliases tab/page):

    And finally a reminder how the run the macro:

    When you run the macro it will ask you for the top of RAM which is where the constants are stored. Answer "149" or more for this program. This is the same program described in the "Details Section" of this Project (if you want to know more about it).

    Alan X

  • Using the Arduino to debug WCPU

    agp.cooper08/03/2016 at 05:33 0 comments

    Using the Arduino to test boards

    Because of the complex logic I had to use an Arduino to check these everything.

    Here is Weird CPU mark I, using the Arduino as a PROM and testing the PC board (the stack consist of the IO board, the timing and memory board (only the RAM is installed) and the PC board). The access time of the Arduino PROM was about 1.3 us so I slowed down the CPU clock from 1 MHz to 100 kHz:

    Here is the stack disassembled:

    You may note the repeated use of read and write decoder chips (2) on each board (generally the first two on the left). 41 tracks is not enough to decode all the hardware addresses just once.

    Here are the build notes for one of the boards:

    Without the Arduino I doubt that I could have completed the project.

    AlanX

  • Reading the schematic of Weird CPU

    agp.cooper08/01/2016 at 04:29 0 comments

    Understanding Weird CPU

    Now that I have spent some time reviewing other CPU project (it is good that I am not the only mad person out there!), I do find it hard to follow their concepts.

    So I will try and breakdown my schematic (divide and conquer!).

    Before we begin

    One instruction - Move

    Basically the instruction is:

    Move [PC] -> [PC+1]

    The CPU moves the data at the address pointed to by PC to the address pointed to by PC+1. So its a just a fetch and a deposit.

    Confused?

    Answer the question, how would to move data at one memory location directly to another memory location?


    Instructions are memory locations

    The memory address for the ALU registers P and register Q are 0xF8 and 0xF9, respectively, but:

    • If you read register P (0xF8) you get back "P ADD Q" (not the value you wrote to P).
    • If you read register Q (0xF9) you get back "P NAND Q" (not the value you wrote to Q).

    By the way, other than SHR (which was an omission) this is a complete set of instructions.

    You can software code a P XOR Q in 10 instructions.

    Making a jump

    To make a jump, write the jump address to the Program Counter (PC) at 0xFF.

    The four jump options are:

    1. 0XFF Jump unconditionally
    2. 0XFE Jump if carry set for P ADD Q
    3. 0XFD Jump if P=Q
    4. 0XFC Jump if P>Q

    Accessing the front panel

    • The address of the Address IO (the bottom row on the front panel) is 0xFA.
    • The address of the Data IO (the top row) on the front panel is 0xFA.
    • One trick, the input is inverted (and momentary).


    DONE!

    The Schematic

    The schematic has 28 chips excluding the PROM, RAM,and associated memory address decoder.

    Lets kill off the Data IO and Address IO

    Nothing complicated, just basic input and output (IO) - 24 chips to go:

    Note: The "!" in the WR and RD signals indicate active low.


    Let kill off the ALU NAND sub-system

    Note the ALU sub-systems have common P and Q registers - 21 chips to go:


    Let kill off the ALU ADD sub-system

    Nothing complicated here just two 4 bit adders - 18 chips to go:

    Let kill off the ALU Comparator sub-system

    Now we can see the P and Q registers referenced above - 14 chips to go:

    Lets kill off the Address Decoder for the ALU and IO

    The decoded address space is 0xF8 to 0xFF but not all are used. Two signal come from the Timing sub-System: !RD and !WR - 11 chips to go:

    Lets kill off the Program Counter (PC)

    This one is a little more complicated as it includes decoding and jump logic. There are a number of inputs from the Timing sub-system (i.e. !CLR, PC_CLK and !PC_OUT) - 6 chips to go:


    Lets kill off the Fetch and Deposit registers

    These two registers (Address and Data) hold the fetch and deposit address (in turn) and the data moved between the fetch and deposit addresses. The PC controls the buses 50% of the time and these registers control the buses the remaining 50% of the time.

    The inputs from the Timing System are DATA_CLK, !DATA_OUT, ADDR_CLK and ADDR_OUT - only 4 chips to go:

    Finally lets kill off the Timing sub-system

    What you see here is:

    • A clock using a 2 input NAND gate (74LS132). Note that it has been presented as two 74LS14 schmitt triggers and an OR gate. This was necessary because the simulator model for 74LS132 is not actually a schmitt trigger?!
    • Reset logic using a 74LS14.
    • A two phase clock (74LS93).
    • Some timing signal decoding logic.

    Here is the timing signals from the timing sub-system, it might make more sense now:

    Well, you may not get it all the first time but everything is there for you to understand the Weird CPU.

    For my actual build, I did not include the comparator sub-section as Jump On Carry is sufficient for a minimal system.

    Weird CPU II has some improvements: 16 bit rather than 8 bit, rearranged instruction addresses and the inclusion of the missing SHR instruction. I have also inverted the jump flags (i.e. Jump on not carry, Jump on P!=Q and Jump on P<=Q).

    Your challenge, if you accept it, is to design and build your own minimal CPU with:

    1. a lower chip count, and
    2. more instructions.

    Best of luck, AlanX

  • Print to Scale Board Designs

    agp.cooper07/31/2016 at 00:46 0 comments

    Print to Scale Board Designs


    Added the print to scale (top view) board designs to the file list.

    Reverse these (in mspaint) for the reverse side view.

    These are the images I used to construct the WCPU.

    I kept them up to date as I found errors.

    The only board not used in the CPU was the Comparator Board.

    While it would be useful it is not necessary.

    Jump on Carry is all you really need.

    Print to scale is important for reducing errors when cutting tracks and soldering components.

    If you do decide to build WCPU then double check everything before cutting a track and work from one side of the board to the other.

    A ruler to check cut positions is useful.

    AlanX

  • On DIY

    agp.cooper07/30/2016 at 03:32 0 comments

    On DIY

    Having successfully designed and built a reasonable complex project (a TTL computer) I would like to make some suggestions to those who are considering doing the same.

    If your a genius then you make your own rules and don't need to consider my learnings.

    The key message is that you need structure. It is great fun firing up the soldering iron and doing something but the novelty wears off pretty quickly and the project is soon abandoned. You need a plan before you begin.

    So what is structure or a plan?

    My structure is based on divide and conquer. Break the project down to smaller sub-projects. How small? That depends on you ability to complete the sub-project.

    An example: A discrete transistor CPU

    1. Design your project (CPU) using standard MSI logic gates (don't worry too much about memory as it is not part of the CPU).
    2. Redesign the CPU with SSI logic gates.
    3. Replace the SSI logic gates with discrete transistor equivalents.

    Notes:

    • MSI = Medium Scale Integration (for example an 8 bit latch or an ALU)
    • SSI = Small Scale Integration (for example a quad NAND gate or a Dual D-Flipflop)
    • Each stage is complete after you have built and debugged it!
    • There are plenty of MSI standard logic gate CPU designs on this forum to get you started.
    • Pick one and make it your own (Szoftveres' TTL CPU is worth a look).
    • You can easy get someone to review your schematics.

    Now even these steps are too big for most people but you get the idea.

    Is there a doable path to follow?

    You don't need to full populate the plan providing you are confident it is doable when you get there. For example, how to program the ROM can wait.

    Testing and debugging

    • Me: "Well I have designed and built my CPU but it does not work!"
    • My dog: "No surprise, it is to be expected!"
    • Me: "?"
    • My dog: "Why did you assemble the CPU without testing each component/board first?"
    • Me: "!"

    A big hint - It takes longer to test and debug a CPU project than to design and built it!

    So two things to note:

    1. Time spent making sure the design is correct is time saved.
    2. The sooner you test and debug your work the better.


    Arduino to the rescue

    How did I test and debug my CPU?

    I emulated the CPU and CPU components with an Arduino.

    Okay, which board would you build first? Did you say the IO Board?

    Why, because it is pretty easy to write code for the Arduino to:

    • test the IO Board (early visual success)
    • emulate the CPU (to test boards and software)
    • test the monitor program (with the actual IO Board).

    Did I tell you that the monitor program when uploaded to the CPU PROM worked first time! But it did take two attempts to get the Arduino code for the PROM programmer to work (but I had made provision for this).

    I wrote quite a few Arduino programs to help me debug my boards.


    If you cannot program an Arduino the perhaps you should not be reading this post!

    Regards AlanX

  • Added the PROM Programmer the the file list

    agp.cooper07/29/2016 at 13:48 0 comments

    PROM Programmer

    One of the sub-projects was to program the PROMs with the Monitor Code. Now I know some guys use a few switches, a power supply and a couple of fly wires! Well some of the schematics were not that much better. But today we have the Arduino so really it is pretty easy. A switchable power supply and some code.

    Here is my PROM Programmer:

    The only hard bit is making sure you wire it up correctly. Note the wire colours, same a the resistor codes, so wire 1 is brow, wire 2 is red etc.

    Here is the board design:

    You will see two 7805 voltage regulators. One is just a 5v supply and the other switches between 5v and 12.5v (the voltage pulse generator).

    Here is the schematic for the voltage pulse generator (note the load resistors are the PROM loads for the simulation):

    The PROM specifications are quite onerous with regard to voltage slew rate and load impedance thus the fairly complicated circuit.

    I also note from the board design that I added data read circuity (the 1n4148 diode and 4k7 resistor).

    I have also added the Arduino code for writing the high and low nimbles for the PROM Programmer to my file download list.

    AlanX

View all 6 project logs

Enjoy this project?

Share

Discussions

agp.cooper wrote 08/09/2016 at 13:11 point

Thanks KnivD, I am currently working on a 4 Bit version and that is tough to get anything usable (very limited address space).
Forced me to look at OpCodes and variable machine cycles lengths.
I have something that is close (38 TTL chips total) but this time I will go PCB (a few days away).

Regards AlanX 

  Are you sure? yes | no

Kn/vD wrote 08/08/2016 at 19:00 point

I love its minimalism. Great work!

  Are you sure? yes | no

Yann Guidon / YGDES wrote 08/08/2016 at 18:49 point

Excellent ! Fabulous work !

That's the kind of thing I would like to develop too :-)

  Are you sure? yes | no

agp.cooper wrote 07/29/2016 at 02:18 point

Okay, my error. The 2112s (which would have used if I could find some) and the 2114s where around in the late 1970s.

  Are you sure? yes | no

jaromir.sukuba wrote 07/28/2016 at 14:18 point

Lovely project, I like it. By the way 2114 was made by NMOS process, not bipolar.

  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