# Do ALUs perform all/most N operations before running through the multiplexer?

I'm doing some self-study on hardware and currently implementing an ALU. The way I'm designing it is such that I have an N:1 MUX (N inputs yield a single output (16 bit number) based on selector bits). I feed in 2 16-bit numbers with a series of control bits to get my output.

My question is that I have a bunch of gates that execute before they hit the MUX and then the MUX says "based on these control bits I'll output this calculation". Just wondering if it is inefficient to execute all these operations even if they aren't used/outputted.

For example, if I simply want to negate A, the circuit will still perform other arithmetic operations despite not using them at all in the final result. It seems like it would increase the time to get the desired result since you're running through more gates.

• What's the alternative proposal? May 17 '20 at 15:25
• I don't have one, just curious if that's how it works in practice from a high-level.
– Ryan
May 17 '20 at 15:25
• @Ryan Are you asking if this is "wasting" (inefficient with) resources? If so, there are other ways to implement this kind of design. In fact, higher end processors do things differently. Are you asking what those other techniques might be? Or am I misunderstanding you?
– jonk
May 17 '20 at 16:43
• A common design of an ALU is simply creating each block of instructions and feeding it to the MUX and having the user select which instructions they wish to call. Will multiple of these blocks be activated? Yes, they may but with the MUX you can select which instruction to execute. The operands you feed into the ALU could very well be applied to each instruction but to avoid multiple outputs of each of these instructions, that's where the MUX comes in.
– user103380
May 17 '20 at 16:49
• @KingDuken I provided a diagram in my comment. Have a look and see if this is what you are considering. The longest path through will determine the cycle time. But I think the OP is asking if there are other approaches... and there are. The PPro and P II and beyond use registration stations and break them into separate functional units to operate in parallel, when possible. So there is more than one approach. I suspect the OP wants to see those other approaches.
– jonk
May 17 '20 at 16:50

Using any modern synthesis tool you can be reasonably sure it'll optimise away any redundancy it possibly can, to the point of sometimes eliminating the entire design if it wasn't tested properly in simulation first.

So, yes this is inefficient; but synth will fix that.

Better to keep what you write simple, clean and clear. 16 ops and a 16:1 MUX fills that bill.

In case all arithmetic operations are performed in the same number of clock cycles, some operations (e.g multiplication) will limit the maximum clock frequency achievable.

I can tell two similar solutions. I will assume multiplication is the bottleneck, as an example.

1. Pipelining bottleneck operations

Say all other operations are performed in one clock cycle, still we can split multiplication into several clock cycles, 2 cycles for example. The CPU needs to stall for one cycle when multiplication is performed. This brings some extra control logic, but roughly doubles the maximum clock frequency.

There are two challenges for this solution. First, pipelining is not easy for some arithmetic operations, however this can be done by the synthesis tool using some retiming (register balancing) commands. Second, the area will increase by about 16 flip-flops.

2. Defining multi-cycle paths

This is a better solution I think. Again extra control logic is required to stall the CPU, but we don't need to pipeline and put additional flip-flops. We should just tell the synthesis tool that multiplication logic is a multi-cycle path. For example, the set_multicycle_path command can be used in Synopsys Design Compiler.

You may be interested in the old TI 74181 4bits ALU which was used in many mincomputers in the 70's:

https://en.wikipedia.org/wiki/74181

A clever arrangement of gates to generate many different operations.

• Additions and subtractions can be combined by conditionally inverting an input and using the carry-in (for two's complement)
• Logical operations can be merged with some arithmetical by removing carry propagation.
• Not / Neg likewise is using the subtraction inverter and a carry-in. Or Inc/Dec using the adder.
• Shift left as an addition... etc.

Depending on the amount of optimisation you want to achieve, you may let a logic synthesis tool do all the optimisations from an high level description, or manually tune it. Sometimes with RISCs some bits in CPU opcodes can be used to control multiplexers or drive constants in the ALU without further decoding.