Signed values, fixed point and digital codes
- Interpret two's-complement values
- Calculate signed range
- Apply sign extension
- Reason about fixed-point scale, rounding, and saturation
- Explain BCD, Gray code, and parity
Explanation
Two's complement
Most digital systems use two's complement for signed integers. In an N-bit two's-complement value, the most significant bit has weight -2^(N-1) and the remaining bits retain positive weights.
For 8'b1111_1011:
-128 + 64 + 32 + 16 + 8 + 0 + 2 + 1 = -5
Another decoding method is to invert the bits and add one to find the magnitude:
1111_1011 invert -> 0000_0100
0000_0100 add 1 -> 0000_0101 = 5
result = -5
The range is asymmetric:
N-bit signed minimum = -2^(N-1)
N-bit signed maximum = 2^(N-1) - 1
Eight signed bits represent -128 through +127. There is one more negative value because zero occupies a nonnegative pattern.
Other signed encodings
Sign-magnitude uses one sign bit and magnitude bits. Ones' complement forms a negative value by inverting every bit. Both have positive and negative zero, which complicates arithmetic. They remain useful to recognize when reading older formats, but two's complement is the normal arithmetic representation.
Sign extension and narrowing
To widen a two's-complement value, copy its sign bit into the new upper positions:
8-bit -5: 1111_1011
12-bit -5: 1111_1111_1011
Zero extension would change this to positive 251. When narrowing, the removed bits must all match the retained sign bit for the value to remain representable.
Signed overflow
Signed overflow is different from the unsigned carry-out. Adding two positive values and getting a negative result indicates overflow; so does adding two negative values and getting a nonnegative result.
8-bit signed: 100 + 60 = 160 mathematically
bit result: 0110_0100 + 0011_1100 = 1010_0000
interpreted: -96, so signed overflow occurred
Adding operands with different signs cannot overflow in two's-complement addition.
Binary fractions and fixed point
Fixed-point data agrees on an implied binary-point position. A common notation Qm.n uses integer and fractional fields, but conventions differ on whether the sign bit is included in m. A design must state its convention explicitly.
For an unsigned value with four fractional bits, the stored integer is scaled by 2^-4 = 1/16:
stored bits 0011_1010 = integer 58
real value = 58 / 16 = 3.625
Multiplying values with F1 and F2 fractional bits produces a full-precision product with F1 + F2 fractional bits. Returning to the original format requires scaling and possibly rounding. Truncation introduces a directional error; round-to-nearest usually reduces average error. Saturation prevents a large result from wrapping to an unrelated value.
Useful non-arithmetic codes
BCD stores each decimal digit separately in four bits. Decimal 59 becomes 0101_1001, while ordinary binary 59 is 0011_1011. BCD uses extra patterns but is convenient for decimal displays and financial formats.
Gray code orders values so adjacent codes differ in one bit. It is useful when a changing multi-bit pointer crosses a clock boundary because the receiver is less likely to observe a mixture of several transitioning bits. Gray code does not remove the need for synchronization.
Binary: 00, 01, 10, 11
Gray: 00, 01, 11, 10
Parity adds one bit so the total number of ones is even or odd. It detects any odd number of bit flips, including every single-bit error. It cannot locate the bad bit and misses errors that flip an even number of protected bits.
Representation checklist
- Record width, signedness, scale, units, and legal range.
- State rounding, saturation, and overflow policy.
- Treat casts, extension, and truncation as design decisions.
- Do not mix BCD, Gray, or raw binary values without explicit conversion.
Worked example
A signed sensor sample uses 8 total bits with 3 fractional bits. The bit pattern is 1110_1100.
- As an 8-bit two's-complement integer,
1110_1100is -20. - Three fractional bits give a scale of
1/8. - The represented value is
-20 / 8 = -2.5. - The format range is
-128/8through127/8, or -16.0 through 15.875. - Widening to 12 bits while preserving the scale gives
1111_1110_1100.
Now multiply by 1.5, represented as integer 12 with three fractional bits. The integer product is -20 × 12 = -240 with six fractional bits. Its real value is -240 / 64 = -3.75. To return to three fractional bits, divide the stored product by eight using the specified signed rounding rule.
Check yourself
Why does zero extension corrupt a negative two's-complement value? Why must a fixed-point interface document both width and fractional-bit position?