Wrapping is correct for addresses, counters, and modular arithmetic. Signal-processing and control quantities often need saturation because a large positive result wrapping negative is catastrophic.
For the sensor pipeline, saturation is applied after nearest-even rounding at the final Q1.15 boundary. Keeping the 42-bit accumulator intact until then avoids repeated clipping. The half-LSB error budget applies only to unclipped outputs; clipped results carry the saturation flag and are checked against the clamp policy, not that accuracy bound.
Step | Q2.2 input +1.50 -> signed Q2.0 output |
|---|---|
Input code |
|
Nearest-even to integer | 6/4 = 1.5 -> four-bit signed code |
Output range | Two-bit signed codes -2 through +1 |
Clamp before narrowing | +2 exceeds +1: output code |
Wrong: narrow first | +2 becomes |
The range comparison is in output code units, after rescaling to the output's fractional-bit count. The running pipeline drops 15 low bits to move from F=30 to F=15, keeping the rounded code in wide signed storage. Sign-extend the signed output limits to that same width before comparing. For the Q1.15 output, +1.0 corresponds to rounded code 32768; it must clamp to 32767 (real value 1 - 2^-15), not wrap to -32768. Whether rounding or clipping sets a status flag is part of the interface contract.
Clamp to -2, code 10, before narrowing. Simply taking the low two bits of -3 gives 01 (+1), the wrong sign.
// snippet: signed saturating add
logic signed [W-1:0] a, b, y;
logic signed [W:0] wide;
localparam logic signed [W-1:0] MAX = {1'b0, {(W-1){1'b1}}};
localparam logic signed [W-1:0] MIN = {1'b1, {(W-1){1'b0}}};
assign wide = {a[W-1], a} + {b[W-1], b};
always_comb begin
if (wide > $signed(MAX)) y = MAX;
else if (wide < $signed(MIN)) y = MIN;
else y = wide[W-1:0];
endDecision | Specify |
|---|---|
Where to saturate | Each stage or only architectural output |
Positive/negative limits | Signed or unsigned representable range |
Flag | Pulse, sticky status, counter, or no report |
Order | Round then saturate, or saturate at full precision |
Maximum is 0 followed by W-1 ones; minimum is 1 followed by W-1 zeros.