Arithmetic Circuits 01011 +00101 10000 Didn’t I learn how to do addition in the second grade? UNC courses aren’t what they used to be... 01011 +00101 10000 Finally; time to build some serious functional blocks We’ll need a lot of boxes
… … … Review: 2’s Complement N bits -2N-1 2N-2 … … … 23 22 21 20 Range: – 2N-1 to 2N-1 – 1 “sign bit” “binary” point 8-bit 2’s complement example: 11010110 = –27 + 26 + 24 + 22 + 21 = – 128 + 64 + 16 + 4 + 2 = – 42 If we use a two’s-complement representation for signed integers, the same binary addition procedure will work for adding both signed and unsigned numbers. By moving the implicit “binary” point, we can represent fractions too: 1101.0110 = –23 + 22 + 20 + 2-2 + 2-3 = – 8 + 4 + 1 + 0.25 + 0.125 = – 2.625
Carries from previous column Binary Addition Here’s an example of binary addition as one might do it by “hand”: 1 Carries from previous column A: 1101 B:+ 0101 10010 Adding two N-bit numbers produces an (N+1)-bit result Let’s start by building a block that adds one column: called a “full adder” (FA) A B CO CI S FA Then we can cascade them to add two numbers of any size… A B CO CI S FA A3 B3 A2 B2 A1 B1 A0 B0 S4 S3 S0 S1 S0
Designing a “Full Adder”: From Last Lecture Start with a truth table: Write down eqns for the “1” outputs Co = CiAB + CiAB + CiAB + CiAB S = CiAB + CiAB + CiAB + CiAB Simplifying a bit (seems hard, but experienced designers are good at this art!) Co = Ci(A + B) + AB S = Ci A B Co = Ci(A B) + AB S = Ci (A B)
For Those Who Prefer Logic Diagrams … A little tricky, but only 5 gates/bit Co = Ci(A B) + AB S = Ci (A B) CI A B S CO “Carry” Logic “Sum” Logic
Subtraction: A-B = A + (-B) Using 2’s complement representation: –B = ~B + 1 ~ = bit-wise complement B 1 But what about the “+1”? So let’s build an arithmetic unit that does both addition and subtraction. Operation selected by control input: A B CO CI S FA A3 A2 A1 A0 S4 S3 S0 S1 S0 B3 B2 B1 B0 Subtract
Condition Codes Besides the sum, one often wants four other bits of information from an arithmetic unit: To compare A and B, perform A–B and use condition codes: Signed comparison: LT NV LE Z+(NV) EQ Z NE ~Z GE ~(NV) GT ~(Z+(NV)) Unsigned comparison: LTU C LEU C+Z GEU ~C GTU ~(C+Z) Z (zero): result is = 0 big NOR gate N (negative): result is < 0 SN-1 C (carry): indicates that add in the most significant position produced a carry, e.g., “1 + (-1)” from last FA V (overflow): indicates that the answer has too many bits to be represented correctly by the result width, e.g., “(2i-1 - 1)+ (2i-1- 1)” -or-
TPD of Ripple-Carry Adder What is TPD?? See Lec. 8-9. An-1 Bn-1 An-2 Bn-2 A2 B2 A1 B1 A0 B0 A B CO CI S FA A B CO CI S FA A B CO CI S FA A B CO CI S FA A B CO CI S FA C … Sn-1 Sn-2 S2 S1 S0 Worse-case path: carry propagation from LSB to MSB, e.g., when adding 11…111 to 00…001. tPD = (tPD,XOR +tPD,AND + tPD,OR) +(N-2)*(tPD,OR + tPD,AND) + tPD,XOR (N) CI A B S CO A,B to CO CI to CO CIN-1 to SN-1 (N) is read “order N” and tells us that the latency of our adder grows in proportion to the number of bits in the operands.
Can we add faster? Yes, there are many sophisticated designs that are faster… Carry-Lookahead Adders (CLA) Carry-Skip Adders Carry-Select Adders
Adder Summary Adding is not only common, but it is also tends to be one of the most time-critical of operations. As a result, a wide range of adder architectures have been developed that allow a designer to tradeoff complexity (in terms of the number of gates) for performance. Smaller / Slower Bigger / Faster Ripple Carry Carry Skip Carry Select Carry Lookahead Add A B S Add/Sub A B S At this point we’ll define a high-level functional unit for an adder, and specify the details of the implementation as necessary. sub
Shifting Logic 1 R7 R6 R5 R4 R3 R2 R1 R0 X7 X6 X5 X4 X3 X2 X1 X0 “0” SHL1 Shifting is a common operation that is applied to groups of bits. Shifting can be used for alignment, as well as for arithmetic operations. X << 1 is often the same as 2*X X >> 1 can be the same as X/2 For example: X = 2010 = 000101002 Left Shift: (X << 1) = 001010002 = 4010 Right Shift: (X >> 1) = 000010102 = 1010 Signed or “Arithmetic” Right Shift: (-X >>> 1) = (111011002 >>> 1) = 111101102 = -1010
Boolean Operations It will also be useful to perform logical operations on groups of bits. Which ones? ANDing is useful for “masking” off groups of bits. ex. 10101110 & 00001111 = 00001110 (mask selects last 4 bits) ANDing is also useful for “clearing” groups of bits. ex. 10101110 & 00001111 = 00001110 (0’s clear first 4 bits) ORing is useful for “setting” groups of bits. ex. 10101110 | 00001111 = 10101111 (1’s set last 4 bits) XORing is useful for “complementing” groups of bits. ex. 10101110 ^ 00001111 = 10100001 (1’s complement last 4 bits) NORing is useful for.. uhm… ex. 10101110 # 00001111 = 01010000 (0’s complement, 1’s clear)
Boolean Unit It is simple to build up a Boolean unit using primitive gates and a mux to select the function. Since there is no interconnection between bits, this unit can be simply replicated at each position. The cost is about 7 gates per bit. One for each primitive function, and approx 3 for the 4-input mux. This is a straightforward, but not too elegant of a design. Ai Bi Qi Bool 00 01 10 11 This logic block is repeated for each bit (i.e. 32 times)
An ALU, at Last Now we’re ready for a big one! An Arithmetic Logic Unit. A B R Bidirectional Shifter Boolean Add/Sub Sub Bool Shft Math 1 0 … That’s a lot of stuff Flags V,C N Flag Z Flag