Skip to content
code0.HDL

Width and sign

Two's complement, why one bit pattern is two numbers depending on how it is read, what widening and narrowing do to a value, and the difference between a lost carry and an overflow.

In this chapter

  • Read one bit pattern as an unsigned and as a two's-complement number
  • Predict what widening and narrowing do to a value under each reading
  • Tell a lost carry from a signed overflow
Concepts in this chapter
  • Two's complement
  • Signed and unsigned reading of one pattern
  • Extension and truncation
  • Carry and overflow
Prerequisite concepts

1. Two's complement gives the top bit a negative place value

A bus holds only 0s and 1s, so a negative number has to be a way of reading a pattern. Two's complement is that way: in an n-bit number, bit n−1 is worth −2^(n−1) instead of +2^(n−1), and every other bit keeps its usual place value. In four bits, bit 3 is worth −8. The pattern 1111 is −8 + 4 + 2 + 1 = −1; 1000 is −8; 0111 is 7. The range is −8 to 7.

WidthUnsignedTwo's complement
40 to 15−8 to 7
80 to 255−128 to 127
n0 to 2^n − 1−2^(n−1) to 2^(n−1) − 1

The experiment starts at 1111 and shows both readings; the place value above bit 3 is −8. Press bits and confirm that the two's complement readout is the sum under the 1s.

Concept experiment · 4-bit

A browser model of the circuit, not a compiled design. The real toolchain runs in the examples.

Bit3210Place value-8421Inputs
Unsigned
15
Two's complement
-1
Hex
0xF

To negate a number, invert every bit and add 1. Take 5 = 0101: inverting gives 1010, adding 1 gives 1011, and 1011 reads −8 + 2 + 1 = −5. The same two steps turn −5 back into 5. The most negative value is the exception: in four bits, negating 1000 leaves 1000 because +8 is outside the signed range. Widen first if the positive result must be represented.

Two's complement is used because the previous unit's adder needs no change for it: 1111 + 0001 is 10000, and without the fifth bit that is 0000, as −1 + 1 should be.

Check

Read the 4-bit pattern 1010 as two's complement.

2. One pattern, two numbers

The circuit stores the pattern and nothing else. Whether 1111 means 15 or −1 is decided by whoever reads it. In a signed reading the top bit tells the sign, 1 for negative. Patterns whose top bit is 0 mean the same thing either way: 0000 to 0111 are 0 to 7 in both readings.

Where the readings disagree, comparisons disagree too: unsigned, 1000 is larger than 0111; signed, −8 is smaller than 7. Which reading a signal gets is not stored on the bus; it is part of the signal's type or declaration and any explicit conversions, which each language expresses in its own way.

3. Widening keeps the value only if the new bits fit the reading

Moving a 4-bit value onto an 8-bit bus adds four bits on the left, and they have to be given values. Zero extension fills them with 0 and preserves the unsigned reading. Sign extension fills them with copies of the old top bit and preserves the two's complement reading.

When the old top bit is 0, both extensions produce the same pattern and preserve both readings. The table shows a top bit of 1, where the results differ.

4-bit patternZero-extendedSign-extended
10100000101011111010
read unsigned10, as before250
read signed10−6, as before

Going the other way, truncation drops the top bits and keeps the lower ones. The value survives only when every dropped bit was 0 for an unsigned reading, or a copy of the new top bit for a signed one. 17 is 10001 in five bits; kept to four bits it is 0001, which is 1, because the dropped bit was worth 16.

Caution. Truncation is silent in the circuit: four wires carry four bits, and nothing records that a fifth existed. Whether a language warns, refuses or extends automatically when widths differ is that language's rule, taught in its path.

Check

Sign-extend the 4-bit pattern 1010 to 8 bits.

Check

17 is kept in a 4-bit unsigned signal. What value does the signal hold?

4. A lost carry and an overflow are different failures

A carry-out shows that an unsigned sum needs an extra bit; it is not itself an error. 9 + 8 is 1001 + 1000 = 10001; the fifth bit is the last stage's cout from the previous unit. Kept in four bits the result is 0001, which is 1, and the 16 the carry stood for is lost.

Signed overflow means that the true sum is outside the signed result range. 7 + 1 is 0111 + 0001 = 1000 with cout = 0, and read signed 1000 is −8: 8 is outside −8 to 7, so two positives summed to a negative. cout says nothing here; signed overflow shows in the signs, both operands one sign and the result the other.

ReadingThe result did not fit whenWhat shows it
Unsignedthe true sum is 2^n or morecout = 1
Signedthe true sum is outside −2^(n−1) to 2^(n−1) − 1operands one sign, result the other

The fix is the same for both: give the result one more bit than the operands, keeping cout as bit n for unsigned, or sign-extending both operands by one bit before adding for signed.

Check

A 4-bit signed adder computes 7 + 1 and the result reads −8. What happened?

Your answer

Check

A 4-bit unsigned adder computes 9 + 8 and stores 1. What is the smallest result width that would have stored 17 correctly?

5. Variation: a width for a signed range

A signal must hold every value from −20 to 20. Both endpoints must fit: −2^(n−1) must be at most −20, and 2^(n−1) − 1 must be at least 20. Five bits give −16 to 15 and miss both endpoints; six bits give −32 to 31. Unsigned, 0 to 20 would fit in five bits; the sign costs one bit.

Check

What is the smallest width that holds every two's complement value from −20 to 20?

6. Summary

  • In two's complement the top bit is worth −2^(n−1). n bits hold −2^(n−1) to 2^(n−1) − 1.
  • The bus stores the pattern; signed or unsigned interpretation comes from types, declarations and explicit conversions.
  • Zero extension preserves the unsigned value, sign extension the signed value. Truncation drops the top bits silently.
  • For addition, cout shows an unsigned sum outside the original width. Signed overflow occurs when same-sign operands produce the opposite sign. An extra result bit preserves the full sum when the operands are extended appropriately before adding.

Every circuit so far has no stored state. The next chapter introduces the register, which holds a value from one clock edge to the next.

Checkpoint

Answer the checks in this chapter