Verilog has no dedicated text type - storing something like a test name or a log message means packing ASCII characters into a fixed-width reg vector and hoping it's wide enough. SystemVerilog fixes this with a real string data type: dynamically sized, easy to compare and slice, and built specifically for the kind of text handling a testbench needs constantly.

8 min read | Beginner Level

What You'll Learn

  • What the string data type is and how it differs from packing characters into a reg
  • The operators and built-in methods available on string variables
  • Why string is verification-only, unlike the fixed-width vector workaround
  • How to convert between strings and numeric types

What is a SystemVerilog string ?

The string data type is an ordered collection of characters. The length of a string variable is the number of characters it holds, which can change dynamically over the course of a simulation. A string variable doesn't behave the same way as a string literal, and no truncation occurs when you use the string type.

Syntax


string  variable_name [= initial_value];

variable_name is a valid identifier, and the optional initial_value can be a string literal, the value "" for an empty string, or a string-typed expression. If no initial value is given at declaration, the variable defaults to "", an empty string.

SystemVerilog String Example


module tb;
  // Declare a string variable called "dialog" to store string literals
  // Initialize the variable to "Hello!"
  string   dialog = "Hello!";  

  initial begin
    // Display the string using %s string format
    $display ("%s", dialog);
  
    // Iterate through the string variable to identify individual characters and print
    foreach (dialog[i]) begin
      $display ("%s", dialog[i]);
    end
  end
endmodule
Output
ncsim> run
Hello!
H
e
l
l
o
!
ncsim: *W,RNQUIE: Simulation is complete.

How are strings represented in Verilog ?

A single ASCII character requires 8 bits (1 byte), so storing a string in plain Verilog needs as many bytes as there are characters.

Click here to learn about Verilog Arrays


reg  [16*8-1:0] 	my_string;           // Can store 16 characters

my_string = "How are you";              // 5 zeros are padded from MSB, and 11 char are stored
my_string = "How are you doing?";       // 18 characters; my_string will get "w are you doing?"

Design vs. Verification: A fixed-width reg vector like my_string above is synthesizable - it maps directly to hardware bits. The string data type is not. It's a verification-only construct that exists purely for testbench code and can never appear in synthesizable RTL.

Quick Check

Q: Why does assigning "How are you doing?" (18 characters) to a 16-character-wide my_string result in "w are you doing?" instead of an error?

Show Answer

A fixed-width vector can't grow to fit the string, so the assignment silently keeps only the rightmost 16 characters and drops the first 2 ("H" and "o") from the front. This kind of silent truncation is exactly what the string type avoids.

String Operators

CategoryOperatorSemantics
EqualityStr1 == Str2Returns 1 if the two strings are equal and 0 if they are not
InequalityStr1 != Str2Returns 1 if the two strings are not equal and 0 if they are
ComparisonStr1 < Str2, Str1 <= Str2, Str1 > Str2, Str1 >= Str2Returns 1 if the corresponding condition is true and 0 if false
Concatenation{Str1, Str2, ..., StrN}All strings are concatenated into one resultant string
Replication{multiplier{Str}}Replicates the string N times, where N is the multiplier
IndexingStr[index]Returns a byte - the ASCII code at the given index. Returns 0 if the index is out of range
MethodsStr.method([args])The dot (.) operator is used to call string functions

Example


module tb;
  string firstname = "Joey";
  string lastname  = "Tribbiani";
  
  initial begin
    // String Equality : Check if firstname equals or not equals lastname
    if (firstname == lastname)
      $display ("firstname=%s is EQUAL to lastname=%s", firstname, lastname);
  
    if (firstname != lastname)
      $display ("firstname=%s is NOT EQUAL to lastname=%s", firstname, lastname);
  
    // String comparison : "<" compares lexicographically by ASCII value, not by length
    if (firstname < lastname)
      $display ("firstname=%s is LESS THAN lastname=%s", firstname, lastname);
  
    // String comparison : ">" compares lexicographically by ASCII value, not by length
    if (firstname > lastname)
      $display ("firstname=%s is GREATER THAN lastname=%s", firstname, lastname);
  
    // String concatenation : Join first and last names into a single string
    $display ("Full Name = %s", {firstname, " ", lastname});
  
    // String Replication
    $display ("%s", {3{firstname}});
  
    // String Indexing : Get the ASCII character at index number 2 of both first and last names
    $display ("firstname[2]=%s lastname[2]=%s", firstname[2], lastname[2]);
  
  end
endmodule
Output
ncsim> run
firstname=Joey is NOT EQUAL to lastname=Tribbiani
firstname=Joey is LESS THAN lastname=Tribbiani
Full Name = Joey Tribbiani
JoeyJoeyJoey
firstname[2]=e lastname[2]=i
ncsim: *W,RNQUIE: Simulation is complete.

String comparison is lexicographic, based on ASCII values - "Joey" < "Tribbiani" because 'J' (ASCII 74) comes before 'T' (ASCII 84), the same way you'd compare words alphabetically.

Basic String Methods

SystemVerilog also includes a number of special methods to work with strings, using built-in method notation.

