SystemVerilog Series · SV-02

SystemVerilog Series — SV-02: Literal Values — VLSI Trainers
SystemVerilog Series · SV-02

Literal Values

Integer, logic, real, time, string, array, and structure literals in SystemVerilog — what's new versus Verilog-2001, how sizing and signing rules apply, and practical patterns for every literal type.

💡 Overview & What's New

SystemVerilog extends Verilog-2001's literal value syntax in four important areas. The integer and base rules remain the same, but SystemVerilog adds a compact single-bit fill notation, a proper time literal with a unit suffix, richer string literal handling tied to the new string data type, and entirely new array and structure literals that mirror C initialiser syntax.

Integer & Logic
Verilog rules unchanged plus new unsized single-bit fill forms: '0, '1, 'X, 'Z that replicate to match context width.
🕐
Time Literals
Numeric value followed directly by a unit: 10ns, 0.1us, 100ps. Scaled automatically to the current `timescale precision.
💬
String Literals
Behaviour unchanged for packed-array assignment. New: implicit conversion to the string data type, new escape sequences \v, \f, \a, \xNN.
📄
Array & Struct
C-style braces {} initialise arrays and structs. Replication operator {N{val}} works inside array literals. Struct members can be named: {a:0, b:0.0}.
All Verilog-2001 literal rules still apply. Sized and unsized integers, all four bases (binary, octal, decimal, hex), X and Z values, underscore separators for readability, sign — everything from Verilog-2001 works exactly the same. SystemVerilog only adds new forms; it removes nothing.
Integer
8'hFF 12'b1010_1111 -5 '0   '1   'X   'Z 8'bx
Real
1.5 2.0e10 shortreal'(1.2) 1.0 -3.14
Time
10ns 0.1us 100ps 40ms 1step
String/Array
"hello" "line1\nline2" '{0,1,2} {a:0, b:1.0} {default:0}

Integer & Logic Literals

SystemVerilog inherits all Verilog-2001 integer literal forms unchanged: sized integers with base specifiers, unsized integers, and X/Z values. The one genuine addition is the unsized all-bits fill notation using a leading apostrophe.

Verilog-2001 Forms (Still Valid)

// Sized literals: 'size base value
8'hFF          // 8-bit hex 255
16'hDEAD       // 16-bit hex
12'b1010_1111_0000  // binary with underscore readability
6'o77          // octal
32'd100        // decimal, explicitly sized

// Unsized literals — width from context (at least 32 bits)
100            // decimal unsized
'hFF           // hex unsized

// X and Z values
4'bxxxx        // all bits unknown
4'bz           // all bits high-impedance (z fills)
8'b1x0z        // mixed known/unknown

// Signed literals
-8'sd128       // signed 8-bit value
4'sb1010       // signed binary

New in SystemVerilog: Single-Bit Fill Literals

SystemVerilog adds a compact form using just an apostrophe followed by a single bit value. The value fills all bits of the target expression to that value. In a self-determined context the width is 1 bit; when assigned to a wider type, every bit gets the fill value.

// New SV-only unsized fill literals (apostrophe, no base specifier)
'0   // all bits  0 — fills to match left-hand side width
'1   // all bits  1
'X   // all bits  X  (also lowercase 'x)
'Z   // all bits  Z  (also lowercase 'z)

// Practical examples
logic [7:0] a;
a = '0;         // same as a = 8'b0000_0000
a = '1;         // same as a = 8'b1111_1111 (all ones)
a = 'x;         // same as a = 8'bxxxx_xxxx

logic [31:0] bus;
bus = '0;        // fills 32 zeros — no need to write 32'b0

// In self-determined context: width is 1 bit
logic bit1 = '1; // width=1, value=1
Why '0 and '1 are useful: When writing a parameterised module where the bit-width is a parameter, you cannot write WIDTH'b0 directly. The fill forms '0 and '1 adapt to any width automatically, making them the idiomatic way to reset or set all bits of a variable regardless of its width.

Base Specifiers & Value Characters

Base LetterBaseValid digitsExample
b or BBinary0 1 x X z Z _4'b1010
o or OOctal0–7 x X z Z _6'o77
d or DDecimal0–9 x X z Z _8'd255
h or HHexadecimal0–9 a–f A–F x X z Z _16'hBEEF
Underscore readability tip: Underscores can appear anywhere within the digit portion of a literal and are ignored by the compiler. The convention is to group in fours for binary (16'b1010_1100_0011_1111) or in twos for byte-aligned hex (32'h00FF_AB01). Leading underscores are not allowed.

Sizing & Signing Rules

Truncation (MSB lost — warning issued)

logic [3:0] x;
x = 8'hFF;  // truncates to 4'hF (warning!)
x = 255;    // unsized decimal, truncates (warning)

Zero / sign extension (silent)

logic [7:0] y;
y = 4'b1010; // zero-extends: 8'b0000_1010
logic signed [7:0] z;
z = 4'sb1010;// sign-extends: 8'b1111_1010

🔢 Real Literals

SystemVerilog supports the same real literal formats as Verilog-2001 but adds the shortreal cast. The default type for a real literal is real (equivalent to a C double, 64-bit IEEE 754). The new shortreal type is a 32-bit IEEE 754 float, equivalent to a C float.

Real Literal Forms

// Fixed-point format — default type is real (64-bit double)
1.5         // 1.5
3.14159     // pi
0.001       // leading zero required
-2.0        // negative real

// Scientific (exponent) format
2.5e3       // 2500.0
1.0E-6      // 0.000001
3.0e+10     // 3 * 10^10

// Cast to shortreal (new in SV) — 32-bit float
shortreal'(1.2)    // convert literal to shortreal
shortreal'(3.14)   // precision reduced to 32-bit

// Declaring real and shortreal variables
real      pi    = 3.14159265;
shortreal pi_f = shortreal'(3.14159265); // ~7 decimal digits precision
real vs shortreal: real (64-bit double) gives ~15 decimal digits of precision. shortreal (32-bit float) gives only ~7 digits. For most simulation purposes real is the right choice. Use shortreal only when you need to model a design that itself uses 32-bit floats (e.g. a hardware FPU), or when passing values across the DPI to a C function that takes a C float.

🕐 Time Literals

Time literals are one of the most practical additions in SystemVerilog. Rather than writing a raw number and relying on the current `timescale, you can write a value with an explicit unit suffix directly in the source. The simulator scales the value to the current time unit and rounds to the current time precision automatically.

