§ 2.4. Comparison and Selection¶
ALU8 reuses its arithmetic subtraction path for comparisons. ZeroDetect8 reduces a word to a zero predicate; CompareSelect8 consumes subtraction outputs to produce predicates or select one of the original operands.
| Component | Description | Structural | Behavioral |
|---|---|---|---|
ZeroDetect8 |
Reports whether an eight-bit word is zero through a one-bit predicate | Yes | Yes |
CompareSelect8 |
Uses subtraction results and flags to produce equality/less-than predicates or signed/unsigned min/max selections | Yes | Yes |
These columns indicate registered simulator implementations; the simplified C++ examples below are not counted.
The bit numbering, signed interpretation, and no-borrow convention from 2.1. Arithmetic Components apply here. Both components are combinational, with no clock or stored flags. The simplified C++ examples describe binary behavior, not the simulator implementation; they omit propagation delays and X/Z handling and can be compiled together in the order shown.
2.4.1. ZeroDetect8¶
ZeroDetect8 asserts a one-bit output only when every input bit is zero. The same component is reused for equality detection and the complete ALU's result-zero flag.
IO pins¶
| Pin | Direction | Width | Description |
|---|---|---|---|
A |
Input | 8 | Word to inspect |
ZERO |
Output | 1 | 1 when all eight input bits are zero |
Behavior¶
For binary inputs,
ZERO is an active-high predicate, not an eight-bit result. There is no signed/unsigned distinction: only the all-zero bit pattern produces 1.
C++ example¶
Unknown inputs and timing¶
| Input condition | Settled ZERO |
|---|---|
| Every bit is 0 | 1 |
At least one bit is 1, regardless of other X/Z bits |
0 |
No bit is 1, and at least one bit is X or Z |
X |
Z denotes high impedance and is interpreted as unknown by the OR/NOT gates. The component's ZERO output never denotes high impedance.
The OR gates form a balanced three-level reduction tree. Every input bit crosses the same number of OR gates before the final inversion. The predicate can still change while inputs propagate; no single component latency is declared. The C++ example describes only settled binary behavior.
Implementation¶
Structural implementation¶
| Internal component | Count | Connection |
|---|---|---|
BitSplitter<8> |
1 | Split A into bits 0–7 |
ORGate |
7 | Reduce the bits to an any-one predicate |
NOTGate |
1 | Invert the reduction into ZERO |
OR0–OR3 combine adjacent input-bit pairs; OR4 and OR5 combine pairs of those results; OR6 combines the two halves. OR6.OUT feeds NOT_ZERO.IN; NOT_ZERO.OUT drives the external ZERO pin.
Behavioral implementation¶
Behavioral8<ZeroDetect8> calls zero, which OR-reduces the eight four-state input values and inverts the result. A known 1 establishes ZERO = 0; without a known 1, an X or Z prevents the result from being known.
The evaluator is defined in ALU8Behavioral.cpp; its value functions are in ALU8ValueModel.hpp. It retains the public pins without functional circuit children. Catalog construction supplies a delay table characterized from the gates; where a delay twin is available and agrees with the computed value, publication can follow the current inputs’ gate-level settling time within that bound, subject to older pending results. The compact evaluator does not reproduce transient gate glitches.
The recorded scenario runs against both implementations in CTest. ALU8FidelityContractTest checks binary/X/Z settled-output equivalence against the structural circuit. The example table uses the default structural run; its checkpoint times need not match the behavioral run.
Examples¶
All 11 recorded rows of ZeroDetect8Test, in checkpoint order. Outputs are test expectations verified against the simulation. Time is the absolute settled checkpoint time in simulator units, not milliseconds or CPU cycles.
Default scenario profile: canonical-default-preview / structural (4a124a9ab994974b). Changing fidelity or the circuit can change these times.
| Checkpointzero-based number · timeline label | Timesimulator units | AInput · 8 bit |
ZEROExpected output · 1 bit |
|---|---|---|---|
#0row-0 | 5 | 0x00 |
1 |
#1row-1 | 11 | 0x01 |
0 |
#2row-2 | 14 | 0x02 |
0 |
#3row-3 | 19 | 0x10 |
0 |
#4row-4 | 24 | 0x7F |
0 |
#5row-5 | 29 | 0x80 |
0 |
#6row-6 | 34 | 0xFF |
0 |
#7row-7 | 40 | 0b0000X000 |
X |
#8row-8 | 46 | 0b1000X000 |
0 |
#9row-9 | 52 | 0b0000Z000 |
X |
#10row-10 | 58 | 0b1000Z000 |
0 |
Scroll within the table for all rows and pins. Buses use hexadecimal; values containing X/Z use MSB-first binary. Inputs show the declared values in effect at each checkpoint, including retained inputs. Sequential tests also replay preparation changes between checkpoints, such as lowering the clock. Use the matching checkpoint label in the simulation below.
Embedded simulation¶
The zero-detect8 scenario runs ZeroDetect8Test: seven binary cases and four four-state cases. The latter drive bit 3 to X or Z, first without a known 1 elsewhere and then with bit 7 high. Use checkpoints to compare the resulting unknown and known-zero predicates.
Open ZeroDetect8 in the simulator
Source and tests¶
| Test | Coverage |
|---|---|
ZeroDetect8Test / zeroDetect8Rows() |
11 recorded cases: seven binary words and four X/Z cases. Checks ZERO; this is the embedded scenario. |
CompareSelect8Test and ALU8ContractTest |
Exercise zero detection through equality selection and the integrated ALU's result flags. These are integration checks, not a standalone exhaustive zero-detector sweep. |
ZeroDetect8Test does not sweep all 256 binary words or all four-state patterns.
2.4.2. CompareSelect8¶
CompareSelect8 derives comparison decisions from an externally supplied subtraction result and flags. It returns an eight-bit predicate or selects A or B; it contains no subtractor.
IO pins¶
| Pin | Direction | Width | Description |
|---|---|---|---|
A |
Input | 8 | First original operand, available for min/max selection |
B |
Input | 8 | Second original operand, available for min/max selection |
DIFF |
Input | 8 | Low eight bits of A - B |
CARRY_IN |
Input | 1 | Carry-out of that subtraction; 1 means no unsigned borrow |
OVERFLOW_IN |
Input | 1 | Signed overflow of that subtraction |
OP |
Input | 3 | Local comparison/selection opcode |
OUT |
Output | 8 | Predicate encoded as 0x00/0x01, or the selected operand |
CARRY_IN is a subtraction output supplied to this component, not the incoming carry/borrow operand of AddSub8. There is no C_IN pin and no ZERO, CARRY, OVERFLOW, or INVALID_OP output on CompareSelect8.
Behavior¶
For the results to represent comparisons of the supplied A and B, the caller must provide a consistent subtraction:
The internal decisions are
L_s corrects the sign of a wrapped subtraction when signed overflow occurs. A sign-bit test alone is not a signed comparison.
Local OP |
Operation | OUT |
Decision inputs | Complete ALU8.OP |
|---|---|---|---|---|
0b000 |
EQ |
0x01 if E, otherwise 0x00 |
All DIFF bits |
0x15 |
0b001 |
SLTU |
0x01 if L_u, otherwise 0x00 |
CARRY_IN |
0x16 |
0b010 |
SLT |
0x01 if L_s, otherwise 0x00 |
DIFF[7], OVERFLOW_IN |
0x17 |
0b011 |
MINU |
A if L_u, otherwise B |
CARRY_IN |
0x18 |
0b100 |
MAXU |
B if L_u, otherwise A |
CARRY_IN |
0x19 |
0b101 |
MINS |
A if L_s, otherwise B |
DIFF[7], OVERFLOW_IN |
0x1A |
0b110 |
MAXS |
B if L_s, otherwise A |
DIFF[7], OVERFLOW_IN |
0x1B |
0b111 |
Reserved | 0x00 |
None | No corresponding comparison operation |
Predicate operations ignore the A and B pins directly; the supplied subtraction signals determine the decision. Min/max operations additionally use the original operands as output data. Inputs absent from an operation's decision and data paths are ignored for a known local opcode. Equal operands select B for min and A for max, with identical output values.
The component does not validate the consistency requirement. For example, EQ returns 0x01 for DIFF = 0 even if the separately supplied A and B differ. The complete ALU prevents this mismatch by wiring all subtraction signals from the shared arithmetic path.
The global codes 0x15–0x1B are explicitly remapped to local codes 0–6. Passing only the low three global opcode bits would select the wrong operation. The complete ALU computes result flags separately; a false predicate produces OUT = 0, so its result-zero flag is 1.
C++ example¶
std::uint8_t compare_select8_ref(
std::uint8_t a, std::uint8_t b, std::uint8_t diff,
bool carry_in, bool overflow_in, std::uint8_t op) {
const bool equal = zero_detect8_ref(diff);
const bool unsigned_lt = !carry_in;
const bool signed_lt = ((diff & 0x80u) != 0) != overflow_in;
switch (op) {
case 0: return static_cast<std::uint8_t>(equal);
case 1: return static_cast<std::uint8_t>(unsigned_lt);
case 2: return static_cast<std::uint8_t>(signed_lt);
case 3: return unsigned_lt ? a : b;
case 4: return unsigned_lt ? b : a;
case 5: return signed_lt ? a : b;
case 6: return signed_lt ? b : a;
default: return 0;
}
}
The example consumes diff, carry, and overflow rather than recomputing a - b. Like the structural component, it does not reject inconsistent input combinations. op represents the three-bit local selector; out-of-range integer arguments also return zero.
Unknown inputs and timing¶
For a known EQ selection, the ZeroDetect8 rules apply to DIFF. A known 1 in DIFF establishes inequality even if another bit is unknown. For SLTU, unknown carry makes the predicate bit unknown. For SLT, an unknown sign or overflow input makes the predicate bit unknown. In each predicate operation, output bits 7–1 remain zero.
Min/max outputs follow the structural multiplexers, including their handling of an unknown decision signal; they do not perform a separate integer comparison to resolve it. The known reserved local selection produces zero even with unknown data. Z inputs passing through logic are treated as unknown.
When used with the arithmetic unit, subtraction data and flags can arrive at different times before the comparison settles. There is no single declared structural CompareSelect8 latency. The standalone recorded scenario supplies DIFF and the flags as inputs; it does not simulate the upstream subtraction's propagation.
Implementation¶
Structural implementation¶
| Internal block | Function |
|---|---|
DIFF_SPLIT |
Expose DIFF[7] for the signed decision |
EQUAL (ZeroDetect8) |
Derive the equality predicate from DIFF |
UNSIGNED_LT (NOTGate) |
Invert the no-borrow input |
SIGNED_LT (XORGate) |
Combine the difference sign and overflow |
A_SPLIT, B_SPLIT |
Expose original operand bits for selection |
MINU_*, MAXU_*, MINS_*, MAXS_* |
Select operand bits using Mux2to1 components |
RESULT_* (Mux8to1) |
Select a predicate, min/max data, or constant zero per output bit |
OUT_JOIN |
Assemble the result word |
To connect a standalone AddSub8, drive its A and B from the same operands, set SUB = 1 and C_IN = 1, and connect:
| Subtraction output | CompareSelect8 input |
|---|---|
AddSub8.OUT |
DIFF |
AddSub8.CARRY_OUT |
CARRY_IN |
AddSub8.OVERFLOW |
OVERFLOW_IN |
The complete ALU uses ArithmeticUnit8 in SUB mode for these signals and selects the CompareSelect8 result. No second Adder8 or dedicated comparator datapath is instantiated for these operations.
Behavioral implementation¶
Behavioral8<CompareSelect8> calls compare. It derives equality from DIFF, unsigned less-than from CARRY_IN, and signed less-than from DIFF[7] XOR OVERFLOW_IN, then uses four-state multiplexer functions to assemble the selected predicate or operand. It consumes the supplied subtraction signals without recomputing or validating A - B.
The evaluator is defined in ALU8Behavioral.cpp; its value functions are in ALU8ValueModel.hpp. It retains the public pins without functional circuit children. Catalog construction supplies a delay table characterized from the gates; where a delay twin is available and agrees with the computed value, publication can follow the current inputs’ gate-level settling time within that bound, subject to older pending results. The compact evaluator does not reproduce transient gate glitches.
The recorded scenario runs against both implementations in CTest. ALU8FidelityContractTest checks binary/X/Z settled-output equivalence against the structural circuit. The example table uses the default structural run; its checkpoint times need not match the behavioral run.
Examples¶
All 40 recorded rows of CompareSelect8Test, in checkpoint order. Outputs are test expectations verified against the simulation. Time is the absolute settled checkpoint time in simulator units, not milliseconds or CPU cycles.
Default scenario profile: canonical-default-preview / structural (7be6cfe79f7552e1). Changing fidelity or the circuit can change these times.
| Checkpointzero-based number · timeline label | Timesimulator units | AInput · 8 bit |
BInput · 8 bit |
CARRY_INInput · 1 bit |
DIFFInput · 8 bit |
OPInput · 3 bit |
OVERFLOW_INInput · 1 bit |
OUTExpected output · 8 bit |
|---|---|---|---|---|---|---|---|---|
#0row-0 | 11 | 0x00 |
0x01 |
0 |
0xFF |
0x0 |
0 |
0x00 |
#1row-1 | 23 | 0x01 |
0x01 |
1 |
0x00 |
0x0 |
0 |
0x01 |
#2row-2 | 35 | 0x7F |
0x01 |
1 |
0x7E |
0x0 |
0 |
0x00 |
#3row-3 | 44 | 0x80 |
0x01 |
1 |
0x7F |
0x0 |
1 |
0x00 |
#4row-4 | 53 | 0xFF |
0x01 |
1 |
0xFE |
0x0 |
0 |
0x00 |
#5row-5 | 62 | 0x00 |
0x01 |
0 |
0xFF |
0x1 |
0 |
0x01 |
#6row-6 | 73 | 0x01 |
0x01 |
1 |
0x00 |
0x1 |
0 |
0x00 |
#7row-7 | 80 | 0x7F |
0x01 |
1 |
0x7E |
0x1 |
0 |
0x00 |
#8row-8 | 90 | 0x80 |
0x01 |
1 |
0x7F |
0x1 |
1 |
0x00 |
#9row-9 | 100 | 0xFF |
0x01 |
1 |
0xFE |
0x1 |
0 |
0x00 |
#10row-10 | 109 | 0x00 |
0x01 |
0 |
0xFF |
0x2 |
0 |
0x01 |
#11row-11 | 120 | 0x01 |
0x01 |
1 |
0x00 |
0x2 |
0 |
0x00 |
#12row-12 | 129 | 0x7F |
0x01 |
1 |
0x7E |
0x2 |
0 |
0x00 |
#13row-13 | 139 | 0x80 |
0x01 |
1 |
0x7F |
0x2 |
1 |
0x01 |
#14row-14 | 150 | 0xFF |
0x01 |
1 |
0xFE |
0x2 |
0 |
0x01 |
#15row-15 | 161 | 0x00 |
0x01 |
0 |
0xFF |
0x3 |
0 |
0x00 |
#16row-16 | 172 | 0x01 |
0x01 |
1 |
0x00 |
0x3 |
0 |
0x01 |
#17row-17 | 179 | 0x7F |
0x01 |
1 |
0x7E |
0x3 |
0 |
0x01 |
#18row-18 | 187 | 0x80 |
0x01 |
1 |
0x7F |
0x3 |
1 |
0x01 |
#19row-19 | 195 | 0xFF |
0x01 |
1 |
0xFE |
0x3 |
0 |
0x01 |
#20row-20 | 205 | 0x00 |
0x01 |
0 |
0xFF |
0x4 |
0 |
0x01 |
#21row-21 | 216 | 0x01 |
0x01 |
1 |
0x00 |
0x4 |
0 |
0x01 |
#22row-22 | 227 | 0x7F |
0x01 |
1 |
0x7E |
0x4 |
0 |
0x7F |
#23row-23 | 237 | 0x80 |
0x01 |
1 |
0x7F |
0x4 |
1 |
0x80 |
#24row-24 | 247 | 0xFF |
0x01 |
1 |
0xFE |
0x4 |
0 |
0xFF |
#25row-25 | 257 | 0x00 |
0x01 |
0 |
0xFF |
0x5 |
0 |
0x00 |
#26row-26 | 269 | 0x01 |
0x01 |
1 |
0x00 |
0x5 |
0 |
0x01 |
#27row-27 | 276 | 0x7F |
0x01 |
1 |
0x7E |
0x5 |
0 |
0x01 |
#28row-28 | 287 | 0x80 |
0x01 |
1 |
0x7F |
0x5 |
1 |
0x80 |
#29row-29 | 298 | 0xFF |
0x01 |
1 |
0xFE |
0x5 |
0 |
0xFF |
#30row-30 | 307 | 0x00 |
0x01 |
0 |
0xFF |
0x6 |
0 |
0x01 |
#31row-31 | 319 | 0x01 |
0x01 |
1 |
0x00 |
0x6 |
0 |
0x01 |
#32row-32 | 329 | 0x7F |
0x01 |
1 |
0x7E |
0x6 |
0 |
0x7F |
#33row-33 | 340 | 0x80 |
0x01 |
1 |
0x7F |
0x6 |
1 |
0x01 |
#34row-34 | 352 | 0xFF |
0x01 |
1 |
0xFE |
0x6 |
0 |
0x01 |
#35row-35 | 362 | 0x00 |
0x01 |
0 |
0xFF |
0x7 |
0 |
0x00 |
#36row-36 | 372 | 0x01 |
0x01 |
1 |
0x00 |
0x7 |
0 |
0x00 |
#37row-37 | 379 | 0x7F |
0x01 |
1 |
0x7E |
0x7 |
0 |
0x00 |
#38row-38 | 387 | 0x80 |
0x01 |
1 |
0x7F |
0x7 |
1 |
0x00 |
#39row-39 | 395 | 0xFF |
0x01 |
1 |
0xFE |
0x7 |
0 |
0x00 |
Scroll within the table for all rows and pins. Buses use hexadecimal; values containing X/Z use MSB-first binary. Inputs show the declared values in effect at each checkpoint, including retained inputs. Sequential tests also replay preparation changes between checkpoints, such as lowering the clock. Use the matching checkpoint label in the simulation below.
The 0x80 versus 0x01 rows compare 128 with 1 as unsigned values, but −128 with 1 as signed values. The overflow input is necessary because the eight-bit difference wraps to the positive pattern 0x7F.
Embedded simulation¶
The compare-select8 scenario runs CompareSelect8Test: 40 recorded cases using all eight local selections, five A values (0, 1, 127, 128, 255), and B = 1. The test driver supplies consistent DIFF, carry, and overflow for every case, including the reserved local opcode. All rows appear in the table above.
Open CompareSelect8 in the simulator
Source and tests¶
- Interface:
CompareSelect8.hpp - Implementation:
CompareSelect8.cpp - Shared subtraction wiring:
ALU8.cpp
| Test | Coverage |
|---|---|
CompareSelect8Test |
40 recorded binary cases: eight local selections × five A values, with B = 1 and consistent subtraction inputs. Checks OUT; this is the embedded scenario. |
ALU8ContractTest: integrated checks |
Includes 1,134 binary boundary cases for the seven comparison operations: seven opcodes × nine A values × nine B values × both top-level carry inputs. Seeded random ALU cases provide additional coverage. Subtraction signals come from the actual shared arithmetic unit. |
These checks are not exhaustive over operand pairs or independently driven DIFF/flag combinations. The recorded comparison scenario contains no X/Z cases. The separate ALU8FidelityContractTest exercises independently driven DIFF/flags, sparse and dense X/Z data, and every four-state local selector against both fidelities.