Rondo
Back to List
nand2tetris

My Nand2Tetris Journey #2 - Building Basic Chips And ALU

Rondo

2026-08-26

What I Built

  • HalfAdder, FullAdder, Add16, Inc16, And ALU.

How I Solved

Like when I built logic gates, I started with analyzing truth table of HalfAdder, FullAdder.

HalfAdder was really easy. After looking at the truth table, I could map the sum and carry outputs to logic gates pretty quickly.

FullAdder was also not hard since it's really similar to HalfAdder except that it can add 3 bits. I realized that I could build it by combining some chips and logic gates I had already made instead of designing everything again from scratch.

Once I finished building them, I was also able to build Add16. At first, I had no idea how to sum all the 16 bits. But I soon realized that I could build a 16-bit adder by combining the smaller adders I had already built and passing carry information to the next bit. It looks not beautiful, but still works.

And about Inc16, it's basically add exactly 1(0000000000000001). So I could easily build it using Add16. (But I did something weird at first.. check the Reflection below)

ALU was the core part of project 2. Once I realized that Mux can be used as if, I could make proper outputs using logic gates. ALU is also a combination of logic gates and chips, after all.

What I Learned

  • How to build basic chips using logic gates and already-built chips
  • Why I should reuse the chips for another chip(check the Reflection section below)
  • Mux can be used like if
  • How to use bit slicing and fan-out in HDL and why it's important

Reflection

Before I started this part, I didn't know two things: I could use bit slicing and true, false for each bit. So when I first tried to build Inc16, it looked really weird, since I calculated all the bits one by one.

It's not logically wrong. But not beautiful either. I was not sure if it was right or not. Then I realized that I already built Add16. But I had no idea how I could use it to add exactly 1(0000000000000001).

After googling, I realized that I could use bit slicing like Python's list slicing and construct the input I needed without manually connecting every bit. With that, the ugly Inc16 I made at first became much simpler. Yes. Don't forget the chips you got and bit slicing.

About ALU, I used to consider it as an alien, since its truth table looked really creepy and disordered. But I didn't have to be afraid of ALU in advance. I could calculate the output step by step. For example, instead of trying to understand every possible output at once, I handled the control bits for input x one by one using Mux and logic gates. I did the same thing to input y. So I could deal with zx, nx, zy, ny step by step.

f and no were the same. I calculated the possible outputs first and used Mux to choose which output should be used depending on each control bit. After that, I faced the hardest part that tortured me a lot. When I finished making the final 16-bit output, I also needed to output zr and ng, which were just 1 bit each. But the ALU output was 16-bit. I had no idea how I could derive those single-bit flags from the final output. I tried to use Or8Way for the output, but it's not allowed to use bit slicing for internal pins. So I was just sitting and thinking about this for a while but couldn't find the solution. I googled about it and realized that I could use fan-out. Fan-out allowed one output signal to feed multiple destinations only when it's actually going out, which also let me access the parts of the output I needed. With that, I could finally derive both ng and zr from the final ALU output without directly slicing an internal pin.

And it's done. ALU is now working! I think I should've known bit slicing and fan-out in advance, but it's not a big deal at all.

Keep moving on!