Time Literal Syntax

// time_literal = number followed immediately by unit (no space)
// Units: fs  ps  ns  us  ms  s  step

10ns       // 10 nanoseconds
0.1ns      // 100 picoseconds (fixed-point ok)
100ps      // 100 picoseconds
40ms       // 40 milliseconds
1s         // 1 second
500fs      // 500 femtoseconds
1step      // one simulation step (smallest time increment)

How Scaling Works

// Example: `timescale 1ns/1ps (time unit = 1ns, precision = 1ps)

10ns  // → stored as 10.000 (10 * 1ns / 1ns = 10 units)
5.5ns // → stored as 5.500 (rounds to 5500 precision steps)
1us   // → stored as 1000 (1us / 1ns = 1000 units)
100ps // → stored as 0.100 (100ps / 1ns = 0.1 units)

// Usage in initial blocks and timing
initial begin
  #10ns  sig = 1;   // delay 10 ns then assert
  #0.5us sig = 0;   // delay 500 ns then deassert
  #1step $display("one simulation step later");
end

// Assigning to a realtime variable
realtime t1 = 2.5ns;
realtime t2 = 0.1us;
When to use time literals vs raw numbers: Time literals make testbenches portable. If you write #10 you are writing “10 time units” — what that means depends entirely on `timescale. If you write #10ns you mean 10 nanoseconds regardless of timescale, and the compiler will scale it for you. This is especially important in package-level code that may be compiled with different timescales.

Time Literal in Module/Interface Instantiation

// When a time literal is used as a parameter value at an instance,
// the time unit of THAT instance applies (not the calling scope).

module top;
  // timescale here is 1ns/1ps
  dut #(.DELAY(5ns)) u1(...); // 5ns scaled to dut's timescale
endmodule

module dut #(parameter realtime DELAY = 1ns);
  // DELAY is always expressed in this module's time unit
endmodule

💬 String Literals

A string literal is a sequence of characters enclosed in double quotes. In Verilog-2001, string literals were only used at the lexical level — treated as packed arrays of 8-bit characters. SystemVerilog keeps that behaviour and adds implicit conversion to the new string data type, which holds variable-length strings without truncation.

Basic Assignment Rules

