Close
0%
0%

8 Bit Breadboard CPU

A home-brew 8 bit Microprocessor built on a breadboard
64K Address Space, IRQ, and DMA
16 Bit Stack Pointer, 4 8 bit Registers or 2 16 bit

Public Chat
Similar projects worth following
This will be an 8 bit CPU built to interface with a RAM, ROM, and I/O. It will be built out of standard TTL logic on solderless breadboards.

CPU Includes (current design):
- 64K address space (16 address lines).
-Two 16 bit Registers that can be used as 4 8 bit registers.
- 16 bit program counter.
- 16 bit stack pointer.
- 8 bit status register, high nibble used as instruction step counter (carry, zero and negative)
- 8 bit Instruction register (256 possible opcodes)
- IRQ input
- DMA input
- Reset input
- Tri-state address and data line buffers
- AB, XY, PC, SP, and instruction step counter built out of up/down counters for quick incr / decr.

I was doing research for a new hobby project.  I wanted to build a 68000 system on a bread board with I/O and possible video.  As I dug deeper I started shifting towards maybe starting with an 8 bit CPU (6809) and then do the 68000 after.  I'm pretty rusty at hardware, haven't done anything serious since the early 90's.  

While doing this research I discovered a brilliant You-tuber named Ben Eater https://www.youtube.com/channel/UCS0N5baNlQWJCUrhCEo8WlA . He is an excellent presenter and educator.  I watched his series on building an 8 bit bread board computer.  He goes through step by step building a functioning 8 bit computer out of TTL logic.  I'm sure many of you might be familiar with his work.

I've never really had a good understanding of the internals of a CPU.  I knew that it involved state machines and registers but didn't really grasp how it functioned.  In his series he broke down the computer into easy to understand blocks.  After watching his series I was inspired to try and build something of my own.

Instead of building s simple computer, I want to build a self contained CPU that could be connected to a complete system (RAM, ROM, and I/O).  I will use RAM and some I/O to build it but  design it so it can be separated. I want to have some more advanced features on my CPU while trying to avoid feature creep.  I do want to actually finish.

I've ordered a bunch of Breadboards TTL chips, resistors, LED's, DIP Switches, EEPROM's, RAM chips, hookup wire (8 colours), capacitors, 555 timers, toggle switches, and some other bits.   I found a good deal on the long (63 row) breadboards on amazon.  3 boards for $12CDN with free shipping.  I just received 9 of them today and they are superb quality.

I can't wait to get the rest of the supplies so I can start tinkering.

I've drawn up a block diagram for the basic design. 

https://docs.google.com/drawings/d/1BW84zwO5effvYcdKjxzyki9cuvuHsM98z6nAamw4iTM/edit?usp=sharing

I've also started an instruction list which also has a page that lists the full names for all the control lines shown in the block diagram.  Like I said I'm pretty rusty and not up to speed on normal naming conventions.

https://docs.google.com/spreadsheets/d/1kbxYGDeIOszgvjPYRdes-bELOBlojT_tjxe_RD9MVUQ/edit?usp=sharing

I've started an upverter project where I will be posting all the schematics.