UsageDefinitionComments
str.len()function int len()Returns the number of characters in the string
str.putc()function void putc (int i, byte c);Replaces the ith character in the string with the given character
str.getc()function byte getc (int i);Returns the ASCII code of the ith character in str
str.tolower()function string tolower();Returns a string with characters in str converted to lowercase
str.compare(s)function int compare (string s);Compares str and s, as in the ANSI C strcmp function
str.icompare(s)function int icompare (string s);Compares str and s, ignoring case
str.substr (i, j)function string substr (int i, int j);Returns a new string formed by the characters in position i through j of str

Example


module tb;
   string str = "Hello World!";
  
   initial begin
   	  string tmp;

	  // Print length of string "str"
      $display ("str.len() = %0d", str.len());

      // Assign to tmp variable and put char "d" at index 3
      tmp = str;
      tmp.putc (3,"d");
      $display ("str.putc(3, d) = %s", tmp);

      // Get the character at index 2
      $display ("str.getc(2) = %s (%0d)", str.getc(2), str.getc(2));

      // Convert all characters to lower case
      $display ("str.tolower() = %s", str.tolower());

      // Comparison
      tmp = "Hello World!";
      $display ("[tmp,str are same] str.compare(tmp) = %0d", str.compare(tmp));
      tmp = "How are you ?";
      $display ("[tmp,str are diff] str.compare(tmp) = %0d", str.compare(tmp));

      // Ignore case comparison
      tmp = "hello world!";
      $display ("[tmp is in lowercase] str.icompare(tmp) = %0d", str.icompare(tmp));
      tmp = "Hello World!";
      $display ("[tmp,str are same] str.compare(tmp) = %0d", str.compare(tmp));

      // Extract new string from i to j
      $display ("str.substr(4,8) = %s", str.substr (4,8));

   end
endmodule
Output
str.len() = 12  
str.putc(3, d) = Heldo World!
str.getc(2) = l (108)
str.tolower() = hello world!
[tmp,str are same] str.compare(tmp) = 0
[tmp,str are diff] str.compare(tmp) = -1
[tmp is in lowercase] str.icompare(tmp) = 0
[tmp,str are same] str.compare(tmp) = 0
str.substr(4,8) = o Wor

Common Mistake: str.compare() mirrors ANSI C's strcmp - it returns 0 for equal strings and a nonzero value otherwise, not a boolean 1/0. Don't treat a nonzero result as "true" the way you might with ==.

String Conversion Methods

MethodDefinitionDescription
str.atoi()function integer atoi();Returns the integer corresponding to the ASCII decimal representation in str
str.atohex()function integer atohex();Interprets the string as hexadecimal
str.atooct()function integer atooct();Interprets the string as octal
str.atobin()function integer atobin();Interprets the string as binary
str.atoreal()function real atoreal();Returns the real number corresponding to the ASCII decimal representation in str
str.itoa(i)function void itoa (integer i);Stores the ASCII decimal representation of i into str
str.hextoa(i)function void hextoa (integer i);Stores the ASCII hexadecimal representation of i into str
str.octtoa(i)function void octtoa (integer i);Stores the ASCII octal representation of i into str
str.bintoa(i)function void bintoa (integer i);Stores the ASCII binary representation of i into str
str.realtoa(r)function void realtoa (real r);Stores the ASCII real representation of r into str

Where Are Strings Used?

Testbenches use string constantly - test names passed via +UVM_TESTNAME, log and error messages built with $sformatf, config file paths, and comparing a DUT's ASCII output against an expected string in a reference model. None of this could be done cleanly with a fixed-width reg vector.

Common Beginner Mistakes

Mistake #1: Assuming string can be used in synthesizable RTL.

string is verification-only. If you need text-like storage in a real design, you're back to a fixed-width reg/logic vector, with the truncation behavior shown earlier.

Mistake #2: Off-by-one errors with string indexing.

Like arrays, string indexing is 0-based. firstname[2] is the third character, not the second - easy to miscount when a string is short.

Mistake #3: Treating str.compare()'s return value as a boolean.

It returns 0 for equality and a nonzero value otherwise, matching ANSI C's strcmp - not a straightforward 1-for-true result.

Practice Exercise

Challenge: Extract a Substring

Given string str = "SystemVerilog";, write a single line using str.substr() that extracts just the word "Verilog".

Hint

Index positions are 0-based. Count characters starting from 0 to find where "Verilog" begins and ends within "SystemVerilog".

Solution
str.substr(6,12)
  

"SystemVerilog" has "System" occupying indices 0-5, so "Verilog" starts at index 6 and ends at index 12 (the last character, "g").

Summary

In this tutorial, you learned:

  • The string data type is a dynamically-sized, verification-only text type - unlike a fixed-width reg vector, it never silently truncates
  • Strings support equality, comparison, concatenation, replication, and indexing operators
  • Built-in methods like len(), putc(), getc(), tolower(), compare(), and substr() cover most everyday string manipulation
  • Conversion methods like atoi() and itoa() move data between string and numeric representations
Did you find what you were looking for?

Quiz

Test Your Knowledge

1 of 5 Score: 0 / 5