Project: Crazy Small CPU

Thread Starter

DoctorWkt

Joined Aug 10, 2017
17
I've just completed building a CPU from about a dozen 7400-style chips:
  • three 74LS161 4-bit registers for the A & B registers and to store the flags output from the ALU

  • one 74LS157 4-bit multiplexer, to choose from where to load the A & B registers

  • two 74LS161 4-bit register/counters which are the Program Counter (PC)

  • one NE556 timer which acts as either a one-shot clock or a periodic clock

  • one RAM chip for memory: only 256 4-bit words are used

  • one ROM chip that acts as an ALU with two 4-bit inputs, sixteen operations, a 4-bit output and also four result flags: negative, zero, overflow and carry (NZVC)

  • two ROM chips that provide the control logic: one holds literal values and the other enables the control lines for the other chips
The CPU is small enough that you can build it on three breadboards, but it is powerful enough to calculate the Fibonacci sequence up to 27 decimal digits, and to draw a sine wave using Minsky’s circle drawing algorithm. The schematic for the CPU is attached, as is a Zip file with the assembler, a compiler, documentation on these tools and the CPU instruction set, and example programs. There is a Youtube playlist with videos describing the architecture and the build stages.

It makes a good educational tool for someone who wants to learn how a CPU works and how to build one.

Description of the CPU

I asked myself: "Crazy idea: what's the smallest number of 7400-style chips needed to build a CPU?". This is the result, my "crazy small" CPU. I've implemented it both in Logisim and also with real chips on two breadboards. The chip count ended up as three ROMs, one RAM, three registers, two counters, one multiplexer and one timer for a total of eleven chips.

The CPU has a 4-bit data path with an 8-bit address space (256 4-bit words). There are two 4-bit data registers, A and B, which can be loaded across the data bus from the RAM. The A and B values are sent to the ALU, which can perform sixteen different operations. The ALU result can be placed back on the data bus for writing back to RAM. Using the multiplexer, both the A and B registers can be loaded either from RAM or from part of the current instruction. This allows constant literal values to be used in the program. The instruction sequence is controlled by the 8-bit Program Counter (PC) which normally increments. The PC's value chooses a location in the top and bottom ROMs. The bottom ROM's value is the RAM location to access on this instruction. The top ROM's value encodes the six control signals for the CPU:
  • ALUop (3 bits): which ALU operation to perform
  • PCincr (1 bit): increment the PC (high) or load the PC (low)
  • Aload (1 bit, active low): load the A register from the multiplexer (low)
  • Bload (1 bit, active low): load the B register from the multiplexer (low)
  • Asel (1 bit): when loading a register, get data from the instruction (low) or from RAM (high). This control line serves a dual purpose. It also acts as an ALUop bit, giving the ALU sixteen operations.
  • RAMwrite (1 bit, active low): when high, read from RAM onto the data bus; when low, read from the ALU onto the data bus and write it to RAM
Finally, the ALU outputs four result flags: negative (N), zero (Z), overflow (V) and carry (C). These are buffered in the Flags register at the end of each instruction to be used on future instructions. The CPU can perform jumps. When the PCincr control line is low, the address from the bottom ROM is loaded into the PC, "jumping" to a new instruction. To do conditional jumps, the two ROMs receive and combine the PC's value and the NZVC value as the ROM address to look at. This means that there are sixteen ROM "pages", one for each combination of NZVC flags. So here is where it gets tricky. If you want the CPU to keep running one instruction after the other, you need to write the instruction sequence in all 16 pages on the ROMs. Thus, regardless of what the NZVC flags are, the correct next instruction will be found. So, how is a conditional jump like JCS (jump to location X if carry is set) done? Assume that this instruction occurs at location 12 in the instruction sequence. At location 12 on the eight ROM pages which would be accessed when the C flag is set, a "jump" instruction is encoded. At location 12 on the other eight ROM pages, a "nop" instruction is encoded. Only when the C flag is set will the ROMs access the pages with the "jump" instruction and jump. Otherwise, the CPU will perform the "nop" instruction and move onto the next instruction.
The ALU Operations
The ALU can perform sixteen operations based on the A and B inputs:
  1. A + B decimal
  2. A - B decimal
  3. A & B
  4. A | B
  5. A ^ B
  6. A + 1
  7. Output 0, flags set to B's value
  8. Output 0
  9. A + B binary
  10. A - B binary
  11. Output A
  12. Output B
  13. A * B binary, high nibble
  14. A * B binary, low nibble
  15. A / B binary
  16. A % B binary
