74181 ALU Notes
Pitfalls
A=B Bit
The A=B bit does not detect that the A and B inputs are the same. Instead, it is active when all result bits are one. This can be used with the A minus 1 operation to detect A==0, or with A-B-1 to detect A=B, but it is not useful for other operations. A bit that detects an all-zero result would seem to be more useful.
NOTE: The A=B pin is wired as low or tri-state rather than low or high, so it will never display anything if an LED is wired from A=B to ground. Instead, the state can be observed by wiring an LED and resistor from Vcc to A=B pin. See https://electronics.stackexchange.com/a/454342 for details.
Conflicting datasheets
Several datasheets for the 74181 have errors or inconsistencies:
- The Texas Instruments 1988 datasheet appears to be correct
- The Fairchild 2000 datasheet has differences compared to the TI sheet
- the A and not B operation is incorrectly listed as A and B
- the not (A xor B) operation is listed as not A xor not B (which would be the same as just A xor B)
- The Texas Instruments 1983 Databook shows the A plus A operation as A
Carry flag
The carry flag output (Cn+4) is not a simple output that indicates overflow for all arithmetic operations. Instead, it outputs LOW for addition overflow and HIGH for subtraction overflow. While this seems confusing at first glance, it makes sense when seen in the context of chaining multiple ALUs together to do operations on larger word lengths.
For the purpose of this discussion, some terminology is defined here that is not in the 74181 datasheet:
- CIN, or carry in, refers to the Cn pin of the ALU
- COUT, or carry out, refers to the Cn+4 pin of the ALU
- The “normal case” refers to an operation that does not cause a carry or borrow condition
- The “upper” and “lower” ALU refer to a case where two ALUs are wired together to do operations on 8 bits, where the lower ALU holds the least significant 4 bits and the upper ALU holds the most significant 4 bits
The CIN pin is active low. When it is low, any arithmetic operation adds an additional 1 to the final result.
The table below shows five useful arithmetic operations that can be performed by the 74181 ALU. By showing the CIN=1 and CIN=0 operations side by side, it is easier to see how operations are related so that two (or more) ALUs can be used together to work with more than 4 bits.
Selects | CIN=H Operation | CIN=L Operation |
---|---|---|
LLLL | A | A + 1 |
LHHL | A - B - 1 | A - B |
HLLH | A + B | A + B + 1 |
HHLL | A + A | A + A + 1 |
HHHH | A - 1 | A |
When using more than one ALU, the Mode and Select bits are connected to the same sets of pins on all ALUs. the COUT (Cn+4) of the lower ALU is connected to the CIN (Cn) of the upper ALU. The CIN of the lower ALU is used, along with the Mode and Select bits, to select an operation to be performed. The COUT of the upper ALU can be used, with some interpretation, to indicate an overflow of the entire operation.
The examples below use two ALUs, but the principles are the same using any arbitrary number of 74181s to achieve the desired bit width. There may be delay issues when using multiple ALUs, but those are beyond the scope of this discussion. See the 74S182 Carry Lookahead chip datasheets for details.
For the A+B addition operation, the CIN of the lower ALU is not asserted. Note that this means it is in a HIGH state, because the CIN pin is active low. The COUT from the lower ALU is also not asserted in the normal case where the result of the addition does not cause an overflow out of the lower 4 bits. The COUT of the lower ALU is connected to the CIN of the upper ALU, so both ALUs will do an A+B operation on their respective 4 bits of data.
In the case where the lower ALU addition overflows, the COUT connected to the upper ALU’s CIN is asserted, so the lower ALU will do an A+B operation on its 4 bits, and the upper ALU will do an A+B+1 operation on its 4 bits. This gives the desired result of the carry from the overflow of the lower ALU cascading into the upper ALU.
The addition cases described above for A+B are identical for the A+A operation as well.
For subtraction, the no-carry operation is A-B-1, but asserting the CIN bit gives an A-B operation. This is why CIN must be asserted on the lower ALU for subtraction but not for addition. Similar to addition, the lower ALU asserts the same value on COUT as it receives on CIN for the normal case, so the lower ALU and upper ALU will both perform an A-B operation on their respective 4 bits.
In the case where the subtraction in the lower ALU needs a borrow from the upper ALU, the lower ALU will not assert the COUT signal, causing the upper ALU to perform an A-B-1 operation. This effectively borrows a one from the upper ALU value.
From the above operations, it would seem like a carry/borrow bit to indicate 8-bit overflow/underflow could be implemented by checking to see if the CIN to the lower ALU has a different value than the COUT of the upper ALU. This could be accomplished by just an XOR of the two signals and would work for both the addition and subtraction case. Unfortunately, the increment and decrement (A+1 and A-1) operations break this model.
For both addition and subtraction, the upper and lower ALUs perform the same operation in the normal case and perform different operations in the lower ALU overflow case. The increment and decrement functions behave differently.
Consider the case to increment the number 5, or 0000 0101 in binary. The lower ALU will perform an A+1 operation, but the upper ALU must perform an A operation to leave the upper 4 bits unchanged. The result would be 6, or 0000 0110. In this normal case, the lower ALU will have CIN asserted and the upper ALU will not. For the overflow case, such as an increment of 0000 1111, both ALUs will have CIN asserted and will both do an A+1 operation, giving 0001 0000 as the result. The decrement operation is similar, with the ALUs doing different operations in the normal case and the same operation in the lower ALU overflow case.
The following tables summarize the usage of the carry bits for the 5 arithmetic operations.
The columns in the table represent these pins and conditions:
- Selects - function select bits S3 to S0
- Upper ALU - function performed by lower ALU
- Lower ALU - function performed by upper ALU
- CINU - CIN (Cn) to upper ALU produced by COUT (Cn+4) of lower ALU
- CINL - CIN (Cn) to lower ALU
- COUTUN - COUT (Cn+4) from upper ALU in “normal” (non-overflow) case
- COUTUC - COUT (Cn+4) from upper ALU in overflow case
This table shows the five operations in the normal case, when the lower ALU does not have an overflow condition.
Selects | Lower ALU | Upper ALU | CINL | CINU | COUTUN | COUTUC |
---|---|---|---|---|---|---|
LLLL | A + 1 | A | L | H | H | L |
LHHL | A - B | A - B | L | L | L | H |
HLLH | A + B | A + B | H | H | H | L |
HHLL | A + A | A + A | H | H | H | L |
HHHH | A - 1 | A | H | L | L | H |
The next table shows the same five operations in the case when the lower ALU has an overflow condition. The only differences with the previous table are the upper ALU operations that are produced by the different values produced by the COUT of the lower ALU pin that is connected to the CIN of the upper ALU.
Selects | Lower ALU | Upper ALU | CINL | CINU | COUTUN | COUTUC |
---|---|---|---|---|---|---|
LLLL | A + 1 | A + 1 | L | L | H | L |
LHHL | A - B | A - B - 1 | L | H | L | H |
HLLH | A + B | A + B + 1 | H | L | H | L |
HHLL | A + A | A + A + 1 | H | L | H | L |
HHHH | A - 1 | A - 1 | H | H | L | H |
Carry Flag Usage in 8-bit Microprocessors
To understand how the 74LS181 might be used, it is helpful to compare the use of the carry flag with arithmetic operations of some real microprocessors.
The Z-80 and 8080/8085 have a Carry Flag for arithmetic operations. This same flag is sometimes referred to as the Borrow Flag for subtraction, but it is still just one physical flag.
For addition with carry, the operation is A+B+C. A cleared carry flag produces A+B and a set carry flag produces A+B+1. The carry bit is set if the result overflows into the ninth bit. For subtraction, the operation is A-B-C. A cleared carry flag produces A-B and a set carry flag produces A-B-1. The carry flag is set if the result of the subtraction borrows from the ninth bit.
The 6502 processor also has a single Carry Flag that is used for addition and subtraction operations, but it functions differently than the Z-80/8080/8085.
Like the Z-80, the addition with carry the operation is A+B+C. A cleared carry flag produces A+B and a set carry flag produces A+B+1. The carry flag is set if the result overflows into the ninth bit.
Subtraction on the 6502 is a bit different. The operation is A-B-(1-C), which can also be written as A-B-1+C. A cleared carry flag produces A-B-1 and a set carry flag produces A-B. The carry flag is cleared if the result of the subtraction borrows from the ninth bit.
In both processors, the carry can be used to do multiple byte addition or subtraction because the carry result produced by an operation is the result needed to do the operation on the next byte of data.
The Z-80 model is easier to understand - a set carry flag always indicates a carry or borrow from the operation. The 6502 model is actually a better match for the 74LS181 ALU because it uses different values of the carry bit depending on whether addition or subtraction is performed. The only complication is that interpretation of the carry bit is inverted between the 6502 and the 74181.
ALU Operations List
The following is a list of all possible operations of the ALU using a simplified syntax. All operations are spelled out explicitly, like ‘or’ and ‘plus’ instead of ‘+’ and ‘plus’ as in the datasheets.
Arithmetic
M Cn S3 S2 S1 S0
0 0 0 0 0 0 A plus 1
0 0 0 0 0 1 (A or B) plus 1
0 0 0 0 1 0 (A or not B) plus 1
0 0 0 0 1 1 zero [all zeroes]
0 0 0 1 0 0 A plus (A and not B) plus 1
0 0 0 1 0 1 (A or B) plus (A and not B) plus 1
0 0 0 1 1 0 A minus B
0 0 0 1 1 1 A and not B
0 0 1 0 0 0 A plus (A and B) plus 1
0 0 1 0 0 1 A plus B plus 1
0 0 1 0 1 0 (A or not B) plus (A and B) plus 1
0 0 1 0 1 1 A and B
0 0 1 1 0 0 A plus A plus 1
0 0 1 1 0 1 (A or B) plus A plus 1
0 0 1 1 1 0 (A or not B) plus A plus 1
0 0 1 1 1 1 A
0 1 0 0 0 0 A
0 1 0 0 0 1 A or B
0 1 0 0 1 0 A or not B
0 1 0 0 1 1 negative 1 [all ones]
0 1 0 1 0 0 A plus (A and not B)
0 1 0 1 0 1 (A or B) plus (A and not B)
0 1 0 1 1 0 A minus B minus 1
0 1 0 1 1 1 (A and not B) minus 1
0 1 1 0 0 0 A plus (A and B)
0 1 1 0 0 1 A plus B
0 1 1 0 1 0 (A or not B) plus (A and B)
0 1 1 0 1 1 (A and B) minus 1
0 1 1 1 0 0 A plus A
0 1 1 1 0 1 (A or B) plus A
0 1 1 1 1 0 (A or not B) plus A
0 1 1 1 1 1 A minus 1
Logic
M Cn S3 S2 S1 S0
1 x 0 0 0 0 not A
1 x 0 0 0 1 not A or not B
1 x 0 0 1 0 not A and B
1 x 0 0 1 1 0
1 x 0 1 0 0 not (A and B)
1 x 0 1 0 1 not B
1 x 0 1 1 0 A xor B
1 x 0 1 1 1 A and not B
1 x 1 0 0 0 not A or B
1 x 1 0 0 1 not (A xor B)
1 x 1 0 1 0 B
1 x 1 0 1 1 A and B
1 x 1 1 0 0 1
1 x 1 1 0 1 A or not B
1 x 1 1 1 0 A or B
1 x 1 1 1 1 A