System Verilog Union – Packed, Unpacked, and Tagged

Introduction

In System Verilog, a union allows a single piece of storage to be represented in different ways using multiple named members. Unlike a struct, where each member has its own storage, all members of a union share the same memory space.

~ This means only one member is valid at a time.
~A union is large enough to contain its largest member, and all members overlap this memory region.

Key difference:

  • struct → Members are laid out one after another.
  • union → Members overlay each other’s memory.

Example: Simple Union vs Struct

// Union example
union {
  int a;
  byte b;
  bit [15:0] c;
} data;

  • Here, int is the largest member (32 bits).
  • The union will occupy 32 bits of storage.
  • Writing to one field overwrites the others.
// Struct example
struct {
  int a;
  byte b;
  bit [15:0] c;
} data;

  • Members are placed sequentially in memory.
  • Total size = sum of all members (with possible padding).

Note:

Union –> saves space, but only one field valid at a time.

Struct –> all fields have independent storage.


Typedef Union

Like structs, unions can be defined as user-defined types:

typedef union {
  int i;
  bit [15:0] b1;
} data_t;

data_t d1, d2;

Packed vs Unpacked Unions

1. Unpacked Union

  • Default in SystemVerilog.
  • Members can have different sizes.
  • Cannot be synthesized (mainly used in testbenches).
  • Storage = size of the largest member.

Example:

union {       // Unpacked
  int a;
  byte b;
  bit [15:0] c;
} data;

Simulation Example:

module union_example;
  logic [31:0] x;
  typedef union {
    int a;
    byte b;
    bit [15:0] c;
  } data_t;

  data_t d1;

  initial begin
    d1.a = 32'hffff_ffff;
    x = d1.b;   // overlayed value
    $display("x = %h", x);

    d1.b = 8'h01;
    x = d1.a;
    $display("x = %h", x);

    d1.c = 16'h1010;
    x = d1.a;
    $display("x = %h", x);
  end
endmodule

Simulation Log:

x = ffffffff
x = 00000001
x = 00001010

2. Packed Union

  • Declared with union packed.
  • All members must be the same size.
  • Can be used in arithmetic/logical operations.
  • Synthesizable.
  • Cannot contain real, shortreal, unpacked arrays, or unpacked unions.

Example:

typedef union packed {
  int a;
  bit [31:0] c;
} data_t;

Both members are 32 bits → valid packed union.


3. Tagged Union

  • Declared with union tagged.
  • Includes an implicit tag field that records the last written member.
  • Prevents accidental misuse (type-checked).
  • Reading from a member that wasn’t last written → runtime error.

Example:

module tagged_union_example;
  logic [31:0] x;
  typedef union tagged {
    int a;
    byte b;
    bit [15:0] c;
  } data_t;

  data_t d1;

  initial begin
    d1 = tagged a 32'hffff_ffff; // write to 'a'
    x = d1.b; // ERROR - cannot read 'b' when 'a' was last written
  end
endmodule

Error:

Invalid member usage of a tagged union.
Expected tag: 'a', but tag 'b' is used.

Tagged unions enforce safer access by requiring consistent use of the last written member.

Use unpacked unions in testbenches, packed unions in synthesizable RTL, and tagged unions when safety and error-checking are required.

vlsitrainers.com

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top