// ── Assigned to a packed integral type (Verilog-2001 behaviour) ──
byte          c  = "A";          // c = 8'h41  (ASCII 65)
bit [7:0]     b  = "\n";         // b = 8'h0A  (newline)
bit [47:0]    h  = "hello";      // h = 48-bit packed ASCII (5 chars)
bit [31:0]    s  = "hi";         // right-justified: 32'h0000_6869
bit [1:4][7:0] w  = "hello";      // 4 chars: truncated to "ello" (MSB lost)

// ── Assigned to a string variable (SV behaviour) ──────────────
string name = "John Smith";  // arbitrary length, no truncation
string empty = "";           // empty string, len() = 0
string msg;                  // auto-initialised to "" if not specified

// ── Assigned to unpacked byte array (left-justified) ──────────
byte c3 [0:12] = "hello world\n"; // left-justified, extra bytes = 0

Multi-Line String Literals

// A string must fit on one logical line.
// Use backslash continuation to span physical lines:
string msg = "This is a very long message that \
continues on the next line";
// The \ and newline are REMOVED — result is one continuous string

Escape Sequences

SystemVerilog adds four escape sequences to the Verilog-2001 set:

\nNewline (LF)
\tHorizontal tab
\\Backslash
\”Double quote
\NNNOctal ASCII code
\vVertical tab (new)
\fForm feed (new)
\aBell (new)
\xNNHex ASCII (new)
// Using new escape sequences
$write("\x1B[31m");   // ANSI red colour code (hex escape)
$write("\a");         // ring the terminal bell
string s = "col1\tcol2\tcol3\n"; // tab-separated columns

String Literals and the string Type

// Implicit conversion: when at least one operand is type string,
// literal strings are automatically converted.

string a = "hello";
string b = " world";
string c = {a, b};      // "hello world" — string concatenation
string d = {a, "!"};    // "hello!" — literal auto-converts
string e = {3{"abc"}};  // "abcabcabc" — non-const replication OK

// Indexing: returns a byte (ASCII code)
byte ch = a[0];         // 'h' = 8'h68
a[0]    = "H";          // "Hello"

// Casting packed array to string
bit [11:0] bits = 12'ha41;
string s2 = string'(bits);  // or: string s2 = bits;
// s2 = "\x0a\x41" (zero-padded if not multiple of 8)
Packed array vs string type: The key difference is truncation. Assigning "hello world" (11 chars) to a bit [31:0] silently truncates to the rightmost 4 characters. Assigning it to a string variable keeps all 11 characters. For any text you intend to display, compare, or manipulate, always use the string type rather than a packed array.

📄 Array Literals

SystemVerilog introduces array literals using braces {}, syntactically similar to C array initialisers. The key difference from C is that the nesting of braces must match the number of array dimensions. Replication using {N{val}} is allowed within array literals.

Basic Array Literal Syntax

// 1-D array literal — values listed in order
int arr1[4] = '{10, 20, 30, 40};   // arr1[0]=10, arr1[1]=20, ...

// 2-D array literal — outer braces for each row
int n[1:2][1:3] = '{'{0,1,2}, '{3,4,5}};
// row 1: {0,1,2}    row 2: {3,4,5}

// The apostrophe prefix ' on the outer brace signals array literal
// (vs a concatenation expression)

Replication in Array Literals

// {N{val}} fills N elements with val — replication operator
int zeros[8]  = '{8{0}};       // all eight elements = 0
int threes[6] = '{6{3}};       // all six elements = 3

// Mixed: some explicit, rest with replication
int n2[1:2][1:3] = '{'{0,1,2}, '{3{4}}};
// row 2 = {4,4,4}

// Nested replication: outer and inner both replicate
int m[1:2][1:3] = '{2{'{3{4, 5}}}};
// expands: '{2{'{4,5,4,5,4,5}}} = '{'{{4,5,4,5,4,5},{4,5,4,5,4,5}}}
Inner braces of a replication are removed: When the replication operator is applied inside an array literal, the inner braces of the replicated group are stripped. So '{3{4,5}} is not {'{4,5}, '{4,5}, '{4,5}} but rather '{4,5,4,5,4,5} — the inner {4,5} contributes its elements directly into the enclosing array dimension.

Explicit Type with Cast

