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

  • SystemVerilog Language Foundations34
    • SystemVerilog Data Types
      • 4-State vs 2-State Types
      • Nets vs Variables
      • Integer Types & Casting
      • X/Z Propagation & Pessimism
      • Enums, Structs & Unions
      • Strings, Reals & Special Types
    • Arrays: Packed, Dynamic, Queues & Associative
    • Procedural Code & Scheduling
    • Operators, Expressions & Width Rules
    • Packages, Typedefs & Compilation
    • Interfaces, Modports & Clocking Blocks
  • Object-Oriented SystemVerilog for Verification33
  • Constraint Randomization — Interview-Critical Deep Dive56
  • SystemVerilog Assertions — Interview-Critical Deep Dive54
  • Functional Coverage in SystemVerilog28
  • Testbench Architecture in SystemVerilog32
  • Advanced Language & Integration30
  • Senior & Interview Preparation29
Loading lesson

‹SystemVerilog Data Types
  1. Topics
  2. SystemVerilog
  3. SystemVerilog Language Foundations
  4. SystemVerilog Data Types
  5. Integer Types & Casting

Part 1 · Language Foundations · Intermediate

Integer Types & Casting

Integer widths and signedness, static and checked casts, and truncation and extension rules.

On this page

    Why this matters

    A countdown loop never ended, and a 16-bit field read back FFFE instead of 00FE. Both came from the same two silent rules: which integer types are signed, and how width changes fill the new bits.

    After this lesson you can: name the signedness and width of each integer type, predict truncation and extension, and pick a static cast, $cast or a streaming conversion.

    The integer family

    The fixed-width 2-state integers byte, shortint, int, and longint are all signed by default. The legacy 4-state types integer (32-bit signed) and time (64-bit unsigned) complete the family, while bit and logic vectors are unsigned.

    The signed default is the part that bites. One unsigned operand makes a whole comparison unsigned, so a negative value silently becomes huge and the comparison flips.

    Type

    Bits

    State

    Signed by default

    byte

    8

    2

    Yes

    shortint

    16

    2

    Yes

    int

    32

    2

    Yes

    longint

    64

    2

    Yes

    integer

    32

    4

    Yes, legacy Verilog

    time

    64

    4

    No, unsigned

    Declare int unsigned or byte unsigned whenever the value is a count, an address, or a bit pattern rather than a true signed number. Expression-level signedness and shift rules belong to the operators topic; this lesson covers declarations and conversions.

    Three kinds of cast

    A static cast (int'(expr), unsigned'(expr), 16'(expr)) converts between compatible types: width, signedness, or numeric type. It always succeeds, and data may truncate or round, since real-to-int rounds rather than truncates.

    A dynamic cast ($cast(dst, src)) is a runtime-checked downcast for stuffing an integer back into an enum. Called as a function it returns 0 on failure, so always check the result. Class-handle downcasts use the same call and are covered in the OOP patterns topic.

    A bit-stream cast reinterprets raw bits between packed structs, vectors, and queues, which is the standard trick for serializing a header into bytes. The next lesson proves the struct-to-vector form in simulation.

    Truncation and extension

    Plain assignment across widths needs no cast. A narrower target silently truncates from the MSB side, and a wider target extends: zero-extension for unsigned sources, sign-extension for signed ones.

    The rule to internalize is that the signedness of the source decides extension while the width of the target decides truncation. Most lint tools flag implicit truncation precisely because the language stays silent.

    Truncation keeps the low bits; extension fills by the source's signedness.
    Predict first A byte holding -2 is assigned to a 16-bit vector, and int'(3.7) is evaluated. What are the two results?

    16'hFFFE and 4. The byte is signed, so the assignment copies its top bit into the new upper bits. A cast from real to int rounds to the nearest integer; it does not truncate.

    Which conversion to use depends on what is changing:

    1. Changing width, signedness, or numeric type of values: static cast, or plain assignment where lint allows.

    2. Converting an integer to an enum: $cast, checking the function result.

    3. Serializing packed data: bit-stream cast or the streaming operator.

    4. Real to integer with a chosen direction: $floor or $ceil first, since plain cast rounds.

    Testbench

    Truncation, both extension rules, the mask idiom, and three static casts with exact expected values.

    design.sv
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    module tb_casts;
      logic [3:0] nib;
      logic [15:0] wide;
      byte sb;
      int errors = 0;
    
      initial begin
        nib = 16'hABCD;                       // silent truncation from the MSB side
        if (nib !== 4'hD) errors++;
        wide = nib;                           // unsigned source: zero-extend
        if (wide !== 16'h000D) errors++;
        sb = -2;                              // 8'hFE
        wide = sb;                            // signed source: sign-extend
        if (wide !== 16'hFFFE) errors++;
        wide = byte'(sb) & 8'hFF;             // mask idiom recovers 16'h00FE
        if (wide !== 16'h00FE) errors++;
        if (unsigned'(-1) !== 32'hFFFF_FFFF) errors++;
        if (int'(3.7) !== 4) errors++;        // real to int rounds, not truncates
        if (byte'(16'h1234) !== 8'h34) errors++;
        if (errors != 0) $fatal(1, "FAIL: cast checks saw %0d unexpected results", errors);
        $display("PASS: truncation kept low bits, signed sources sign-extended, casts converted");
        $finish;
      end
    endmodule
    Terminal
    PASS: truncation kept low bits, signed sources sign-extended, casts converted

    Common pitfall

    The loop for (int unsigned i = n; i >= 0; i--) never terminates because an unsigned counter cannot go below 0. Count down in a signed type or compare against the bound explicitly.

    Interview

    “What does a static cast from real to int do with 3.7, and how do you force truncation instead?” The cast rounds to 4, while $rtoi truncates to 3. Follow up with the sign-extension rule for narrow signed sources.

    Check yourself nib is logic [3:0] and the code says nib = 16'hABCD. Does the compiler stop you, and what does nib hold?

    No error; at most a lint warning. nib holds 4'hD, because a narrower target keeps the low bits and drops the rest silently.

    Check yourself When do you reach for $cast instead of a static cast?

    When the conversion needs a runtime legality check, such as stuffing an integer into an enum. A static cast always succeeds, so it cannot reject an illegal encoding.

    Remember

    • byte, shortint, int and longint are signed; bit and logic vectors are unsigned.

    • A narrower target keeps the low bits; a wider one fills by the source's signedness.

    • A static cast always succeeds (real to int rounds); $cast checks and can fail.

    Rule of thumb: the source's signedness decides the fill, the target's width decides the truncation.

    How this was checked

    Run with Verilator 5.048 (--binary --timing) on 2026-10-18; every bench printed the PASS line shown, with no warnings. Icarus 13 (-g2012) runs them too, with the same output.

    Related topics

    • Next: Enums, Structs & Unions

    Previous

    3 / 296

    Next: X/Z Propagation & Pessimism

    Up next

    Up nextX/Z Propagation & Pessimism

    Sign in to save progress

    Practice this lessonReport an error

    See also

    • 4-State vs 2-State Types
    • Enums, Structs & Unions
    • Strings, Reals & Special Types