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

  • Start Here6
  • SystemVerilog Language Foundations28
    • SystemVerilog Data Types
    • Arrays: Packed, Dynamic, Queues & Associative
      • Packed vs Unpacked Arrays
      • Dynamic Arrays and Queues
      • Associative Arrays
      • Array Methods and Selection
    • Procedural Code & Scheduling
    • Operators, Expressions & Width Rules
    • Packages, Typedefs & Compilation
    • Interfaces, Modports & Clocking Blocks
  • Object-Oriented SystemVerilog for Verification30
  • Constraint Randomization — Interview-Critical Deep Dive36
  • SystemVerilog Assertions — Interview-Critical Deep Dive40
  • Functional Coverage in SystemVerilog22
  • Testbench Architecture in SystemVerilog23
  • Advanced Language & Integration25
  • Senior & Interview Preparation21
  • Principal-Level Verification28
Loading lesson

‹Arrays: Packed, Dynamic, Queues & Associative
  1. Topics
  2. SystemVerilog
  3. SystemVerilog Language Foundations
  4. Arrays: Packed, Dynamic, Queues & Associative
  5. Packed vs Unpacked Arrays

Part 1 · Language Foundations · Intermediate

Packed vs Unpacked Arrays

Packed vectors versus unpacked elements: layout, slicing, copies and synthesis.

On this page

    Why this matters

    A 16 KB memory model synthesized into 131,072 flip-flops instead of one RAM, because its dimensions sat on the wrong side of the name. Which side a dimension sits on decides what the array is.

    After this lesson you can: tell packed from unpacked dimensions, index and slice both kinds, and say which operations each allows.

    One vector or many elements

    Dimensions before the name are packed. The whole array is one contiguous vector that supports arithmetic, comparison and part-selects.

    Dimensions after the name are unpacked. Each element is independent, so whole-array arithmetic is illegal, while whole-array copy and == work element by element on matching shapes.

    Packed

    Unpacked

    Declaration

    logic [7:0] bus

    logic [7:0] mem [0:1023]

    Meaning

    One 8-bit vector

    1024 independent bytes

    bus + 1

    Legal

    Illegal: no whole-array arithmetic

    ==, !=

    Legal

    Legal when both arrays have the same element type and shape

    [3:0] slice

    Legal: selects bits

    Legal: selects whole elements, not bits

    Element type

    bit, logic, reg, packed structs, unions and enums

    Anything, including classes

    The declaration logic [7:0] mem [0:1023] reads as 1024 unpacked elements of packed 8-bit vectors. That is exactly the shape of a byte memory.

    Packed dimensions apply to single-bit types (bit, logic, reg), packed structs and unions, and enums. Integer types such as byte, shortint and int already count as packed vectors, but they cannot take extra packed dimensions: int [3:0] x is illegal, while int x [4] (unpacked) is fine.

    Ranges, order and slicing

    Packed ranges conventionally run [msb:lsb]. Unpacked ranges traditionally run [0:n-1], with [n] as shorthand for [0:n-1].

    Index unpacked dimensions first from left to right, then packed dimensions from left to right. Bit part-selects need a packed dimension. On an unpacked dimension, [3:0] and +: select a slice of whole elements.

    Dimensions before the name pack into one vector; dimensions after it make separate elements.
    • Declaration: packed dimensions sit before the name, unpacked dimensions after it.

    • Indexing: consume unpacked dimensions first left to right, then packed dimensions left to right.

    • Slicing: bit part-selects apply to packed dimensions only; unpacked slices select whole elements.

    • Copies: whole-array assignment and equality need identical element type and shape on both sides.

    Common mistakes

    Common pitfall

    A part-select on an unpacked dimension selects elements, not bits. For logic [7:0] mem [0:7], mem[0:3] is four bytes. Bit slices need a packed dimension.

    Interview

    Likely question: “which side of the name makes an array packed?”

    • Before the name is packed: one vector with arithmetic and slicing.

    • After the name is unpacked: independent elements.

    • Order of indexing: unpacked first, then packed.

    Check yourself Why does bus + 1 compile for a packed array but not for an unpacked one?

    Only packed arrays are vectors. Arithmetic is a vector operation, and unpacked arrays are collections of independent elements.

    Check yourself logic [31:0] mem [0:4095] synthesizes to RAM, but one flat 131072-bit vector does not. Why?

    RAM inference looks for unpacked elements of packed words with an indexed read and a clocked write. One flat vector looks like discrete flops, so the tool builds flops.

    Testbench

    Predict first The bench writes 32'hDEAD_BEEF to frame[0], then 8'hAA to lane 3, then clears bit 7 of lane 3. What do frame[0][3] and frame[0][0] hold?

    8'h2A and 8'hEF. Lane 3 is bits 31:24, so it becomes AA and then loses its top bit; lane 0 keeps the EF from the first write.

    Layout, lane access, slicing and copy rules, proved with one self-checking testbench.

    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
    25
    26
    27
    module tb_packed_layout;
      logic [3:0][7:0] frame [0:1];   // 2 unpacked rows of packed 4-lane vectors
      logic [7:0] a [0:3];
      logic [7:0] b [0:3];
      int errors = 0;
    
      initial begin
        frame[0] = 32'hDEAD_BEEF;     // whole packed value of row 0
        frame[0][3] = 8'hAA;          // lane 3 (bits 31:24) of row 0
        frame[0][3][7] = 1'b0;        // clear top bit of lane 3: AA -> 2A
        frame[1][1:0] = 16'hCAFE;     // packed slice: lanes 1..0
        if (frame[0][3] !== 8'h2A) errors++;
        if (frame[0][0] !== 8'hEF) errors++;
        if (frame[1][1:0] !== 16'hCAFE) errors++;
    
        a = '{8'h11, 8'h22, 8'h33, 8'h44};
        b = '{default: 8'h00};
        b = a;                        // legal: identical shape, element-wise copy
        // c = a;                     // ILLEGAL when c has 8 elements vs 4
        if (a != b) errors++;
        if (b[2] !== 8'h33) errors++;
    
        if (errors != 0) $fatal(1, "FAIL: packed layout self-check");
        $display("PASS: packed lanes and slices read back, identical-shape copies compare equal");
        $finish;
      end
    endmodule
    Terminal
    PASS: packed lanes and slices read back, identical-shape copies compare equal

    Remember

    • Dimensions before the name are packed: one vector with arithmetic and bit slices.

    • Dimensions after the name are unpacked: separate elements, copied and compared one by one.

    • Index unpacked dimensions first, then packed, each left to right.

    Rule of thumb: before the name is one vector; after the name is many elements.

    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 cannot run this bench (it rejects the default: assignment pattern).

    Related topics

    • Next: Dynamic Arrays and Queues

    Previous

    12 / 259

    Next: Dynamic Arrays and Queues

    Up next

    Up nextDynamic Arrays and Queues

    Sign in to save progress

    Practice this lessonReport an error

    See also

    • Associative Arrays
    • Array Methods and Selection