Engineer in Electronics and Computer Engineering

4-bit Processor

4-bit Processor

Overview

Schematic and Simulations

Before I started to build anything, I wanted to make sure that my design actually worked as intended. I mainly used the program LogiSim to simulate the circuit behaviour, and then I did the actual implementation of the PCB in KiCad.

Circuit Simulation

I found the program LogiSim to be a good starting point. Some of the components, for example the memory module, can be represented with a single symbol that acts as an abstraction layer. This gave me a high-level overview of the circuit before I started with the actual implementation. Figure - shows a simulation of the circuit behaviour.

When I had confirmed that the simulation worked as intended, I remade the circuit with discrete chips instead. This removed some of the abstraction, which was helpful in order to start thinking about the actual implementation of the circuit.

Hardware Modules

The processor is designed in a module architecture, where each block serves a specific purpose. The modules then work together to make up the complete processor. This chapter explains the design process of each of the modules.

Clock

Each sequential component in a digital circuit needs to know when to proceed to the next action. This is the purpose of a clock, it acts as a common trigger that synchronizes the actions in the circuit. In the case of this processor, the clock tells the registers when to store new data and when the carry bit from the ALU should be read.

I wanted to be able to use the clock in two different modes, one where the user can input manual pulses and one where the clock progresses by itself. I found the circuit from Ben Eater to suit my needs, so my circuit is mostly identical with some minor changes. One difference is that my circuit is lacking a HLT signal since that instruction is not part of my instruction set. The other difference is that I changed the select logic to NAND-logic so that I can use the unused gates for other parts of my circuit. This change also reduced the total gate count.

The below image shows the clock circuit implemented on a breadboard, and the full schematic can be seen in appendix A.

Registers

When the processor is running, it needs a place where it can temporarily store information. The information could for example be the result of an addition, or the input from a user. This is the purpose of registers, they store a small piece of information for a short amount of time. Different registers serve different purposes. For example, the program counter is responsible for storing the current instruction address, and the output register is where the result is stored and displayed to the user.

My processor has 4 registers: A, B, OUT and PC. These were implemented using 4-bit binary counters. While there are specific register IC:s, I found it easier to use counters since I needed that functionality for the program counter anyway. The counter can also be used as a regular register by deactivating the count enable pin.

For the output register, I wanted to be able to display two base-10 digits. This is because the processor operates on 4 bits and can thus output values from 0-15. By simply using a BDC (Binary Decimal Converter) the output would be in hexadecimal if the output is larger than 9, which is not as human-readable as a base-10 number. The trick is to convert the binary number into a Binary Coded Decimal (BCD) number. A BCD number is encoded just like a binary number, except it rotates at the number 9 just like a decimal number would. This makes it suitable for outputting to 7-segment displays.

In order to implement this, the circuit needs some way of detecting when the number is greater than 9. Figure - shows a circuit that turns on a signal when this condition is met.

By adding 6 to the number if the condition is met, the number naturally wraps around to the correct value in BCD-form. The circuit for the output register is shown in figure -.

The below image shows the registers implemented on a breadboard, and the full schematic can be seen in appendix A.

ALU

The ALU (Arithmetic Logic Unit) is responsible for the actual computation of the operands. In many cases the ALU can perform different operations based on the opcode, for example addition, subtraction, multiplication and logical operations such as OR and SHIFT. This ALU is however limited to only addition in order to keep the circuit simple.

My ALU design is based on the design of -, but it has been modified to be able to perform addition directly between registers. The original design always fetched the second operand from the immediate value from the instruction, which meant that I had to add additional circuitry so that both operands could be registers.

The below image shows the ALU implemented on a breadboard, and the full schematic can be seen in appendix A.

Memory

The instruction memory is the part of the circuit where the actual instructions for the program are stored. These instructions tell the computer which operations and calculations to perform. I knew I wanted to be able to change the instructions without having to bring out an external board each time, so that’s why I decided to make a diode memory out of DIP-switches. You usually don’t design an instruction memory this way since it’s very bulky, but since my processor is purely educational this wasn’t an issue for me.

