• Please review our updated Terms and Rules here

Making my own CPU

per

Veteran Member
Joined
Jan 21, 2008
Messages
3,052
Location
Western Norway
Some time ago, I was talking about making my own CPU out of simple TTL logics. Now I actually have gotten around making one. It is not the easiest processor to program, but it should be possible to do most stuff with the instruction set I have implemented.

There is a lot of technical information below, but you don't ned to read it unless you are curious. There is a small non-technical pharagraph at the end.

The memory is organized quite odd. for each address, there is 16 bits (AKA: 16-bit words). However, the CPU is 8-bit, and everything within the CPU happens 8-bit at a time. The instruction is allways in the lower 8 bits of a word, and the high 8-bits is to be used as imed. data for that instruction, if the instruction says so. There is seperate functions to write/read to/from the High 8-bits and the Low 8-bits. There is also instructions for I/O.

The use of registers are also quite limited. All registers have their function, and there are no register for just storing a value. All operands in an instruction are actually defined as registers, even the ALU.

It is to note that all ALU functions have to be done quite manually; the ALU mode may be changed/set, data may be fed into the ALU input registers, the result must then be read from the ALU output register and then processed. It's quite flexible, but it uses more code to do less work.

There is one flag used when the ALU is in addition or subtraction mode. This is an overflow/carry flag, and it can be used with conditional instructions. There is in fact only 128 instructions, but all of them got an unconditional version and a conditional version. The unconditional ones are allways being executed, while the conditional ones are only being executed if the flag is set. There is also instructions to lock/unlock the flag in cause the ALU has to be used within blocks of conditional code.

There are no instructions for jumps, but jumps can be achieved by writing directly to the P register. By using the ALU and the conditional instructions, conditional jump and left-rotate operations are possible to achieve.

Last, the P register will only be able to address 256 instructions. Since this is by far from doing anything productive, I plan to divide this into four "windows" to a bigger memory pool. Changing the pointers will be done with I/O and some hardware on the memory board, whitch I haven't designed yet.

Registers:
  • A = Accumulator. Main input to the ALU. Can be written to, and the value stored can also be read as it is. It's value is constantly fed into the ALU.
  • AL = Temporary ALU register. Secondary input to the ALU. Can be written to, but when read from, the result from the actual ALU operation is being returned.
  • D = Data output register. This register serve as a buffer for the byte being written to memory durning a memory write instruction, and in out instructions too. A value can however be written to it and read as written, but it is to note that it will automaticly be updated if any memory Write/Out instructions occours.
  • AD = Address register. All memory read/write in/out instructions uses this register for the address/port to read/write in/out from/to. This register must be set in advance of the read/write in/out instruction, and the value can also be read back.
  • P = Instruction pointer. Points to the current instruction, and it is increased after every instruction is done executing, even after writes to this register. Can be written to in order to achieve jumps, and can also be read (usefull for indirect jumps).
  • IL = Low input register. This is the lower 8 bits of the word making up the instruction. It can only be read, as all writes are redirected to the OL register
  • IH = High input register. This is the same as IL, but with the upper 8 bits of the instruction word instead of the 8 lower bits. Writes are also redirected to OH, not OL.
  • OL = Low output register. Lower 8 bits of the output register. The output register are a write-only register to a data-bus that is constantly holding the data of the output registers. Other cards can use this value for a various functions, only up to the imagination of the card's creator. Al reads are redirected to IL.
  • OH = High output register. The same as OL, but with the upper 8 bits instead. It's also write-only, so all reads are redirected to IH.
  • NO = Nothing. Reads the value of FFh, and nothing happens durning writes.

ALU modes:
  • Add(ition)
  • Sub(traction)
  • And
  • Or
  • Xor
  • Nand
  • Exception: Lock flag
  • Exception: Unlock flag