Idea's and advice are most welcome.

  • Instructions ....

    2-Zons2 days ago 1 comment

    OK,  More massaging of the instruction set.  I removed the inverse jumps (JNC, JNZ, JNM).  You get the not jump condition in the next memory location after the jump.  The only reason to have them IMHO is to make the code easier to read.  I need the opcodes for more desirable instructions.

    I re-added immediate indirect addressing for the MOV instruction so memory locations can work as pointers. 

    I found a bunch more instructions that were 16 bit and marked them.

    I added a 16 bit memory to memory MOV.  Need to think of a good way to indicate it for the assembler as both the 8 and 16 bit versions are using an address.  Maybe MVL for move long, which could be used for all 16 bit moves.

    After all these changes I have a few unused codes, which is a good place to be in.

    I am realizing that this instruction set is going to be very iterative.  I am sure I will be doing more and more tweaking as I get on with the design.  As I am implementing the microcode in EEPROM's changes will be easy.  I don't plan on working on an assembler until I have a very stable design.  I do plan on using EEPROM's for regular programming as well, but I can program without an assembler.  

     https://docs.google.com/spreadsheets/d/1kbxYGDeIOszgvjPYRdes-bELOBlojT_tjxe_RD9MVUQ/edit?usp=sharing

  • I thought I was done with instructions for now

    2-Zons3 days ago 3 comments

    Going over them one final time with advice from @roelh.  I've updated them to show which are 16 bit and which are 8 bit.  I've removed the XNR instruction, although I thought it was a good way to set a byte to FF, like the status register.  Used the free'd up codes to add the opposite jump's JNC, JNZ, JNM, and some XY stack addressing to the ADD and SUB commands.

    https://docs.google.com/spreadsheets/d/1kbxYGDeIOszgvjPYRdes-bELOBlojT_tjxe_RD9MVUQ/edit?usp=sharing

    Going through this I'm questioning how I have the XY stack instructions currently.  If it is being used as a stack that grows down in memory (starting at a high address and growing toward 0000h) then any time it is the destination it should be pre decremented.  This way it will move to it's new address then store, then it will hold the address of the last byte it stored.  When reading from the stack, or popping, it should post increment, so that it moves to the location where the next byte will be stored, and it will always be pointing to valid data (unless you hit bottom of the stack).

    Is there something wrong with my thinking?  If not then I have the increment and decrements of my XY stack instructions wrong.

    Since I have a dedicated stack pointer (SP), should the XY stack grow towards FFFFh ?  This way both stacks can share the same memory space.  If so, using the above logic, store instructions to the XY stack should be pre incremented, and reads or pops from the stack should be post decremented.  If so then my instructions are still wrong.

    Is there anything I am missing?

  • Finished Instruction Set (For Now)

    2-Zons4 days ago 2 comments

    Whew, I am now at a point where I think I can move ahead.  I have worked out a set of instructions (not set in stone) that I think will work.  It's definitely not orthogonal.  Without complicating the design by adding the ability to have 2 instruction registers or greatly simplifying the instruction set, I can't see a way of doing it.

    The instruction syntax I am suing is "INStruction Source,Dest"  e.g. MOV A,$D020

    I think it has some very useful instructions.  XY Can be used as another stack pointer.  I didn't have to room to allow AB to be used as a pointer directly, so only XY can be used for register indirect instructions.   One instruction it does not have is clear, so no direct way to clear the status register.  You can XOR A with itself (should be 3 cycles) then MOV A,SR (2 cycles). Or if you can't use A, you can XOR a byte in RAM with itself or use a known zero location.

    I have yet to receive enough parts to actually start building anything.  I've ordered parts from several different vendors trying to get the best prices.   With all the shipping charges though I'm not sure If I actually saved anything. 

    I have in instruction matrix on the google docs spreadsheet

    https://docs.google.com/spreadsheets/d/1kbxYGDeIOszgvjPYRdes-bELOBlojT_tjxe_RD9MVUQ/edit?usp=sharing

  • More work on instructions

    2-Zons5 days ago 4 comments

    With the help of some excellent feedback from @roelh I am reworking the instruction set.  I have decided to move away from the load / store syntax and am moving to a 68K style move instruction to help avoid duplicating instructions.  Each two operand instruction will be in the form of INSTR source,destination.  I am building a database in Access to help me come up with my list of instruction.  I've created a table of Operations : 

    MOV ADD SUB INC DEC PUS POP RES RTI RTS JMP JCA JZE JMI TST OR AND XOR XNR NOT JSR CMP

    And a table of Operands:

    A B X Y AB  XY SP PC # ## . $ $## SR +SP -SP +XY +AB

    (symbols are placeholders for Immediate, Absolute, Indirect and Immediate Indirect.)

    The tables have info like the width of each operand, the number of operands for the operations. and notes.  Just combining all these without using the same operand twice results in almost 8,000 instructions.  I am working on using query's to help me build groups of instructions. This will help me prioritize modes for different registers.  I want to give high functionality to the stack.  I will be using AB as the data focused register and XY as the pointer focused one.  I want to have the rules for the instructions be logical so you can easily remember which registers are capable of what.  My first version of instructions had limitations on pointer style programming.  With only 2 pointer registers (besides SP and PC) being able to do operations on memory will be important I think.

    I will look at coming up with an easy way of auto publishing my Instruction info from the database somehow.  I know office 365 have features similar to Google docs so It should be possible.  Just haven't played around with it yet.

    I'm already thinking that If this goes well (I build it in a reasonable amount of time).  I might try taking a crack at a 16 bit CPU.  I love the idea of having enough bits in the instruction code to have 3 bits for source register 3 bits for destination, 4 or 5 bits for operation etc.  would be really cool.  But I am getting way ahead of myself.  Lets just get this one done.  (reminding myself to watch the feature creep).

  • Fleshing out Instruction Set

    2-Zons6 days ago 2 comments

    I updated my instruction list using different addressing modes and the new ALU functions.  I am over by 57 Instructions.  Going to have to do some prioritizing.  I can't beleive they didn't even use all 256 Instructions on the 6502 and others.   I guess when they were drawing all the microcode manually on massive film, walking on it with their socks it kind of makes sense.

    https://docs.google.com/spreadsheets/d/1kbxYGDeIOszgvjPYRdes-bELOBlojT_tjxe_RD9MVUQ/edit?usp=sharing

    Added schematic for program counter

    https://upverter.com/2-Zons/28ed54fb010b5ac1/Program-Counter-16-bit-Register-for-8-bit-TTL-CPU/

  • More Schematic Work

    2-Zons6 days ago 1 comment

    Cleaned up the 16 bit register schematic quite a bit.  Getting better with the upverter software.

    https://upverter.com/2-Zons/2bdc142f8f99588f/16-bit--Dual-8-Bit-register-with-Up--Down-/

    Implemented the fast carry in the ALU for the flag and at bit 4.  Didn't change the  4 bit D-type registers to 8 bit ones as I don't have those chips.  I'm not going to order more chips till I flesh out the schematics.  Keep shipping costs to a min.  Hopefully I will only need one more order to get all the parts I need.

    https://upverter.com/2-Zons/2f903c2bed9cef6d/8-bit-ALU-w-input-and-output-registers/

    Started the master schematic the ties all the modules together.

    https://upverter.com/2-Zons/1a1b5dbb645ac3ba/8-Bit-TTL-CPU-built-on-a-breadboard/

    Put png exports of the schematics up in the gallery.

  • Schematic for 8 bit ALU w/ registers and flags

    2-Zons12/08/2018 at 06:54 6 comments

    Finished the 8 bit ALU design schematic based on @roelh 's square inch ALU design.  Includes design for the input register which has a control signal to load.  It's output is tied to the B input of the ALU.  The data bus will be the A input for the ALU.  The output register design is included, whose input is tied to the output of the ALU. It has a control signal to output to the data bus.  There is also the logic to set the flag lines (CArry, ZERo, and NEGative).  The Status register (not in this schematic) will have a control input that set's weather they flags are stored or not.

    https://upverter.com/2-Zons/2f903c2bed9cef6d/8-bit-ALU-w-input-and-output-registers/

  • Redesign based on feedback

    2-Zons12/08/2018 at 02:00 0 comments

    Reworking things a bit based on some excellent feedback.  I will be using an 8 bit ALU based on @roelh 's 4 bit ALU.  Instead of having hardwired to the AB, XY registers, it will have an input and output register.  It will then use the data-bus and it's input register for inputs and it's output can go anywhere one cycle later.

    I have been thinking about addressing modes for instructions.  I think I will keep it to direct, register, and immediate.  I have been thinking about offset addressing, but with only an 8 bit ALU I will run into page overrun problems.  Better to do this in software I think.  I don't think it's worth building a 16 ALU, as this would introduce a whole new set of problems in this new design, and I have to remember to try and keep it simple. 

    I've updated my block diagram, working on the new instruction set.  These are both a work in progress and very flexible.

    https://docs.google.com/drawings/d/1BW84zwO5effvYcdKjxzyki9cuvuHsM98z6nAamw4iTM/edit?usp=sharing

    https://docs.google.com/spreadsheets/d/1kbxYGDeIOszgvjPYRdes-bELOBlojT_tjxe_RD9MVUQ/edit?usp=sharing

  • Created Register Schematic in Upverter

    2-Zons12/06/2018 at 11:16 0 comments

    Completed V1.0 schematic of one of the 16 bit registers.  There will be two of these (AB and XY)  Created an Upverter project and added to the links.

    https://upverter.com/2-Zons/1a1b5dbb645ac3ba/8-Bit-Breadboard-CPU---AB-Register/

  • Parts are starting to arrive

    2-Zons12/06/2018 at 00:23 0 comments

    Received first shipment of logic chips (see photo) as well as an assortment of switches, and adruino which I will be using to program the EEPROM'S.  Still waiting on a few more items before I can start tinkering.

