In computing, an arithmetic logic unit (ALU) is a combinational digital circuit that performs arithmetic and bitwise operations on integer binary numbers. This is in contrast to a floating-point unit (FPU), which operates on floating point numbers. It is a fundamental building block of many types of computing circuits, including the central processing unit (CPU) of computers, FPUs, and graphics processing units (GPUs).
The inputs to an ALU are the data to be operated on, called operands, and a code indicating the operation to be performed (opcode); the ALU's output is the result of the performed operation. In many designs, the ALU also has status inputs or outputs, or both, which convey information about a previous operation or the current operation, respectively, between the ALU and external status registers.
Signals An ALU has a variety of input and output nets, which are the electrical conductors used to convey digital signals between the ALU and external circuitry. When an ALU is operating, external circuits apply signals to the ALU inputs and, in response, the ALU produces and conveys signals to external circuitry via its outputs.
Data A basic ALU has three parallel data buses consisting of two input operands (A and B) and a result output (Y). Each data bus is a group of signals that conveys one binary integer number. Typically, the A, B and Y bus widths (the number of signals comprising each bus) are identical and match the native word size of the external circuitry (e.g., the encapsulating CPU or other processor).
Opcode The opcode input is a parallel bus that conveys to the ALU an operation selection code, which is an enumerated value that specifies the desired arithmetic or logic operation to be performed by the ALU. The opcode size (its bus width) determines the maximum number of distinct operations the ALU can perform; for example, a four-bit opcode can specify up to sixteen different ALU operations. Generally, an ALU opcode is not the same as a machine language instruction, though in some cases it may be directly encoded as a bit field within such instructions.
Status Outputs The status outputs are various individual signals that convey supplemental information about the result of the current ALU operation. General-purpose ALUs commonly have status signals such as: Carry-out, which conveys the carry resulting from an addition operation, the borrow resulting from a subtraction operation, or the overflow bit resulting from a binary shift operation. Zero, which indicates all bits of Y are logic zero. Negative, which indicates the result of an arithmetic operation is negative. Overflow, which indicates the result of an arithmetic operation has exceeded the numeric range of Y. Parity, which indicates whether an even or odd number of bits in Y are logic one.
Inputs The status inputs allow additional information to be made available to the ALU when performing an operation. Typically, this is a single "carry-in" bit that is the stored carry-out from a previous ALU operation.
Circuit operation
An ALU is a combinational logic circuit, meaning that its outputs will change asynchronously in response to input changes. In normal operation, stable signals are applied to all of the ALU inputs and, when enough time (known as the "propagation delay") has passed for the signals to propagate through the ALU circuitry, the result of the ALU operation appears at the ALU outputs. The external circuitry connected to the ALU is responsible for ensuring the stability of ALU input signals throughout the operation, and for allowing sufficient time for the signals to propagate through the ALU circuitry before sampling the ALU outputs.
In general, external circuitry controls an ALU by applying signals to the ALU inputs. Typically, the external circuitry employs sequential logic to generate the signals that control ALU operation. The external sequential logic is paced by a clock signal of sufficiently low frequency to ensure enough time for the ALU outputs to settle under worst-case conditions (i.e., conditions resulting in the maximum possible propagation delay).
For example, a CPU starts an addition operation by routing the operands from their sources (typically processor registers) to the ALU's operand inputs, while simultaneously applying a value to the ALU's opcode input that configures it to perform an addition operation. At the same time, the CPU enables the destination register to store the ALU output (the resulting sum from the addition operation) upon operation completion. The ALU's input signals, which are held stable until the next clock, are allowed to propagate through the ALU and to the destination register while the CPU waits for the next clock. When the next clock arrives, the destination register stores the ALU result and, since the ALU operation has completed, the ALU inputs may be set up for the next ALU operation.
Functions A number of basic arithmetic and bitwise logic functions are commonly supported by ALUs. Basic, general purpose ALUs typically include these operations in their repertoires:
Arithmetic operations Add: A and B are summed and the sum appears at Y and carry-out. Add with carry: A, B and carry-in are summed and the sum appears at Y and carry-out. Subtract: B is subtracted from A (or vice versa) and the difference appears at Y and carry-out. For this function, carry-out is effectively a "borrow" indicator. This operation may also be used to compare the magnitudes of A and B; in such cases the Y output may be ignored by the processor, which is only interested in the status bits (particularly zero, negative, and carry) that result from the operation. Subtract with borrow: B is subtracted from A (or vice versa) with borrow (carry-in) and the difference appears at Y and carry-out (borrow out). Two's complement: The negative of A (or B) appears at Y in two's complement form. Increment: A (or B) is increased by one and the resulting value appears at Y. Decrement: A (or B) is decreased by one and the resulting value appears at Y.
Bitwise logical operations AND: the bitwise AND of A and B appears at Y. AND may also be used to TEST bits. In this case, the result would not be stored; only the status bits (particularly zero and negative) would be recorded. OR: the bitwise OR of A and B appears at Y. Exclusive-OR: the bitwise XOR of A and B appears at Y. Ones' complement: all bits of A (or B) are inverted and appear at Y.
Bit shift operations + Bit shift examples for an eight-bit ALU Type Left Right Arithmetic shift Logical shift Rotate Rotate through carry
ALU shift operations cause operand A (or B) to shift left or right (depending on the opcode) and the shifted operand appears at Y. Simple ALUs typically can shift the operand by only one bit position, whereas more complex ALUs employ barrel shifters that allow them to shift the operand by an arbitrary number of bits in one operation. In all single-bit shift operations, the bit shifted out of the operand appears on carry-out; the value of the bit shifted into the operand depends on the type of shift. Arithmetic shift: the operand is treated as a two's complement integer, meaning that the most significant bit is a "sign" bit and is preserved. Logical shift: a logic zero is shifted into the operand. This is used to shift unsigned integers. Rotate: the operand is treated as a circular buffer of bits in which its least and most significant bits are effectively adjacent. Rotate through carry: the carry bit and operand are collectively treated as a circular buffer of bits.
Other operations Pass through: all bits of A (or B) appear unmodified at Y. This operation is typically used to determine the parity of the operand or whether it is zero or negative, or to copy the operand to a processor register.
Applications
Status usage
Upon completion of each ALU operation, the ALU's status output signals are usually stored in external registers to make them available for future ALU operations (e.g., to implement multiple-precision arithmetic) and for controlling conditional branching. The bit registers that store the status output signals are often collectively treated as a single, multi-bit register, which is referred to as the "status register" or "condition code register".
Depending on the ALU operation being performed, some status register bits may be changed and others may be left unmodified. For example, in bitwise logical operations such as AND and OR, the carry status bit is typically not modified as it is not relevant to such operations.
In CPUs, the stored carry-out signal is usually connected to the ALU's carry-in net. This facilitates efficient propagation of carries (which may represent addition carries, subtraction borrows, or shift overflows) when performing multiple-precision operations, as it eliminates the need for software-management of carry propagation (via conditional branching, based on the carry status bit).
Operand and result data paths
The sources of ALU operands and destinations of ALU results depend on the architecture of the encapsulating processor and the operation being performed. Processor architectures vary widely, but in general-purpose CPUs, the ALU typically operates in conjunction with a register file (array of processor registers) or accumulator register, which the ALU frequently uses as both a source of operands and a destination for results. To accommodate other operand sources, multiplexers are commonly used to select either the register file or alternative ALU operand sources as required by each machine instruction.
For example, the architecture shown to the right employs a register file with two read ports, which allows the values stored in any two registers (or the same register) to be ALU operands. Alternatively, it allows either ALU operand to be sourced from an immediate operand (a constant value which is directly encoded in the machine instruction) or from memory. The ALU result may be written to any register in the register file (via the register file's write port) or to memory.
Multiple-precision arithmetic In integer arithmetic computations, multiple-precision arithmetic is an algorithm that operates on integers which are larger than the ALU word size. To do this, the algorithm treats each integer as an ordered collection of ALU-size fragments, arranged from most-significant (MS) to least-significant (LS) or vice versa. For example, in the case of an 8-bit ALU, the 24-bit integer 0x123456 would be treated as a collection of three 8-bit fragments: 0x12 (MS), 0x34, and 0x56 (LS). Since the size of a fragment exactly matches the ALU word size, the ALU can directly operate on this "piece" of operand.
The algorithm uses the ALU to directly operate on particular operand fragments and thus generate a corresponding fragment (a "partial") of the multi-precision result. Each partial, when generated, is written to an associated region of storage that has been designated for the multiple-precision result. This process is repeated for all operand fragments so as to generate a complete collection of partials, which is the result of the multiple-precision operation.