Instruction set:
Code:
mov  regD,regS = Register regS is read and the value returned is stored in regD.
sam  func.     = Sets the ALU mode to func.
hlt  msk.      = The CPU halts, but it can be restored with the recover input lines (1-3) that are masked in the 3-bit value of msk.
out  [AD],regS = Register regS is written to register D and then Out'ed to the port defined in register AD.
in   regD,[AD] = The In'ed value from the port defined by register AD is written to the register regD.
sth  [AD],regS = It reads register regS and stores it in register D, and then stores it into the high 8 bits of the word pointed to by AD.
stl  [AD],regS = It reads register regS and stores it in register D, and then stores it into the low 8 bits of the word pointed to by AD.
rdh  regD,[AD] = The high 8 bits of the word pointed to by AD are read and stored in register regD.
rdl  regD,[AD] = The low 8 bits of the word pointed to by AD are read and stored in register regD.
movc regD,regS = If the flag is set, then register regS is read and the value returned is stored in regD.
samc func.     = If the flag is set, then sets the ALU mode to func.
hltc msk.      = If the flag is set, then the CPU halts, but it can be restored with the recover input lines (1-3) that are masked in the 3-bit value of msk.
outc [AD],regS = If the flag is set, then register regS is written to register D and then Out'ed to the port defined in register AD.
inc  regD,[AD] = If the flag is set, then the In'ed value from the port defined by register AD is written to the register regD.
sthc [AD],regS = If the flag is set, then it reads register regS and stores it in register D, and then stores it into the high 8 bits of the word pointed to by AD.
stlc [AD],regS = If the flag is set, then it reads register regS and stores it in register D, and then stores it into the low 8 bits of the word pointed to by AD.
rdhc regD,[AD] = If the flg is set, then the high 8 bits of the word pointed to by AD are read and stored in register regD.
rdlc regD,[AD] = If the flag is set, then the low 8 bits of the word pointed to by AD are read and stored in register regD.

End of technincal stuff.

I estimate the CPU board to end up at about more or less 50 IC's, and the idea is to fit it on one board. Then there will be a board for RAM and ROM, and eventually there will be a board with serial I/O. For all this, I plan to make a front pannel connected to a bus with four slots. I should be able to disable each of the four slots by switches on the front panel, and I would also be able to controll the bus with the front panel.

As of price, I expect it to be expensive if I ever decides to make it. I don't know, but with four 1-square-foot boards and hundreds of components it can easily cost several hundred $. Maybe I'll be crazy enough one day...
 
I've seen stranger instruction sets.

How about an OISC? Or something like the MAXQ2000 from Maxim.

Whatever you choose, my hat's off to you for carrying it through.
 
I had a grand scheme to try to build simple 4-bit adders and build HUGE low-cost panels of them and translate x86 instructions to whatever scheme I ended up using.. Needless to say with little electronics skill this never got past the "I drew a circuit diagram" stage. Good luck though!
 
This thing of using non-programmable logic seems to be fairly important. Otherwise, the design might well fit inside a couple of CPLDs or a single FPGA with room to spare.

It's really strange though--I don't see anyone wanting to build their own CPU from discretes (i.e. transistors, capacitors and resistors) or magnetic cores or tunnel diodes...
 
I just wish there was an easy to read how-to book on this. I'd build it with whatever. Hell I'd jump with joy just building an addiing machine from parts and understanding it.

Andrew was it posted some book I think before that he thought was a good intro to circuit design didn't he? Am I just dreaming?

Per, congrats of course. Did you build a small version or draw the schematics in some app?

Either way very impressive.
 
I've just drawn the design on paper, by hand in fact. I really should test it in a simulator before attempting to make it.

