This project is from the course nand2tetris. From building logic gates to writing a high level language and an operating system in it, the outcome of this project is a modern-day 16-bit computer which I have documented below.
This section aims at building the bare-bones of the computer. We first make simple logic gates and then leverage them to further make more sophisticated hardware. The logic is written in a custom Hardware Description Language (HDL) specified here.
All the logic gates are created from the primitive Nand gate. Here are a list of gates that were implemented.
- Nand, Not, And, Or, Xor
- Mux, DMux
- Not16, And16, Or16, Mux16 - 16-bit wide gates
- Or8Way - Or(x0,...,x7)
- Mux4Way16, Mux8Way16, DMux4Way16, DMux8Way16 - 16-bit wide with 4/8 inputs
This ALU can compute eighteen functions using some minimal hardware design. It uses 6 control bits where each bit refers to a certain elementary operation.
control-bit | description |
---|---|
zx | zero the x input? |
nx | negate the x input? |
zy | zero the y input? |
ny | negate the y input? |
f | compute x+y (if 1) or x&y (if 0) |
no | negate the output? |
The following functions can be computed with the control bits as follows:
# | zx | nx | zy | ny | f | no | f(x,y) |
---|---|---|---|---|---|---|---|
1 | 1 | 0 | 1 | 0 | 1 | 0 | 0 |
2 | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
3 | 1 | 1 | 1 | 0 | 1 | 0 | -1 |
4 | 0 | 0 | 1 | 1 | 0 | 0 | x |
5 | 1 | 1 | 0 | 0 | 0 | 0 | y |
6 | 0 | 0 | 1 | 1 | 0 | 1 | !x |
7 | 1 | 1 | 0 | 0 | 0 | 1 | !y |
8 | 0 | 0 | 1 | 1 | 1 | 1 | -x |
9 | 1 | 1 | 0 | 0 | 1 | 1 | -y |
10 | 0 | 1 | 1 | 1 | 1 | 1 | x+1 |
11 | 1 | 1 | 0 | 1 | 1 | 1 | y+1 |
12 | 0 | 0 | 1 | 1 | 1 | 0 | x-1 |
13 | 1 | 1 | 0 | 0 | 1 | 0 | y-1 |
14 | 0 | 0 | 0 | 0 | 1 | 0 | x+y |
15 | 0 | 1 | 0 | 0 | 1 | 1 | x-y |
16 | 0 | 0 | 0 | 1 | 1 | 1 | y-x |
17 | 0 | 0 | 0 | 0 | 0 | 0 | x&y |
18 | 0 | 1 | 0 | 1 | 0 | 1 | x|y |
The ALU also produces two status bits with the output.
status-bit | description |
---|---|
zr | is the output zero? |
ng | is the output negative? |
The following chips were implemented in this section
Future work: It will be better to replace the naive ripple carry adder in Add16 with a more efficient one like a carry-lookahead adder.
Storage is realized using Data Flip-Flops (DFFs). Registers are 16-bit wide and are composed of DFFs. These registers are further stacked to create the random access memory (RAM). It allows reading/writing data from/to any address in constant time, irrespective of the physical location.
Finally, a program counter is also realized using a 16-bit register which has the following functions - reset to zero, load a particular value, and increment the current value.
List of chips implemented