View all 10 project logs

Enjoy this project?

Share

Discussions

Peabody1929 wrote 4 days ago point

Do you have a goal for the instruction cycle time?  This could be the clock rate times the number of clocks it takes to execute an instruction.

  Are you sure? yes | no

2-Zons wrote 3 days ago point

I have a 16 step instruction counter, so the max instruction will take is 16 cycles.  I have a control line to reset it so I will be able to program each instruction to take the minimum amount of cycles.  I haven't started the microcode yet but from what I'm thinking most 8 bit instructions will take 3 cycles.

As for the frequency of the clock:  I will build a 555 circuit with a pot for initial construction.  Nothing too fast, probably max about 50Khz.  My plan is that once I've got the design to a certain point I will write a program to test every instruction and then see how fast i can get it to run without errors.  I've got 20MHz crystals, if it handles that I would get faster ones.  I would be happy If I could get it running at 10Mhz, but I'm totally new at this.  We will see. 

  Are you sure? yes | no

Steve Toner wrote 12/08/2018 at 01:00 point

OK, just glancing at the register schematic, I see a couple of issues:

1. I wouldn't drive an LED directly from the output of an LS chip.  There should be a current-limiting resistor in there.  Don't depend on the output resistance of the chip itself.  Because a TTL chip can sink more current than it can source, you typically pull the cathode of the LED down rather than trying to pull the anode up.  CMOS is different, and can typically source and sink (approximately) equal amounts of current.

