Your First Computer: Difference between revisions
N00basaurus (talk | contribs) Major rewrite to focus more on teaching the reader what it takes to design and build your own computer, as well as teaching the reader a little more theory. With the build guide serving more as an example than instructions to follow. |
N00basaurus (talk | contribs) m →Instruction Set: clearing up an ambiguous "it" |
||
| Line 51: | Line 51: | ||
==== Instruction Set ==== | ==== Instruction Set ==== | ||
This is the most influential part of planning. This will not only dictate what your computer does, but also how | This is the most influential part of planning. This will not only dictate what your computer does, but also how programs will be stored in program memory. | ||
You can design your own instruction set from scratch if you want something more complex. But for our instruction set, we will be adding 4 types of instructions: load immediate, operate, move, and jumping/branching. These will be organized with the prefixes <code>00</code> <code>01</code> <code>10</code> and <code>11</code> respectively. | You can design your own instruction set from scratch if you want something more complex. But for our instruction set, we will be adding 4 types of instructions: load immediate, operate, move, and jumping/branching. These will be organized with the prefixes <code>00</code> <code>01</code> <code>10</code> and <code>11</code> respectively. | ||
Revision as of 06:25, 12 October 2025
Introduction
This guide is for anyone who is interested in learning how computers work, and wants to learn by building a computer for themselves, but doesn't know where to start.
This guide assumes the reader has a basic understanding of Logic Worlds building mechanics, and has some experience building some of the more intermediate components, such as adders, memory, and decoders. As well as at least some understanding of the binary numbers system.
The first part of this guide will go over the hardware of a very basic computer system. This guide will not be covering things like text and image processing, internet browsing, operating systems, file systems, windows and graphical user interfaces and other systems generally associated with personal computers. These systems are all built using software, and covering them, as well as software in general, is an entire subject unto itself. This guide will only be focusing on creating hardware that can execute software. Furthermore, this guide will only be focusing on core hardware, the bare minimum required to run software. This guide will not be covering peripheral hardware such as screens, graphics processor units, storage devices, co-processors, or multi-core setups. Nor will this guide be covering the topic of source code compilation. These are all topics that require their own study and as such are outside the scope of this guide.
The second part of this guide will be covering the process of designing your computer. It will bring up key details you should consider when planning your computer build, as well as providing a basic layout that you can use if you don't want to design everything from scratch yourself.
The third part will of this guide will cover building your computer.
Hardware Theory
All computers, regardless of complexity, need at least these 4 components. Program memory typically made using read-only memory, an ALU, working memory typically made using individual registers and random-access memory, and a control unit.

