NELIX Silicon Lab Docs Launch Silicon Lab Launch Silicon Lab

Bit widths, signed arithmetic and overflow

How many bits a result needs, how negative numbers work, and what happens when a value does not fit.

StudentEngineer 2 min read · Updated 2026-10-05

On this page How many bitsUnsigned and signedWriting signed arithmeticA worked example: MAC-8OverflowIn the waveformIn a test

Most arithmetic bugs in hardware are width bugs. Software hides them behind 32- and 64-bit integers. Hardware does not.

How many bits#

OperationWidth of the full result
N bits + N bitsN + 1
N bits x M bitsN + M
Adding K values of N bitsN + the number of bits needed to count to K

If the signal you assign to is narrower than the full result, the top bits are thrown away without warning.

Width is not free. A registered W-bit by W-bit multiplier, synthesized with Yosys 0.33: 363 gates at 8 bits, 1,566 at 16. Doubling the width roughly quadruples the gates.

Unsigned and signed#

The same 8 bits mean different things.

BitsUnsignedSigned (two's complement)
0000_000111
0111_1111127127
1000_0000128-128
1111_1110254-2
1111_1111255-1

An 8-bit signed value runs from -128 to 127.

Writing signed arithmetic#

Declare the signals signed. If any operand in an expression is unsigned, the whole expression is treated as unsigned.

systemverilog
input  logic signed [7:0]  a, b;
logic signed [15:0] product;
assign product = a * b;

A worked example: MAC-8#

The MAC-8 starter multiplies two signed 8-bit numbers and adds the product to a running total. Its specification works the widths out:

  • One product is between -16256 (127 x -128) and 16384 (-128 x -128). That needs 16 bits.
  • The accumulator is 20 bits, from -524288 to 524287.
  • So at least 32 worst-case products fit before it wraps.

To add a 16-bit signed product to a 20-bit total, the product is sign-extended: its top bit is copied into the new upper bits.

systemverilog
acc <= acc + {{4{product[15]}}, product};

Overflow#

When a result does not fit, something has to happen. Decide which, and write it in the specification.

BehaviourWhat happensCost
WrapThe top bits are dropped. 127 + 1 becomes -128None. This is what hardware does by default
SaturateThe value sticks at the largest or smallest it can holdA comparator and a multiplexer
Cannot happenThe width is large enough for every caseA proof, written down

MAC-8 wraps, and says so: "Wrap-around is not detected."

In the waveform#

The waveform shows values in hexadecimal. -2 in 8 bits appears as fe, and -3 as fd. Most viewers can switch a signal to signed decimal.

In a test#

Compare like with like. Read a signed output with .value.to_signed(), or mask your Python result to the output's width: (a - b) & 0xFF.

Related

  • Project specificationsThe file that says what a design must do, the sections the starters use, and how the lab and its agents rely on it.
  • Tutorial: build an ALUWrite a small arithmetic unit and its test from a specification, starting from the Blank starter.

Something unclear or missing? Send feedbackSign in and use Feedback to tell us.