The first thing I did was to draw an overall diagram of the register part. Then I put together the instruction set, based uppon the registers from the overall diagram. Try to do it systematic, like make some bits contain the same information for all of the op-codes (it'll save you a lot of troubble with the controll part later). The third thing I did was to make a simple timing diagram of the signals required by the register part and the other cards on the bus to complete any of the op-codes. I also clearly marked what of the signals that happened every cycle and what signals that only occoured durning some of the op-codes.

Then the most difficult thing comes; Designing the controll part. I started by making a clock decoder, in my cause a device with clock, halt request, unhalt and reset inputs, and outputs telling where in the clock cycle the CPU are. Then you should make an op-code decoder. this may be a little tricky if you have a complex instruction set with no systematic patterns. The output here should be one signal for each op-code. The last part is where you'll have to combine the outputs from the clock decoder and the op-code decoder to recreate the exact signals from the timing diagram you created earlier. This is in fact the simplest part since you already got the signals there from the clock decoder, so all you have to do is to just combine them to make them appear with rigth lengths and at the rigth place, then you have to mask them with the output from the op-code decoder to make the signals appear only durning the rigth op-code. Then the only thing left is actually a way to handle the rest of the information within the op-codes.

The components I use are the following.
Controll part:
A pile of And-gates, a handfull of Or-gates, some demultiplexers, a multiplexer, a latch, a transparrent latch, and some misc. other single gates.

Register part:
A load of Xor-gates (for the 'add' and 'sub' functions of the ALU), a somewhat lot of And-gates (also for the ALU), quite a few buffers, a little fewer latches, a multilexer, and some misc gates (mostly the rest of the ALU functions).


All of this logic can be expanded to Nand gates (or Nor gates), but that would be a huge job, and I don't even want to think about how long time it would take and how much paper I would need!


One 1-bit add/sub (with carry/overflow flag in- and output and add/sub select input) block of logic requires 5 Xor gates and 2 And gates. If the select input are removed ('add'-only), then only Xor and 2 And gates are required per bit.

---

This is by definition a third generation computer. A computer made out of core memory and transistors/resistors/capacitors are defined as a secon generation computer, and I really don't got enough experience with thransistors to even think about making a computer out of them.
 
This is by definition a third generation computer. A computer made out of core memory and transistors/resistors/capacitors are defined as a secon generation computer, and I really don't got enough experience with thransistors to even think about making a computer out of them.

What I had in mind was "core logic", not "memory", which you could call first-generation logic. Google "Univac Solid State" and "Parametron" for an idea of two types of core logic (there are several). The Univac SS machine used comparatively few transistors (mostly used to drive indicator lamps), had a master clock generated by transmitting tubes and used a drum for memory. The last time I looked, there was still a complete operational system somewhere in Europe. Not bad for more than 50 years.

My point of all of this is that preservation of knowledge is important. I'll wager that you weren't even aware that computers had been constructed with magnetic cores as their only logic elements. In another 50 years, will any memory of this be around, save for some corner of some dusty archive?
 
Last edited:
I have now gotten as far as putting the controll part into a software TTL simulator. I use CEDAR Logic 1.5, because it got one of the best easy-to-use and most TTL-like interfaces of all the freeware Logic simuators. CL got a wide support of single gates, but when it comes to the more complex IC's, I've had to combine simple logic and some of the standard functions to get it to equalent the TTL chips I am working with. I found and corrected the few errors I found, and it did successfully execute all of the op-codes I threw at it.

Just note that CL is unstable on at least my computer, and that you should allways save your work in two different files. In addition, make sure to allways have a backup copy of those two files, and never ever try to open the backup copies. If CL causes a BSOD, the current open project file will get corrupted, if not totally erased. It tend to crash when handeling files while you try to do anything else inside the program, and often when you try to close the program. You should also keep a copy of the installation program as CL may erease parts of itself durning a crash.
 

Attachments

  • CPU (backup).zip
    16.1 KB · Views: 1
It works!!!

I have now completed making a simulation of the CPU in CEDAR Logic, and as you see above; it works. Attached to this post is the project file and the memory dumps with the test program I used, along with the test program's source code (well documented).

CEDAR Logic can be found here: http://sourceforge.net/projects/cedarlogic/

To use the files, open CEDAR Logic and open the CPU.cdl file through the "open" function. Fan 1 is the controll part, Fan 2 is the register part, and Fan 3 is the RAM part. You should start by selecting Fan 3 and double-click on one of the RAM modules and make sure there are some values stored.

To start the simulation of the CPU and test program, go to Fan 1 and make sure the /Reset line is red, and then toggle "Force unhalt" black and then back to red. When the test progrm is done, it will do a fully recoverable halt, and you will be able to check the results by doubleclicking the RAM modules in Fan 3.

I will do a part-count soon to see how many IC's I actially need in order to make the CPU-board.
 

Attachments

  • CPU.zip
    49.5 KB · Views: 1
TV typewriter??? What?

I generally plan to attempt to write a BrainFøkk Interpreter for it though, but it may take some time...
 
Last edited:
What I had in mind was "core logic", not "memory", which you could call first-generation logic. Google "Univac Solid State" and "Parametron" for an idea of two types of core logic (there are several). The Univac SS machine used comparatively few transistors (mostly used to drive indicator lamps), had a master clock generated by transmitting tubes and used a drum for memory. The last time I looked, there was still a complete operational system somewhere in Europe. Not bad for more than 50 years.

My point of all of this is that preservation of knowledge is important. I'll wager that you weren't even aware that computers had been constructed with magnetic cores as their only logic elements. In another 50 years, will any memory of this be around, save for some corner of some dusty archive?

Hi
The Univac used the cores mostly as amplifiersand used diodes for the actual logic.
The Parametron used the cores for actual logic as well.
The Univac was basically the same function as the memory and used the
fact that a saturated core responded different than an unsaturated.
The parametron used a resonent circuit that took on a phase depending
on the logic value but also depended on the saturation of the core.
Both would continue to operate for ever if they didn't need tubes
and transistors to supply signals and power.
Dwight
 
Hi Dwight. In his early career, Seymour Cray developed a military computer when he was with UNIVAC that used core logic. Do you know anything about it?

There was also multi-aperture core logic as well.
 
And Burroughs had a novel device called a core counter, essentially a divide-by-ten counter/non-volatile memory that would issue a pulse for every tenth pulse in; used a lot in their E series which were their first electronic replacement for their (electro)-mechanical posting machines (decimal-based instead of binary of course). Most of the actual logic was implemented with diodes.
 
Also see the book "Digital Magnetic Logic" by Hewitt Crane, David Bennion and David Nitzan (1969, McGraw Hill, ISBN B0006BW0C4) for all-magnetic logic. This found application in railroad switching and elevator control--it wasn't affected by temperature extremes or destroyed by lightning-induced surges. Extremely reliable stuff, but somewhat slow.
 
Hi Dwight. In his early career, Seymour Cray developed a military computer when he was with UNIVAC that used core logic. Do you know anything about it?

There was also multi-aperture core logic as well.

Hi Chuck
I'd not heard that. I'd guess it was the same as was used for the other machine.
If not, maybe a patent search for Cray's stuff might show something.
I recall rading the patent for the Parametron several times before it
made sense but now I've forgotten exactly how it worked. I do know
that it depended on the phase of the signal relative to a reference
when the calculation was done.
Of course, a simple core memory is a simple two input logic element.
Dwight
 
Hi Dwight!

I went to the USPTO web site and did a search for all "Cray" patents and hit paydirt. Patent 2,741,758, April 10, 1956: "Magnetic core logic circuits". The next one is 3,035,182, "Diode transfer circuit" with Jim Thornton. This seems to have something to do with handling core readout signals.

3,039,688 with Moe, Smith and Miller describes the "Incremental Computer" for the military and is the one I was thinking of. Al has some photos of it on bitsavers. I don't know if it was ever deployed, but you could definitely see the Univac Solid State machines in the description, right down to the drum. Pretty small machine for the time; a 5 msec. cycle time.

3,041,466 (with Hendrickson) is more core logic circuits; more sophisticated.

3,041,582 is yet more core logic circuitry. 3,041,583 concerns using magnetic cores as pulse shapers, Later patents (ca. 1958 ) are CDC patents and concern more traditional circuitry.

There was a 60's book on various logic mechanisms that included traditional transistor-diode logic as well as core logic, but also had some other interesting ideas, including microwave logic (parametric amplifiers?). I wish I could remember the title, but you know how fuzzy the gray matter gets. Parametrons are still a pretty hot (forgive the pun) subject in cryogenic logic.

Ah, now there's a do-it-yourself project--construct a computer using Josephson junctions...
 
Last edited:
Back
Top