2. You can't reliably drive an HC chip from an LS chip, especially if there's an LED pulling down the output level of the LS chip.  HC series expect a higher input voltage to indicate a logic '1'

3. Pullup resistors: typically a current-limiting resistor is used when pulling a pin to logic level '1' rather than connecting it directly to Vcc.  There are people who will tell you it's OK to connect a CMOS input directly to Vcc, buut it doesn't hurt to include it.  And if someone somewhere down the line might substitute a TTL chip for the CMOS part, then it is most certainly a good idea to include it.

4. U76A: Don't leave the unused inputs floating.  Ground 'em.

  Are you sure? yes | no

2-Zons wrote 12/08/2018 at 01:09 point

Thank you for the info.  These are the chips I have.  What would you recommend to interface the HC with LS?  I can go through my inventory and see what other HC I have, but I think I got the HC because I couldn't source the LS.  I will have go through my parts list again.

  Are you sure? yes | no

Steve Toner wrote 12/08/2018 at 01:55 point

You would typically use a pullup resistor on the LS output/HC input.  However, with the LED there you're still going to have problems.  Say it's a red LED that has a forward voltage of 2V.  The way the circuit is drawn (with the input of the HC chip connected directly to the anode of the LED), the HC chip is going to see 2V at its input even with a pullup resistor in there.  And it needs something like 3.5V.  If you were to drive an HC chip directly from an LS chip so that the HC is the only load (i.e., no LED), you'd probably be OK because the HC input draws minimal current so won't pull the nominal 5V output level down...

