Skip to content
DenseChip
Learn
PracticeCode labInterview

DenseChip

Navigate

Menu

LearnPracticeCode labInterview

Tools

All toolsSV editorCode repoResume
DenseChip

Practice, courses, and chip-design tools in one focused workspace.

LearnPracticeCode labInterviewToolsLearning paths

© 2026 DenseChip

AboutContactPrivacyTerms
Skip to lesson

Course contents

  • RTL Foundations36
  • Combinational Design25
    • Combinational Timing Overview
    • Muxes, Decoders and Encoders
    • Arithmetic Blocks
    • Comparators and Shifters
      • Magnitude Comparison
      • Barrel Shifter, Rotate and Arithmetic Shift
      • Mini Project: a Leading-Zero Counter and Normaliser
    • Tri-State and Shared Buses
    • Latch Inference
    • Arithmetic Datapaths
  • Sequential Design27
  • FSM & Control27
  • Timing & Clocking39
  • Reset & CDC34
  • Memory & Buses57
  • Advanced RTL28
  • Senior & Interview76
  • Glossary and Notation
Loading lesson

‹Comparators and Shifters
  1. Topics
  2. RTL Design
  3. Combinational Design
  4. Comparators and Shifters
  5. Magnitude Comparison

Part 2 · Combinational · Intermediate

Magnitude Comparison

One subtraction answers equality and ordering; the borrow gives unsigned less-than and N xor V gives signed.

On this page

    Why this matters

    The same bits give different answers for a < b: 15 against 16 is true unsigned and false signed. A comparison of one signed and one unsigned operand is unsigned, which is how a negative offset ends up as 4,294,967,295.

    After this lesson you can: build equality and ordering comparators, derive unsigned and signed less-than from the subtractor flags, and avoid the mixed-sign trap.

    Equality is cheap, ordering is not

    • Equality (a == b): XNOR each bit pair, then AND all the results. Depth is log₂ N.

    • Ordering (a < b): needs information to flow from the most significant bit down, like a carry. It is a subtraction in disguise.

    An unsigned a < b is exactly a borrow out of a − b. In terms of the adder flags from the earlier lesson, the carry out of a + ~b + 1 is 1 when there is no borrow, so

    a<u​b⟺C

    Signed ordering depends on both the sign bit of the difference and the overflow flag, because the subtraction itself can overflow:

    a<s​b⟺N⊕V

    Worked example with 4 bits. Take a = 0111 (7) and b = 1000 (8 unsigned, −8 signed).

    • Subtract: a − b = 0111 + ~1000 + 1 = 0111 + 0111 + 1 = 1111.

    • Borrow: the sign bit N is 1 and the carry out is 0, so there was a borrow.

    • Overflow: the true answer 7 − (−8) = 15 does not fit 4-bit signed, so V = 1.

    • Answers: the borrow gives unsigned less-than (lt_u = ~C = 1). N ⊕ V = 0 gives signed greater-than (7 > −8).

    Watch lt_u against lt_s: they disagree wherever the top bit changes the meaning. The diagram shows a and b in hex, so 15 appears as f.

    • Slot 1: 7 versus 8 borrows, so lt_u is 1; N ⊕ V is 0, so lt_s is 0.

    • Slot 2: 8 versus 7 has no borrow, so lt_u is 0; N ⊕ V is 1, so lt_s is 1.

    • Slot 3: equal values give eq of 1 and both less-than outputs 0.

    • Slot 4: 15 (f) versus 1 has no borrow, so lt_u is 0; N ⊕ V is 1, so lt_s is 1.

    • Slot 5: 0 versus 15 (f) borrows, so lt_u is 1; N ⊕ V is 0, so lt_s is 0.

    Signed versus unsigned

    This table is the pattern to memorize. Two rows disagree:

    a

    b

    Unsigned a < b

    Signed a < b

    11111 (31 / −1)

    00001 (1 / 1)

    false

    true

    01111 (15 / 15)

    10000 (16 / −16)

    true

    false

    00101 (5 / 5)

    00110 (6 / 6)

    true

    true

    Check yourself Predict: a = 11111, b = 00001. Is a < b true unsigned? Signed?

    Unsigned: false (31 > 1). Signed: true (−1 < 1). Same bits, different answer.

    Check yourself Predict: a = 01111, b = 10000. Is a < b true unsigned? Signed?

    Unsigned: true (15 < 16). Signed: false (15 > −16). The top bit flips the meaning.

    Check yourself The comparison if (offset > -1) on logic [3:0] offset is always false. Why?

    offset is unsigned and -1 is converted to unsigned too (all ones, 4294967295 for a 32-bit literal), so no 4-bit value exceeds it. Declare offset as signed or restate the condition.

    Common mistakes

    A common interview question is how to compare two signed numbers using only an adder.

    • Subtract with the adder: a − b = a + ~b + 1.

    • Answer signed less-than as N ⊕ V, unsigned as ~C.

    • Declare both operands signed, or the comparison is unsigned.

    Common pitfall

    a < b is unsigned unless both operands are declared signed. If one is signed and the other is not, the whole comparison is unsigned, so −1 compares as 31 (or 2³²−1 for a 32-bit variable). Declare numeric operands signed at the point of declaration.

    Tip

    Compare against sized constants. count < 10 uses a 32-bit signed unsized literal, but with unsigned count the comparison is still unsigned and widens the expression; count < 4'd10 keeps it at the counter's width.

    Testbench

    The comparator plus a testbench that checks all 1024 pairs against the language operators.

    compare.sv
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    module compare #(parameter int N = 5) (
      input  logic [N-1:0] a, b,
      output logic         eq, lt_u, lt_s
    );
      logic [N:0]   diff;
      logic [N-1:0] nb;
      logic         c, n, v;
      always_comb begin
        nb   = ~b;
        diff = {1'b0, a} + {1'b0, nb} + 1'b1;          // a - b with carry out
        c    = diff[N];                                  // 1 means "no borrow" (a >= b unsigned)
        n    = diff[N-1];
        v    = (a[N-1] == nb[N-1]) && (diff[N-1] != a[N-1]);
        eq   = &(~(a ^ b));                              // XNOR every bit, AND the results
        lt_u = ~c;
        lt_s = n ^ v;
      end
    endmodule
    

    Remember

    • Equality is an XNOR per bit and an AND tree. Ordering is a subtraction in disguise.

    • Unsigned a < b is ~C (the borrow). Signed a < b is N ^ V.

    • If either operand is unsigned, the whole comparison is unsigned. Declare both signed.

    Rule of thumb: declare both operands signed, or the comparison is unsigned.

    How this was checked

    The test uses 1 ns time units and 1 ps precision. #1 is a settle interval for zero-delay combinational RTL, not a measured comparator delay. It checks known binary operands at N = 5; X/Z operand behaviour and mapped timing need separate checks. Failures identify both numeric interpretations and each expected and actual output, then $fatal gives a failing simulation verdict.

    Keep going

    • Code lab: Build a signed comparator

    • Interview: run a mock interview on this topic

    Related topics

    • Adder building blocks

    Previous

    48 / 350

    Next: Barrel Shifter, Rotate and Arithmetic Shift

    Up next

    Up nextBarrel Shifter, Rotate and Arithmetic Shift

    Sign in to save progress

    Practice this lessonReport an error

    See also

    • Mini Project: a Leading-Zero Counter and Normaliser
    clka785f0b8751feqlt_ult_snvc
    Four-bit subtraction answers equality, unsigned and signed ordering