Program memory is where the program to be executed is stored. It takes the form of a list of binary numbers called machine code. The computer will step through this list one number at a time, grabbing each number, interpreting it, and performing an action corresponding to that number. This process is referred to as the fetch-decode-execute cycle.
Actions that a computer can perform can vary greatly, but two of the most common actions are moving data around, and performing operations using data.
The ALU is what allows a computer to perform these operations, and working memory is where the data being operated on is stored.
Moving data around may seem pointless at first, but often ALU's don't have direct access to working memory, but instead must use whatever is stored in more local registers. Data must therefore be juggled between working memory and registers in order to give the ALU access to the entire dataset. It's also useful for organizing data into larger data structures.
While it might be hard to wrap your head around this at first, everything that computers do can mostly be reduced to these two operations: moving data around, and operating on data. How these two operations can be structured to do things like browse the internet or play games requires a study of software, and is thus outside the scope of this article. But under the hood, millions of these operations are happening at a rate of billions a second, and it's this size and speed that allows computers to perform much more complicated tasks.
Coordinating these instruction fetches, data moves, and ALU operations is the control unit. It's job is to decode the binary integer fetched from program memory and decide what control signals to send out and when.
While this module can get very complicated, the simplest control unit consists of a lookup table that takes the current instruction integer and the value of a counter as a combined input, and produces all the read, write, and function signals the computer needs as an output. A clock is used to increment the counter, and produce a rising edge for the write signals, and the table is configured to read from program memory and write to an instruction register when the counter is 0, then increment an instruction pointer register when the counter is 1. From there, the table can be configured to do different things depending on the value of the instruction register. The counter register is reset when the instruction is complete, and the fetch-decode-execute cycle repeats.
On top of being able to move data around and perform operations, there is a third common type of action a computer can perform called a control flow instruction. These consist of instructions like jumping, conditional branching, calling and returning, and software interrupts. Though we'll only be focusing on jumping and conditional branching here. These all have one thing in common, and that is to break the linear sequence of the program.
Normally, as part of the fetch-decode-execute cycle, the instruction pointer used to index the program memory is incremented after each instruction fetch. Setting up the next instruction in the list to be executed when the current instruction is complete. By writing a new value to the instruction pointer, we queue up a different section of the program memory to be executed next.
This is often used to create infinite loops in your program, or finite loops if you use a conditional branch that resumes a normal execution sequence if a number comparison comes up not equal.
These three action types are the minimum required to create a turing complete computer - a computer that can calculate anything.
Planning A Computer
While you might be inclined to jump head-first into building, computers are complicated things, as the previous section shows. A little bit of forethought is required before you start building in order to help guide your building decisions. Otherwise you will end up with a computer that's too messy to modify, and if it ends up malfunctioning, it'll be too messy to troubleshoot as well. Documentation is key.
Before you begin, think about what you want this computer to do. What ALU functions do you want it to have? What special instructions or special hardware? You'll also want to consider key details such as the width of your ALU, the width of your working memory and program memory, as well as the size of these memory modules, as this will determine the width of your address bus and indexing registers.
Example Computer
Since you'll likely not know what to add, this section will provide for you a very basic plan for you to follow.
Component Sizing
Our computer will be very basic. We'll be using an 8 bit ALU and 8 bit working memory. We can do a lot with 8 bits without needing to make the hardware too big.
We'll also have 256 addresses in our program memory, so an 8 bit address bus and 8 bit indexing register is in order, since 2^8 is 256. The width of the program memory is determined by our computers instruction set.
Instruction Set
This is the most influential part of planning. This will not only dictate what your computer does, but also how programs will be stored in program memory.
You can design your own instruction set from scratch if you want something more complex. But for our instruction set, we will be adding 4 types of instructions: load immediate, operate, move, and jumping/branching. These will be organized with the prefixes 00 01 10 and 11 respectively.
We will be squeezing our instructions into 8 bits, making our program memory 8 bits wide. With 2 of those bits being used as a prefix, that leaves 6 bits to be used as instruction arguments.
Below is the instruction set we will be using:
| Name | Opcode (8 bits) | Opperands | Description |
|---|---|---|---|
| Immediate | 00 xxx xxx | x: The immediate value. | Puts a value given by x into register 0. |
| Add | 01 000___ | Adds the values in register 1 and 2, and puts the result in register 3. | |
| Subtract | 01 001___ | Subtracts the value in register 1 from register 2 and puts the result in register 3. | |
| And | 01 010___ | Bit-wise ANDs the values in register 1 and 2, and puts the result in register 3. | |
| Or | 01 011___ | Bit-wise ORs the values in register 1 and 2, and puts the result in register 3. | |
| XOR | 01 100___ | Bit-wise XORs the values in register 1 and 2 and puts the result in register 3. | |
| Not | 01 101___ | Bit-wise NOTs the values in register 1 and 2 and puts the result in register 3. | |
| Move | 10 xxx yyy | x: The register to move data from. y: The register to move data to. | Moves the data from register x into register y. |
| Test | 11 000___ | Tests the values in register 4 and 5 against each other, putting the result into the flags register. | |
| Jump zero | 11 001___ | Jumps to the instruction in register 6, if the zero flag is ON. | |
| Jump carry | 11 010___ | Jumps to the instruction in register 6, if the carry flag is ON. | |
| Jump negative | 11 011___ | Jumps to the instruction in register 6, if the negative flag is ON. | |
| Jump equal | 11 100___ | Jumps to the instruction in register 6, if the equal flag is ON. | |
| Jump | 11 101___ | Jumps to the instruction in register 6, regardless of an flags. |
Notice that most instructions only use 3 of the 6 argument bits. Move immediate uses all 6, allowing the user to load an immediate value of 0-63, and move also uses all 6 to index 2 registers.
Registers
Since we have 3 bits available to index registers with, our computer will include 8 all-purpose registers.
If you design your own computer, you will need to consider what registers to include, and what will they be used for.
In our case, while all of our registers will be general purpose, meaning you can use them for whatever purpose you like, most of them will be used in a specific way for specific instructions. The registers and their purposes are as follows:
- Register 0 - destination for immediate values
- Register 1 - source of one argument of an operation
- Register 2 - source of the other argument of an operation
- Register 3 - destination of the result of an operation
- Register 4 - source of one argument for a comparison
- Register 5 - source of the other argument for a comparison
- Register 6 - target address for a jump
- Register 7 - general purpose
Note that the instruction pointer and instruction register are separate to these all-purpose registers, so our program will not be able to directly edit the values in these registers.
Editing of these registers is done by the control unit either during the fetch-decode-execute cycle, or through the use of a jump instruction.
Flags
If you decide to include conditional branching in your instruction set, you will need to decide what conditions (called flags) you want to check for and how you're going to check them.
In our case, we will have the following 4 flags in our computer:
- Zero flag - This flag will be ON only if the first value from the last test instruction was equal to 0.
- Carry flag - This flag will be ON only if that last add (or subtract) instruction carried/overflowed.
- Negative flag - This flag will be ON only if the first value from the last test instruction was negative (had its most significant bit ON).
- Equal flag - This flag will be ON only if the values from the last test instruction were equal to each other.
We will also be storing the states of these flags in another register called a flag register. Allowing us to capture the state of these flags with one instruction (test) and use the state of these flags in another instruction (jump).
You do not need to store the state of these flags in a register, or perform a test and branch in two separate instructions. You can perform your comparison and use the results immediately, if you want. Doing so will just require a more complex execution sequence, and possibly bigger instructions.
Example Program
Putting everything together, we can use our instruction set to write a Fibonacci program:
; Initialise registers
Immediate 0 ; 00 000000
Move 2, 0 ; 10 000 010
Immediate 1 ; 00 000001
Move 1, 0 ; 10 000 001
;
; Main loop
Add ; 01 000 ___
Move 2, 1 ; 10 001 010
Move 1, 3 ; 10 011 001
Immediate 4 ; 00 000100
Move 6, 0 ; 10 000 110
Jump ; 11 101 ___
Visualizing the process, we can imagine the first instruction being copied into the instruction register, the instruction pointer being incremented, then the value being copied from the instruction register to register 0.
Then the step counter resets, and we begin again, fetching the instruction, incrementing the instruction counter, and moving the content of register 0 to register 2. Reset the step counter and on and on it goes.
This is what our computer should do when it's complete.
With the planning done, it's now time to move on to building.
Building the Computer
Start by building your major components first. Build your program memory, working memory, ALU, registers, and control unit all on their own circuit board.
This will make rearranging things easier.
Use sockets to create interfaces. This will make changing and swapping out a component easier.
It helps to build everything except the control unit first, then to build the control unit interface so you know what inputs and outputs your control unit needs to have.
Test as you go, and be prepared to do some troubleshooting. Nothing ever works perfectly the first time.