Control Logic

The control logic is responsible for making the processor perform the correct action based on the current instruction. It does this by reading the opcode from the instruction memory, and based on this activating the correct control signals. These control signals determine which register is being written to, and which data is being fed into the ALU.

In order to implement the control logic, I first needed to determine which instructions I wanted to include in the instruction set. Since the processor is operating in 4 bits, the number of possible instructions are 24=16. The circuit I based my design on was lacking the ability to add the contents of register A to register B, and vice versa. This was an essential operation in order to calculate the Fibonacci sequence, which was a goal with making this processor.

Figure - shows the instruction set I decided to settle for. I added the two instructions “ADD A, B” and “ADD B, A” which performs addition between the two registers. The instructions were grouped into instruction types, and I tried to order the instructions so that the logic would be as simple as possible.

The logic was implemented using K-maps in order to minimize the gate count. Figure - shows the logic for the LOAD REG control signals, and the rest of the control signals were done in a similar way.

The expression for the program counter needs to be modified slightly since it is also dependent on the carry bit. As seen in figure -, the JNC instruction only writes to the program counter if the carry bit is not set. If the carry bit is called E, then the expression for the program counter becomes PC=A'+B+C'+D'E.

This circuit was implemented using discrete logic chips. One logic chip can contain up to 4 gates, and if I only need one of them it would take up unnecessary space. In order to prevent this I decided to translate all my expressions to NAND-logic. This is possible since NAND is a universal gate and can implement any boolean logic function.

Speaking of optimization, one important thing to notice is that some of the inputs are the same for different expressions. Implementing these multiple times would be redundant, so one optimization is to reuse the expressions that are shared between the inputs. This reduces the gate count from 17 down to 11, which means that the optimization saved me 6 gates.

The below image shows the control logic implemented on a breadboard, and the full schematic can be seen in appendix A.

Board Design and Demo

At this stage in the design process I was ready to do the actual implementation of the circuit board. I designed it using KiCad since it’s free and very capable.

Custom KiCad Library

The most common approach when designing a PCB is to find the symbols and footprints in a pre-made component library. However, I usually prefer to create them myself since I can then customize them however I like. Figure - shows the symbols I created for my custom library.

KiCad also offers the option to insert a 3D-model for the component. Although this is entirely optional, I find it useful to see the physical dimensions of all the components in a 3D-render of the PCB. Figure - shows the 3D-models I designed for this circuit, and all of them were made using Fusion 360.

PCB Design

I initially intended to do a 2-layer board, and the main reason was to bring down the cost. A 4-layer board is more expensive to manufacture, especially a board this big. When doing the routing however, I found it really difficult to have enough margin to the board edge. Some of the traces needed to be long since the components on the board are so spread out, but routing it this close to the edge is not ideal since the board edge will essentially work like an antenna. This is bad for EMI (Electro Magnetic Interference) and should therefore be avoided.

The solution for me was to change to a 4-layer board. Although it’s more expensive, it means that I can route the really long traces in another layer so that they don’t have to be so close to the board edge. Figure - shows the stackup I chose for this PCB.

The highlighted signal in figure - is the reset signal, which was routed close to the edge for 150 mm in the 2-layer board. The image also shows how this was rerouted in the PWR + SIGNAL layer for the 4-layer board, further from the board edge. The final routing of all the layers can be seen in appendix B.

Executing Programs

BOM (Bill of Materials)

Conclusions

This is a project I’ve wanted to do for a while, and I’m glad I finally got the chance to do it. I’m happy with how it turned out and it has been a really fun challenge. The capabilities of the processor are very limited and would not really be useful with today’s standard in processing power, but this circuit was only intended as an educational tool. I feel like I’ve gained knowledge in computer architecture during this project which has been very exciting.

© 2025 Emil Berg. All rights reserved.
No use or copying without permission.