Silicon From Scratch

    The Complete 32-bit ALU

    We've built and perfected a single ALU slice. Now we line up thirty-two of them, chain each slice's carry into the next, and route the most significant slice's set signal back down to the bottom — and just like that, our one-bit block becomes a complete, fully working 32-bit ALU.

    Think you got this already? Skip to Check Yourself
    The complete 32-bit ALU drawn as a single block: two 32-bit inputs a and b enter the top, a shared control signal selects the operation, and the block produces a 32-bit Result along with status outputs such as carry-out, overflow, and zero.

    Unfinished Business

    In the last lesson, we briefly discussed how we would edit our ALU slices to accommodate the slt instruction. However, we didn't quite get to how the set signal from the most significant slice would interact with the rest of the slices to properly produce the final slt result. As we saw from the last lesson, the set signal by itself is not enough to produce an output of 000…01 if slt evaluates to true, or 000…00 if slt evaluates to false. Instead, by routing the set signal back to the least significant bit's less input and choosing output 3 of the mux (operation = 11), we can effectively produce a 1 in the least significant bit of our result.

    But what do we do with the other less inputs? Well, the key insight is noticing that no matter if slt evaluates to true and we get a result equal to 000…01, or if slt evaluates to false and we get a result equal to 000…00, all of bits [1:31] are 0! The solution to our problem is therefore to simply hardwire, or to force, the less input on all of bits [1:31] as 0!

    The image at right shows precisely this. The sequence of events during the execution of an slt instruction is as follows:

    1. The ALU's control bits are set so that Binvert = 1 and operation = 11, configuring every slice to subtract and to select its less input.
    2. The expression ab is computed across the chain.
    3. The sign bit of that answer — produced in the most significant slice — encodes whether slt evaluated to true, so it is routed back down to the first slice's less input.
    4. Each slice then passes its less signal through the mux to its Result bit.
    5. A Result of 000…01 means slt was true, and a Result of 000…00 means it was false.
    Thirty-two ALU slices chained together: each slice's carry-out feeds the next slice's carry-in, the most-significant slice's 'set' output routes down to the least-significant slice's 'less' input, and every other slice's 'less' input is hardwired to 0.

    Final Touches

    The 32-slice ALU chain with equality-detection added: every slice's Result bit feeds a single 32-input NOR gate on the right, which produces a new output signal 'zero' that is 1 only when all Result bits are 0.

    As of now, our ALU is fully functional — you could drop it into a processor as-is! However, that processor would be fairly slow and weak, limited to just the AND, OR, NAND, NOR, add, subtract, and slt operations. In this course, we will add one more capability that proves incredibly useful during branch instructions. We can already test for less-than (and therefore greater-than), but we can't yet test for equal to!

    Just like with our other operations, we can implement this with a simple hardware trick that keeps our design relatively unchanged. Recall that during the design of the slt operation, we used the fact that to compare a to b you can perform the subtraction ab. If ab < 0, that means a is less than b. To check if a is equal to b, the same operation is performed, but this time we need to check whether our result is equal to 0. To do this, we can make use of one of our old friends — a gate that outputs a 1 if and only if all of its inputs are 0. You guessed it: the NOR gate!

    By feeding every slice's Result bit into a single 32-input NOR gate, we introduce one new output signal, zero, that goes high exactly when every Result bit is 0 — that is, when ab = 0, meaning a and b are equal. Not only will we then be able to test for equality, but we will also be able to test for inequality (ab), which is the case whenever zero = 0.

    Play Time

    Complete 32-bit ALU Datapath

    You may have noticed that between the last two sections, we quietly got rid of our Cin and Binvert inputs, and in their place put a single Bnegate input. This is a way to clean up our hardware, given that both signals are asserted (1) during subtraction and 0 otherwise.

    Another useful tidbit is that you will often see the signals Ainvert, Bnegate, and operation combined into one control signal, Control, which is 4 bits wide and is formed by concatenating all of the control signals together. Use the datapath to the left, and the control panel below, to explore how each operation maps to its own 4-bit Control value — pick a preset or flip the individual control bits and watch the active path light up.

    Check Yourself

    Last lesson, we saw that slt needs extra logic to stay correct when a − b overflows. The equality test (a = b) also works by subtracting and inspecting the result. So, when performing the equality test, do we need to take overflow into account the way we did for slt? If so, why?

    The equality test drawn as hardware: a 32-bit ALU takes inputs a and b with its control set to subtract, and every bit of the resulting a minus b feeds a single 32-input NOR gate whose output, zero, is 1 when a equals b.