HCT parts are TTL compatible.  But the LEDs may still cause problems if they are not buffered.

Additional reading:

http://www.ti.com/lit/an/scla011/scla011.pdf

  Are you sure? yes | no

roelh wrote 6 days ago point

I agree with Steve. LS parts can not deliver much current in high state. You could however use low-current LEDs that light up below 1 mA, the series resistor can then be something like 2K2. 

For the part that receives this logic signal, you could use a HCT instead of HC part. A HCT will see a logic high when the voltage is above approx. 2.4 volt.

  Are you sure? yes | no

Yann Guidon / YGDES wrote 12/07/2018 at 01:26 point

For PC and SP, you might like https://hackaday.io/project/8121-discrete-yasep/log/27843-the-registers
This system uses cascaded 74'193 up/down counters for several registers, which would help keep your system simple.

  Are you sure? yes | no

Yann Guidon / YGDES wrote 12/07/2018 at 01:31 point

  Are you sure? yes | no

Paulo Constantino wrote 12/06/2018 at 19:58 point

why did I receive an email saying you mentioned my name ?

  Are you sure? yes | no

2-Zons wrote 12/06/2018 at 23:08 point

Not sure.  I didn't mention you, should I have?

  Are you sure? yes | no

Yann Guidon / YGDES wrote 12/07/2018 at 01:21 point

the site's server has some hicups...

  Are you sure? yes | no

roelh wrote 12/06/2018 at 12:40 point

Hi Martin,

nice to see another homebuilt cpu here !

I do have a few questions and some advice....

- I do not see logic instructions (AND, OR, XOR) in your ALU. Will you add them ?

- Do you have ideas about the instruction set that you will implement ?

- I suppose you will have a microcoded control. You have a lot of control signals, 48 total in your list. I suppose the microcode will be smaller than that, and the microcode will go to a few decoders to produce the control signals ?
  My experience is, that a datapath with registers and ALU is in most cases not so hard to design. The complexity comes when you want to control the whole stuff. 

- Your design for the 16-bit register seems much too complex for what it does, having 11 IC's, while it could be done with only two 74HC574 (with some loss of functionality).  Incrementing would be useful for PC, and inc/dec for SP. Allowing only 16 bit inc/dec (so dropping 8 bit inc/dec) for these will already simplify your register. For SP, you could consider the simplification to have the upper byte fixed, as in the 6502.

- For registers other than PC or SP, you can consider doing inc/dec with the ALU, in order to simplify these registers.

- It seems that your internal databus is 8 bit wide and the ALU 16 bit wide. I would suggest to make them the same size, 8 bit would be enough for a first design.

- I would suggest that you first build a software model of your processor (or a Logisim version), and make a few programs for it. That will show if things are missing, and will show if there are unused features.

