Last time, we talked about an ALU design that would have 4 operations: add, and, xor, and right shift. It also needed the ability to negate or zero its inputs, and negate its outputs. So, let's put together something that looks like that in Logisim.
I started off by building the input stages. Each input can be zeroed or negated (in that order), so lets build a simple circuit that does that, and then we can just use it twice.
Similarly, we're going to put together a simple circuit for the ALU's output stage. It's just going to run the input through a buffer and an inverting buffer, with separate inputs for both. The reason I'm including a separate enables for the inverted and non-inverted output is so I can turn them both off in case something else needs whatever bus the ALU outputs to.
The input and output stages are pretty simple, but they're going to give us a lot of flexibility.
Now, we just need to run the left and right operands through the operations we want to support: add, and, xor, and right shift. I built a very small right shift circuit, because the built in Logisim shifter didn't support carry in/out, but I want to have them so I can support rotate instructions.
Here's what it looks with the inputs wired up to the different operands.
From here, let's wire up them up to the output, and we'll use a decoder and buffers to control which operand actually makes it through to the output.
The last task we have is to in the operation stage is wire up the extra inputs and outputs. By taking a carry in and sending a carry out, we can do multi-word operations. I'm going to put a multiplexer on the carry in input so I can force it to be 0 or 1 if I want. We're also going to send out signals indicating whether the result is zero or negative, so we can jump around later based on whether the result of our last operation was positive, zero, or negative.
Alright, that's pretty much everything for the operation stage.
For the sake of completeness, I'm going to show the different stages of the ALU put together.
If we trace the path that the signal takes from output backwards to input, it goes through one buffer in the output stage, one buffer and operation in the operation stage, and two buffers in the input stage. If I use 74hc540 and 74hc541 buffers, each of the 4 buffers has a ~20 ns propagation delay. Assuming that addition is the worst of the operation in terms of propagation delay, and it's implemented with a pair of 74hc283s, which have a ~40 ns delay, then we can do some napkin math, and calculate the propagation delay through the entire ALU, which turns out to be ~160 ns. If we assume some other shenanigans are going on in the CPU every clock cycle and round up to 250ns, we can start to get a rough idea of how fast this CPU will run once built: around 4mhz. I'm calculating these with worst case timings from the data sheet, so maybe we'll get more!
If you've gone through Elements of Computing Systems, you'll definitely recognize the design of this ALU, as I pretty much stole it wholesale from that book, then added the xor and right shift operations.
In total, I count about 22 chips necessary to complete this design: 4 buffers on each input stage (8 total), 2 ICs for the first three operations (6 more), plus one buffer for each operation (4), plus a decoder, the big Nor gate for the zero outputs, the carry muxes, and an IC with some inverters. That... That feels like a lot, and the ALU is looking to be pretty massive at this point. I can see why using just one ALU chip is so attractive to people.
Alright, that's all for today, but before we go, let's take a look at our CPU so far. Just the ALU so far, but it's a big step!