Binary Encodings
Unsigned, two's complement, Gray code and BCD: choose the right encoding for the circuit.
One binary word, several meanings
A bit bus has no single meaning. The pattern 1000 can represent:
8as an unsigned integer;-8as a 4-bit two's-complement value;- a Gray-coded position;
- an invalid BCD digit if a decimal digit from 0 to 9 is expected.
Encoding is therefore part of the specification. It must be chosen before writing comparisons, additions or conversions.
Unsigned integers
Unsigned encoding represents positive values only.
| Width | Range |
|---|---|
| 4 bits | 0 to 15 |
| 8 bits | 0 to 255 |
| 16 bits | 0 to 65,535 |
In VHDL, use unsigned to make the intent explicit:
signal counter : unsigned(7 downto 0);
counter <= counter + 1;If counter is 255, the next increment returns to 0 on 8 bits. This wraparound is not a bug: it is a modulo 256 overflow.
Two's complement
Two's complement is the most common signed encoding. On N bits, the range is:
-2^(N-1) to +2^(N-1)-1| Width | Signed range |
|---|---|
| 4 bits | -8 to +7 |
| 8 bits | -128 to +127 |
| 16 bits | -32,768 to +32,767 |
To obtain the opposite of a number:
- invert all bits;
- add
1.
Example on 4 bits:
+3 = 0011
NOT = 1100
+1 = 1101 therefore -3In VHDL:
signal a, b, y : signed(7 downto 0);
y <= a - b;The signed type tells both the synthesizer and the reader that the MSB is a sign bit.
Width extension
Before addition or subtraction, operands sometimes need to be widened to keep the result.
For unsigned values, add zeros on the left:
1010₂ on 4 bits becomes 01010₂ on 5 bitsFor signed two's-complement values, propagate the sign bit:
0010₂ (+2) becomes 00010₂
1010₂ (-6) becomes 11010₂In VHDL, use resize with the right type:
signal a8 : signed(7 downto 0);
signal y12 : signed(11 downto 0);
y12 <= resize(a8, y12'length);Most signed-encoding errors come from incorrect extension or silent mixing between std_logic_vector, signed and unsigned.
Gray code
Gray code changes one bit only between consecutive values. It is useful when a value is read during a mechanical or asynchronous transition.
| Decimal | Binary | Gray |
|---|---|---|
| 0 | 000 | 000 |
| 1 | 001 | 001 |
| 2 | 010 | 011 |
| 3 | 011 | 010 |
| 4 | 100 | 110 |
| 5 | 101 | 111 |
| 6 | 110 | 101 |
| 7 | 111 | |
Common uses:
- rotary encoder;
- position measurement;
- asynchronous FIFO pointers;
- information crossing between two clock domains.
The goal is to reduce the risk of reading an incoherent intermediate value when several bits would otherwise change at the same time.
BCD
BCD (binary coded decimal) encodes each decimal digit on 4 bits.
12₁₀ = 0001 0010 in BCD
12₁₀ = 0000 1100 in pure binaryBCD is less compact than pure binary, but it simplifies display-oriented interfaces: 7-segment displays, decimal input, watches and user-visible counters.
Codes 1010 to 1111 are not valid decimal digits in BCD.
Choosing the encoding
| Need | Recommended encoding |
|---|---|
| Counter, address, size | unsigned |
| Arithmetic with positive and negative values | signed two's complement |
| Position read during a transition | Gray |
| Direct decimal display | BCD |
| Masks, flags, frames | std_logic_vector |
A good design states the encoding clearly in names, types and useful comments. This avoids implicit conversions and makes simulations easier to read.
📝 Test your knowledge - Chapter quiz