The negative (N), zero (Z), overflow (V) and carry (C) flags are set after each ALU operation except the decimal operations. The "Output A" and "Output B" operations allow the ALU to pass the A and B registers through so they can be written out to RAM. The ALU is implemented as a 8K x 8 bit ROM. As input it takes four A bits, four B bits, a carry in bit and the four ALUop bits (including Asel). The output is the four result bits and the four flag bits. The ROM simply looks up the result based on the input. The binary and decimal addition and subtraction operations take and use the carry in bit. This allows N-bit or N-digit additions and subtractions.

Example Program
Here is an example program which calculates the first Fibonacci numbers which fit into four bits. The columns shown are: instruction number, instruction, operand, hex encoded instruction, list of active control lines, comment.
00: LCA 1 a801 Aload # Store 1 in locations 0 and 1
01: SMA 0 3d00 RAMwrite ALUpassa
02: SMA 1 3d01 RAMwrite ALUpassa
03: LMA 0 e800 Asel Aload # Load RAM location 0 into A
04: LMB 1 d801 Asel Bload # Load RAM location 1 into B
05: ADDM 2 3802 RAMwrite ALUadd # Add them and store in location 2
06: JCS end b00c # Result too big, exit the loop
07: LMA 1 e801 Asel Aload # Copy RAM location 1 down to 0
08: SMA 0 3d00 RAMwrite ALUpassa
09: LMA 2 e802 Asel Aload # Copy RAM location 2 down to 1
0a: SMA 1 3d01 RAMwrite ALUpassa
0b: JMP loop b003 # Go to instruction 3 to do it again
0c: JMP end b00c # End: do an infinite loop

If you run this in the Logisim version, you can see the last three values of the Fibonacci sequence in the first three RAM locations.
A ROM for an ALU?
Is implementing the ALU with a ROM fair game, or is it breaking the rules? You could argue either way. I could have hunted down a 74LS181 ALU to make the design really authentic. I'd need two more control lines for the five select/mode bits. Anyway, it's still one chip for the ALU, so the choice doesn't have too much of an impact on the design. A ROM also allows the designer to choose what ALU operations can be performed.
Design Changes
The chip count can be reduced. Right now I'm using two 74LS161 chips for the PC, but there is an obsolete 74LS469 chip that could replace both of them. That would bring the chip count down to ten. Next up, replace the two control ROMs with an AT27C1024 64Kx16 ROM chip (the only x16 ROM I could find): that would bring the chip count down to nine. Finally, the A and B registers could be replaced with one CD4508B dual 4-bit register as it has separate load lines: that would bring the chip count down to eight chips.
I'll probably never do this as I would have to rewire the whole thing!

Design Limitations
It's a Harvard architecture, so instructions and data are separate. There is only direct memory addressing: no pointers, no indexed addressing. The available instructions are determined by the control lines, so there isn't much that you can change. Despite this, we have been able to implement functions, a stack and a sort of recursion.
There is only one carry bit input and output by the ALU; this really limits any shift left/right operations to one bit shifts.
 

Attachments

Last edited:

bertus

Joined Apr 5, 2008
22,120
Hello,

Did you read the requirements to post in this forum?

When posting a project please include the following information:

  1. A clear title that describes the project appended by the word 'Project:', for example "Project: 555 Audio Oscillator".
  2. A list of parts, equipment, software used.
  3. Details of any theory, references or information that may be applicable.
  4. Any schematics, source code, etc.
  5. A short description of what to do.
  6. In the interests of manageability and security, project files/code/schematics must be locally stored on All About Circuits. This is not optional. Links such as You Tube may be used to provide supplementary information, however they must not provide the substance of the project.
  7. A picture displaying the finished project is preferred. It should be the first illustration displayed.
Please complete all details ON THIS SITE and not using a link to an other site.

Bertus
 

Thread Starter

DoctorWkt

Joined Aug 10, 2017
17
Hello,

Did you read the requirements to post in this forum?
Please complete all details ON THIS SITE and not using a link to an other site.

Bertus
Thanks Bertus. I've added in the architecture description from the other site, and I've removed all links to other sites except for the videos on Youtube. Please let me know if there is anything else I have not done correctly.
Cheers, Warren
 
Top