// When the type cannot be inferred from context, provide a cast
typedef int triple [1:3];
$display(triple'{0,1,2});          // cast specifies the array type

// Using index-value pairs (associative literal style)
int b[1:4];
b = '{1:1, default:0}; // index 1 = 1, everything else = 0

// Using type as key (sets all elements of that type)
b = '{int:5, default:0}; // all int elements = 5
Fig 1 — Replication expansion trace for a 2-D array literal
Statement:  int v[1:0][2:0] = '{2{'{a, '{2{b,c}}}}};

Expand inner repetition:  '{2{b,c}} = '{b,c,b,c}
After inner:              '{2{'{a, b,c,b,c}}}
Expand outer repetition:  = '{'{a,b,c,b,c},  '{a,b,c,b,c}}
Final:
  v[1][0]=a  v[1][1]=b  v[1][2]=c
  v[0][0]=a  v[0][1]=b  v[0][2]=c
  (Note: 2*5 elements but array has only 2*3=6 slots — only first 3 of each row assigned)

📌 Structure Literals

Structure literals initialise a struct in a single expression, again using brace syntax. They must have a type — either inferred from the assignment context or provided via a cast. Four notation styles are supported: positional, member-name, type-default, and default catch-all.

Positional Style (Like C)

typedef struct { int a; shortreal b; } ab_t;
ab_t c;

// Type inferred from left-hand context (c is ab_t)
c = '{0, 0.0};             // c.a=0, c.b=0.0
c = '{42, 3.14};           // c.a=42, c.b=3.14

// Array of structs — nested braces match structure
ab_t arr[1:0] = '{'{1, 1.0}, '{2, 2.0}};
// arr[1] = {a:1, b:1.0}     arr[0] = {a:2, b:2.0}

// INVALID (C flat style not allowed in SV):
// ab_t arr[1:0] = '{1, 1.0, 2, 2.0};   // error!

Member-Name Style

// Name each field explicitly — order does not matter
c = '{a:0, b:0.0};          // explicit field names
c = '{b:3.14, a:10};       // order can differ from declaration

Type-Default & Catch-All Default

// default: sets ALL unspecified fields to that value
c = '{default:0};            // c.a=0, c.b=0.0 (all fields zeroed)

// Type-specific default: sets all fields of a given type
ab_t d = ab_t'{int:1, shortreal:1.0};
// All int fields = 1, all shortreal fields = 1.0

// Combined: named fields + default for the rest
typedef struct { int x, y, z; } point_t;
point_t p = '{x:5, default:0};  // x=5, y=0, z=0

Replication Within Struct Literals

// Replicate the same value into all members of the same count
typedef struct { int X,Y,Z; } xyz_t;
xyz_t pt = '{3{1}};            // X=1, Y=1, Z=1 (3 fields, all 1)

// Nested struct + array
typedef struct { int a; int b[4]; } ab_arr_t;
int av=1, bv=2, cv=3;

ab_arr_t v1[1:0][2:0];
v1 = '{2{'{3{'{av, '{2{bv,cv}}}}}}};
Struct literal vs struct port connection: Struct literals only appear on the right-hand side of assignments and in parameter values. You cannot use a struct literal as a port connection expression directly. To pass a struct to a module port, declare a struct variable, initialise it with a literal, then connect the variable.

📋 Quick Reference Summary

The table below collects every literal form covered in this article. Entries marked SV new do not exist in Verilog-2001.

Literal Type Example Notes
Sized binary 8'b1010_1111 Verilog-2001. Underscore ignored.
Sized hex 16'hDEAD Verilog-2001.
X/Z fill 8'bx, 4'bz Verilog-2001. X or Z replicates across all bits.
‘0 ‘1 ‘X ‘Z '0, '1, 'x, 'z SV new. Fills all bits of target with that value.
Real (fixed) 3.14, 1.0 Verilog-2001. Default type is real (64-bit).
Real (exponent) 2.5e3, 1.0E-6 Verilog-2001.
shortreal cast shortreal'(1.2) SV new. Converts literal to 32-bit float.
Time literal 10ns, 0.5us, 1step SV new. Units: fs ps ns us ms s step. Auto-scaled.
String literal "hello" Verilog-2001. Right-justified when assigned to packed type.
Hex escape "\x41" SV new. Also \v, \f, \a.
Array literal '{10,20,30}, '{3{0}} SV new. Apostrophe prefix. Braces mirror dimensions.
Array with keys '{1:1, default:0} SV new. Index or type as key, default catch-all.
Struct literal (positional) '{42, 3.14} SV new. Type from context or cast required.
Struct literal (named) '{a:42, b:3.14} SV new. Field order may differ from declaration.
Struct default '{default:0} SV new. Sets all fields to 0.
What comes next: With literals covered, the next article looks at Data Types in full — the complete SV type system including all integer types, logic, bit, string, chandle, enum, struct, and union.

Leave a Comment

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

Scroll to Top