For inspiration you could also look at the gigatron (https://hackaday.io/project/20781-gigatron-ttl-microcomputer) or my design for an ALU (https://hackaday.io/project/160506-4-bit-ttl-alu) and for the simplest TTL CPU ever designed (https://hackaday.io/project/161251-1-square-inch-ttl-cpu).

  Are you sure? yes | no

Dave's Dev Lab wrote 12/06/2018 at 18:35 point

@roelh - oh oh oh, my feelings are sooo hurt! you didn't include my stuff! hehe

https://hackaday.io/project/158510-ddl4-cpu

  Are you sure? yes | no

roelh wrote 12/06/2018 at 19:36 point

Sorry Dave !

  Are you sure? yes | no

2-Zons wrote 12/06/2018 at 18:48 point

@roelh  Thanks for the feedback.

1 - I wasn't planning on having anything but add / subtract in the ALU.  I haven't really wrapped my head around an ALU with more functions.  I know how to implement the add / sub with zero, carry, and negative status.  I looked at your ALU design, and it seems quite simple for all those functions.   If I can wrap my head around how it works I might try and implement it, that might mean more control lines however, but they would be exclusionary so it might be OK (see 3).

2 - If you look at the other page of that google docs spread sheet you will see a list of instructions that I have come up with, based on the control lines I have, that I can think of.  If I missed any, I would like to know.

3 - As for the microcode.  I plan on using EEPROM's to decode.  You are correct with the 48 lines.  I am simplifying the logic by considering exclusionary groups (see spreadsheet).  E.g. all the data out controls.  Only one of those control lines can be used at a time.  There are 12 of them.  So I can use 4 bits of combinational logic output that will drive a 4 bit mux to get up to 16 exclusionary control lines.  There are only 4 address out controls so I will use a 2 bit mux for those.  Total reduction of 10 bits (2 less ROM chips).  If you can think of other obvious ways I could reduce the control logic that would be awesome.

4 - I don't mind the complexity of the registers.  The SP, and PC will be a lot simpler because they won't have any logic for isolating the inc/dec of the individual bytes.  They will also be only inc and dec respectively. having incrementing registers will make the code much more efficient IMHO.  Having it in the register will allow it to be done in one cycle and added to load / store instructions with no extra cycles.  Having a register auto increment /decrement every time it is used as a pointer without extra cycles is a huge for software efficiency IMHO.  As for an 8 bit SP: I've always thought that a 256 byte stack is too limiting for software.  Probably the only problem I have with the 6502, I know I'm not the only one.   Also with my register / instruction design B and Y are selectable page pointers, setting the page with A or X.  I guess I'm a software guy at heart, and I don't mind making the hardware more complex if it makes for simpler more efficient code.

5 -Inc / dec in the ALU.. see 3 and 4.

6. Having an 8 bit ALU would be less chips, slightly more complex IMHO.  It might even be the same amount of chips.  I might design both and see. 

7. Although I do like the idea of running a sim of my design, personally I think it will be easier to test on the actual circuitry.  I will build each block (AB, ALU,XY, etc) on it's own bread board, starting with a clock circuit that can be paused and single step.  Then a register, Then the ALU etc.  Using LED's I can even test parts of each block. I might be wrong but to me this feels easier.  

8. I was aware of the gigatron (one of the inspirations for this project).  Thanks for the links to your ALU design.  I was writing this response point by point and then saw your link.  Had to change my response to your ALU question.  I was originally saying if I could see a design for an ALU with more functions. That square inch CPU is insane.  I think it's a good example of, if you simplify something too much it makes it can make it more complex in some ways.   

  Are you sure? yes | no

roelh wrote 12/06/2018 at 19:34 point

Thanks for your explanations. I overlooked the instruction tab in your spreadsheet. It does however not show addressing modes for the instructions. For instance, will ADD add from a memory address, from an immediate, or from another register ? 

I do not know a single CPU (except the square inch cpu) that has no logic operations. At least a NAND or NOR should be present I think, since other logic connectives can be derived from that.

Having inc/dec capability will indeed win you a few cycles, but that will be of limited use when the other parts of the cpu are not optimized for speed.

Maybe my own focus is too much toward lowest component count solutions....

The square inch cpu is indeed not very fast or practical, but I think not much has to be added to make it useful.

And before I get a complaint from @Yann Guidon / YGDES  that he is not mentioned, you might find his Processor Design Principles a good read: https://hackaday.io/project/46000-pdp-processor-design-principles

There are even famous processor designs named after this: PDP-8, PDP-11 !

  Are you sure? yes | no

Yann Guidon / YGDES wrote 12/06/2018 at 19:46 point

@roelh  me ? complain ? come on, never ever !!! :-P

I'm looking with interest (like all the CPU projects here) and wait for the perfect timing to invite our new friend to #Hackaday TTLers 

  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