Featured post

Top 5 books to refer for a VHDL beginner

VHDL (VHSIC-HDL, Very High-Speed Integrated Circuit Hardware Description Language) is a hardware description language used in electronic des...

Friday, 30 January 2015

SystemVerilog Linked Lists

Linked lists and arrays are similar since they both store collections of data. The terminology is that arrays and linked lists store "elements" on behalf of "client" code. The specific type of element is not important since essentially the same structure works to store elements of any type. One way to think about linked lists is to look at how arrays work and think about alternate approaches.

The List package implements a classic list data-structure, and is analogous to the STL (Standard Template Library) List container that is popular with C++ programmers. The container is defined as a parametrized class, meaning that it can be customized to hold data of any type. The List package supports lists of any arbitrary predefined type, such as integer, string, or class object. First declare the Linked list type and then take instances of it. SystemVerilog has many methods to operate on these instances. 

A double linked list is a chain of data structures called nodes. Each node has 3 members, one points to the next item or points to a null value if it is last node, one points to the previous item or points to a null value if it is first node and other has the data. 

Difference between Queue and Linked list:

A queue can pretty much do anything a linked listed can do, and more efficiently. The only case where a linked list might be more efficient is when you need to join two lists together, or insert one list in the middle of another list. A queue is very efficient for adding one element at a time.

Previous : SystemVerilog Queue
Next :

Thursday, 29 January 2015

SystemVerilog Queue

Queue is a variable size, ordered collection of homogeneous elements which can grow and shrink. The size of a queue is variable similar to a dynamic array, but a queue may be empty with no element and it is still a valid data structure. Queues can be used as LIFO (Last In First Out) Buffer or FIFO (First In First Out) type of buffers.

Syntax:
A queue is declared simply by putting a $ as the size of an array.
integer my_q[$];

You can initialize a queue at the place of its variable declaration:
integer my_q[$] = {1, 3, 5};

You can also set up an upper limit of index for a queue (a bounded queue):
integer my_q[$:127];

Since index of an array can only be non-negative, the maximum number of elements for the queue in the above case is 128 (i.e., 0 through 127).

Each element in the queue is identified by an ordinal number that represents its position within the queue, with 0 representing the first element and $ represents the last element.

Bounded Queues
Size of a queue can be limited by giving the last index (i.e. upper bound) as follows

int queueA[$:99]; // A queue whose maximum size is 100 integers 

These are called bounded queues.It will not have an element whose index is higher than the queue’s declared upper bound. Operators on bounded queue can be applied exactly the same way as unbounded queues, except that, result should fall in the upper bound limit.

The size of the queue is variable similar to dynamic array but queue may be empty with zero element and still its a valid data structure.

Queues and dynamic arrays have the same assignment and argument passing semantics. Also, queues support the same operations that can be performed on unpacked arrays and use the same operators and rules except as defined below:


// SystemVerilog Queue Operations
int q[$] = { 2, 4, 8 }; 
int p[$]; 
int e, pos; 
e = q[0]; // read the first (leftmost) item 
e = q[$]; // read the last (rightmost) item 
q[0] = e; // write the first item 
p = q; // read and write entire queue (copy) 
q = { q, 6 }; // insert '6' at the end (append 6) 
q = { e, q }; // insert 'e' at the beginning (prepend e) 
q = q[1:$]; // delete the first (leftmost) item 
q = q[0:$-1]; // delete the last (rightmost) item 
q = q[1:$-1]; // delete the first and last items 
q = {}; // clear the queue (delete all items) 
q = { q[0:pos-1], e, q[pos,$] }; // insert 'e' at position pos 
q = { q[0:pos], e, q[pos+1,$] }; // insert 'e' after position pos 

Queue Methods:

Queues also provides several built-in methods to access/modify queue. Below we have list down all such methods.
  • The size() method returns the number of items in the queue. If the queue is empty, it returns 0. 
  • The insert() method inserts the given item at the specified index position. 
  • The delete() method deletes the item at the specified index. 
  • The pop_front() method removes and returns the first element of the queue. 
  • The pop_back() method removes and returns the last element of the queue. 
  • The push_front() method inserts the given element at the front of the queue. 
  • The push_back() method inserts the given element at the end of the queue. 

// SystemVerilog Queue Methods
module queue_methods();

// Queue is declated with $ in array size
  integer queue[$] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
integer i;

initial begin
  $display ("Initial elements in the queue");
  print_queue;
  // Insert new element at begin of queue
  queue = {11, queue};
  $display ("new element added using concatenation");
  print_queue;
  // Insert using method at beginning
  queue.push_front(12);
  $display ("new element added using push_front");
  print_queue;
  // Insert using method at end
  queue.push_back(12);
  $display ("new element added using push_back");
  print_queue;
  // Using insert to insert, here 6 is index
  // and 13 is value
  queue.insert(6,13);
  $display ("new element added using insert(index,value)");
  print_queue;
  // get first queue element method at begining
  i = queue.pop_front();
  $display ("element poped using pop_front");
  print_queue;
  // get last queue element method at end
  i = queue.pop_back();
  $display ("element poped using pop_end");
  print_queue;
  // Use delete method to delete element at index 4 in queue
  queue.delete(10);
  $display ("deleted element at index 10");
  print_queue;
  #1 $finish;
end

  // Method to print queue
task print_queue;
  integer i;
  $write("Queue contains ");
  for (i = 0; i < queue.size(); i ++) begin
    $write (" %g", queue[i]);
  end
  $write("\n");
endtask

endmodule

Results:
Initial elements in the queue
Queue contains  0 1 2 3 4 5 6 7 8 9 10
new element added using concatenation
Queue contains  11 0 1 2 3 4 5 6 7 8 9 10
new element added using push_front
Queue contains  12 11 0 1 2 3 4 5 6 7 8 9 10
new element added using push_back
Queue contains  12 11 0 1 2 3 4 5 6 7 8 9 10 12
new element added using insert(index,value)
Queue contains  12 11 0 1 2 3 13 4 5 6 7 8 9 10 12
element poped using pop_front
Queue contains  11 0 1 2 3 13 4 5 6 7 8 9 10 12
element poped using pop_end
Queue contains  11 0 1 2 3 13 4 5 6 7 8 9 10
deleted element at index 10
Queue contains  11 0 1 2 3 13 4 5 6 7 9 10

Try simulation yourself here

Hope you get the idea how to declare and use the SystemVerilog Queues. Next we will learn about Linked lists, array methods and we will compare the array types in SystemVerilog.

Previous : SystemVerilog Associative Arrays
Next : SystemVerilog Linked Lists

Wednesday, 28 January 2015

SystemVerilog Dynamic Arrays

In this SystemVerilog Tutorial so far we have seen basic array type i.e. SystemVerilog Fixed arrays, as its size is set at compile time. 

Now what if you don't know the size of array until run-time? 

You may wish to set the size of array run-time and wish to change the size dynamically during run time. 

For example an IP packet varies length from one packet to other packet. In verilog, for creating such packet, array with maximum packet size is declared and only the number of elements which are require for small packets are used and unused elements are waste of memory. 

SystemVerilog overcomes this problem and provides us dynamic arrays. 

Following are the features of SystemVerilog Dynamic arrays :

1. Size of dynamic array can be set at runtime.
2. Previously set size of the dynamic array can be changed runtime without loosing the previous contents.

Hence, dynamic array is unpacked array whose size can be allocated run time along with the option to resize.

Declaration of SystemVerilog Dynamic Arrays :
Dynamic arrays are declared with empty word subscript [ ].


1
2
3
integer dyn_array_1[];
integer dyn_array_1[];
integer multi_dime_dyn_array[][]; 

Allocating size of Dynamic Array :
As seen above the dynamic array is declared with empty word subscript [ ], which means you do not wish to allocate size at compile time, instead, you specify the size at runtime.

The dynamic arrays used builtin function new[ ] to allocate the storage and initialize the newly allocated array.


// SystemVerilog Dynamic arrays
module dyn_arr;
  int dyn[], d2[];             // Empty dynamic arrays
  initial begin
    dyn = new[5];              // Allocate 5 elements
    foreach (dyn[j]) begin
      dyn[j] = j;              // Initialize the elements
      $display("j = %0d dyn = %0d",j,dyn[j]); 
    end
    $display("Copy the dynamic array");
    
    // Copy a dynamic array
    d2 = dyn;
    $display("dyn[0] = %0d d2[0] = %0d",dyn[0],d2[0]);
    
    $display("Modify contents of copy");
    // Modify the copy
    d2[0] = 5;                 
    $display("dyn[0] = %0d d2[0] = %0d",dyn[0],d2[0]);
    
    $display ("Extend the array length and check previous content");
    // Expand and copy
    dyn = new[20](dyn);
    $display("dyn[4] = %0d", dyn[4]);
    
    $display ("Extend the array length and check previous content");
    // Allocate 100 new integers. Old values will lost
    dyn = new[100];    
    $display ("dyn[4] = %0d", dyn[4]);
    // Delete all elements
    dyn.delete;   
  end
endmodule

Simulation result :
j = 0 dyn = 0
j = 1 dyn = 1
j = 2 dyn = 2
j = 3 dyn = 3
j = 4 dyn = 4
Copy the dynamic array
dyn[0] = 0 d2[0] = 0
Modify contents of copy
dyn[0] = 0 d2[0] = 5
Extend the array length and check previous content
dyn[4] = 4
Extend the array length and check previous content
dyn[4] = 0

Run Simulation

Methods associated with Dynamic arrays :

.size() : Returns the size of dynamic array. We can also use system task $size() method instead of .size() method.

.delete() : SystemVerilog also provides .delete() method clears all the elements yielding an empty array (zero size).


Previous : Fixed Size Arrays
Next : Associative Arrays

Tuesday, 27 January 2015

SystemVerilog Fixed Arrays

Let's talk about most used data type - Arrays. An array is a collection of data elements having the same type. Individual elements are accessed by index using a consecutive range of integers. However there are some type of arrays allows to access individual elements using non consecutive values of any data types. SystemVerilog Arrays offers several flavors of arrays beyond the single-dimension, fixed-size Verilog-1995 arrays. Many enhancement have been made to these classic arrays. Arrays can be classified as
  • Fixed Arrays or Fixed-Sized Arrays (sometimes known as static arrays) whose size cannot be changed once declared. 
  • Dynamic arrays which can be resized run time.

Declaring and initializing fixed-size array
Verilog requires that the low and high array limits must be given in the declaration. Almost all arrays use a low index of 0, so SystemVerilog lets you use the shortcut of just giving the array size, similar to C:

Example 1 : Declaring and using SystemVerilog fixed-sized arrays

int data[0:15];  // 16 ints [0]..[15]
int address[16]; // 16 ints [0]..[15]
address[15] = 1; // Set last array element


You can create multidimensional fixed-size arrays by specifying the dimensions after the variable name. This makes an unpacked array; we will take a look for packed arrays later. The following example creates several two-dimensional arrays of integers, 8 entries by 4, and sets the last entry to 1.

Example 2 : Declaring and using multidimensional fixed-sized array

int array2 [0:7][0:3]; // Verbose declaration
int array3 [8][4];     // Compact declaration
array2[7][3] = 1;      // Set last array element

SystemVerilog stores each element on a longword (32-bit) boundary. So a byte, shortint, and int are all stored in a single longword, while a longint is stored in two longwords. (Simulators frequently store four-state types such as logic and integer in two or more longwords.)

Example 3 : SystemVerilog Unpacked Array Declaration

bit [7:0] unpacked_array[3]; // Unpacked array

Unpacked array declared above is stored as shown below


You can initialize an array using an array literal that is an apostrophe and curly braces. Using this array literal you can set some or all elements at once. Also its easy to replicate values by putting a count before the curly braces. Below we have shown example to initialize the systemverilog fixed arrays

Example 4 : Initialize SystemVerilog Array

int ascend[4] = {0,1,2,3}; // Initialize 4 elements
int decend[5];
int array[2][3] = {{0,1,2}, {3,4,5}};
descend = {4,3,2,1,0}; // Set 5 elements
descend[0:2] = {5,6,7}; // Set first 3 elements
ascend = {4{8}}; // Four values of 8

Basic Array Operations
The most common way to manipulate an array is with a for or foreach loop. In below example the variable "i" is declared local to the for loop. To get the size of array we can use system function $size that returns the size of array. For foreach loop statement, you specify the array name and an index in square brackets and Systemverilog automatically steps through all the elements of the array. The index variable is local to the loop.

Example 5 : Access the arrays using for and foreach loops

// SystemVerilog For and Foreach loop to access arrays
module array_loops;
  initial begin
    bit [31:0] src[5], dst[5];
    for (int i=0; i<$size(src); i++) begin
      src[i] = i;
      $display("src[%0d] = %0d", i, src[i]); 
    end
    foreach (dst[j]) begin
      dst[j] = src[j] * 2; // dst doubles src values
      $display("dst[%0d] = %0d", j, dst[j]); 
    end
  end
endmodule

Simulation Results:
src[0] = 0
src[1] = 1
src[2] = 2
src[3] = 3
src[4] = 4
dst[0] = 0
dst[1] = 2
dst[2] = 4
dst[3] = 6
dst[4] = 8

Now in below example note that for SystemVerilog multidimensional arrays the syntax is not as you might expected. Instead of listing each subscript in separate square brackets – [i][j] – they are combined with a comma – [i,j].

Example 6: SystemVerilog Accessing Multidimensional Arrays using Foreach loop


// SystemVerilog For and Foreach loop to access arrays
module array_loops;
  int md[2][3];
  initial begin
    $display("Initial value:");
    foreach (md[i,j]) // Yes, this is the right syntax
      $display("md[%0d][%0d] = %0d", i, j, md[i][j]);
    $display("New value:");
    md = '{{9, 8, 7}, {default:5}}; // Replicate last 3 values
    foreach (md[i,j]) // Yes, this is the right syntax
      $display("md[%0d][%0d] = %0d", i, j, md[i][j]);
    end
endmodule

Simulation Results:
Initial value:
md[0][0] = 0
md[0][1] = 0
md[0][2] = 0
md[1][0] = 0
md[1][1] = 0
md[1][2] = 0
New value:
md[0][0] = 9
md[0][1] = 8
md[0][2] = 7
md[1][0] = 5
md[1][1] = 5
md[1][2] = 5

Packed arrays :


Before knowing what exactly packed and unpacked arrays are, lets also see how you can know which array is what, just by their declaration. 

Packed arrays have an object name comes before size declaration. 
For example: bit [3][7] a;

As specified previously unpacked array have an object name comes after size declaration. 
For example: bit a[3];

For some data types, you may want both to access the entire value and also divide it into smaller elements. For example, you may have a 32-bit register that sometimes you want to treat as four 8-bit values and at other times as a single, unsigned value. A SystemVerilog packed array is treated as both an array and a single value. Packed arrays can be made of only the single bit data types (bit, logic, reg) and recursively other packed arrays and packed structures. It is stored as a contiguous set of bits with no unused space, unlike an unpacked array.

Packed Array Example 
The packed bit and word dimensions are specified as part of the type, before the variable name. These dimensions must be specified in the [lo:hi] format. The variable bytes is a packed array of four bytes, which are stored in a single longword.


1
bit [3:0] [7:0] bytes; // 4 bytes packed into 32-bits

Packed Array Layout



You can mix packed and unpacked dimensions. You may want to make an array that represents a memory that can be accessed as bits, bytes, or long words. In Example 2-14, barray is an unpacked array of three packed elements.


Declaration of mixed packed and unpacked arrays


1
bit [3:0] [7:0] barray [3]; // Packed: 3x32-bit

The variable bytes is a packed array of four bytes, which are stored in a single longword. barray is an array of three of these elements.


With a single subscript, you get a longword of data, barray[2]. With two subscripts, you get a byte of data, barray[0][3]. With three subscripts, you can access a single bit, barray[0][1][6]. Note that because one dimension is specified after the name, barray[3], that dimension is unpacked, so you always need to use at least one subscript.

Choosing Between Packed and Unpacked Array

Which should you choose — packed or unpacked array?
A packed array is handy if you need to convert to and from scalars. For example, you might need to reference a memory as a byte or as a longword. The above array barray can handle this requirement. Only fixed-size arrays can be packed, not dynamic arrays, associative arrays, or queues.

If you need to wait for a change in an array, you have to use a packed array. Perhaps your testbench might need to wake up when a memory changes value, so you want to use the @ operator. But this is only legal with scalar values and packed arrays. Using the earlier examples, you can block on the variable lw, and barray[0], but not the entire array barray unless you expand it: @(barray[0] or barray[1] or barray[2]).

Previous : Net Type
Next : Dynamic Arrays

Monday, 26 January 2015

SystemVerilog Net Type

In Verilog, Net data types are used to model physical connections. They do not store values (there is only one exception - trireg, which stores a previously assigned value). The net data types have the value of their drivers. If a net variable has no driver, then it has a high-impedance value (z).

Verilog allows you to use nets without defining them, a feature called implicit nets. This shortcut helps net-listing tools and lazy designers, but is guaranteed to cause problems if you ever
misspell a net name in your SystemVerilog code. The solution is to disable this language feature with the Verilog-2001 compile directive: ‘default_nettype none. Put this (without a period) before the first module in your Verilog code. Any implicit net will cause a compilation error.

Previous : SystemVerilog Strings
Next : Fixed Size Array

Sunday, 25 January 2015

SystemVerilog Strings

String data type is used for storing strings, the size is dynamic and string data types come with build in methods. If you have ever tried to use a Verilog reg variable to hold a string of characters, your suffering is over with this post. The SystemVerilog string type holds variable-length strings. String literals are packed arrays of a width that is a multiple of 8 bits which hold ASCII values i.e. an individual character is of type byte. The elements of a string of length N are numbered 0 to N-1. Note that, unlike C, there is no null character at the end of a string, and any attempt to use the character “\0” is ignored.


string StringName = "VLSI Encyclopedia";

Strings use dynamic memory allocation, so you do not have to worry about running out of space to store the string. Example 1 shows various string operations.

Below is the list of string methods :
  • str.len() returns the length of the string, i.e., the number of characters in the string. 
  • str.putc(i, c) replaces the ith character in str with the given integral value. 
  • str.getc(i) returns the ASCII code of the ith character in str. 
  • str.toupper() returns a string with characters in str converted to uppercase. 
  • str.tolower() returns a string with characters in str converted to lowercase. 
  • str.compare(s) compares str and s, and return value. This comparison is case sensitive. 
  • str.icompare(s) compares str and s, and return value .This comparison is case insensitive. 
  • str.substr(i, j) returns a new string that is a substring formed by index i through j of str. 
  • str.atoi() returns the integer corresponding to the ASCII decimal representation in str. 
  • str.atoreal() returns the real number corresponding to the ASCII decimal representation in str. 
  • str.itoa(i) stores the ASCII decimal representation of i into str (inverse of atoi). 
  • str.hextoa(i) stores the ASCII hexadecimal representation of i into str (inverse of atohex). 
  • str.bintoa(i) stores the ASCII binary representation of i into str (inverse of atobin). 
  • str.realtoa(r) stores the ASCII real representation of r into str (inverse of atoreal)

Example 1: SystemVerilog String Methods


// SystemVerilog Strings
module str; 
  string S1; 
  string S2; 
  initial begin 
    S1 = "VLSI "; 
    S2 = "Encyclopedia"; 
    $display(" %d ",S1.len() ); 
    $display(" %s ",S2.getc(5) ); 
    $display(" %s ",S1.tolower); 
    $display(" %s ",S2.toupper); 
    $display(" %d ",S2.compare(S1) ); 
    $display(" %d ",S1.compare("VLSI") ); 
    $display(" %s ",S1.substr(2,3) ); S1 = "111"; 
    $display(" %d ",S1.atoi() ); 
  end 
endmodule 

Simulation Result :

 5
 l
 vlsi
 ENCYCLOPEDIA
 -17
 1
 SI
 111

Pattern Matching of SystemVerilog Strings
In below example we have used a method to match the strings in SystemVerilog.

Example 2 : Pattern matching


// SystemVerilog String Pattern Matching
 
program main; 
  string S1,S2; 
  initial begin 
    S1 = "String matching in SystemVerilog"; 
    S2 = "String"; 
    if(match(S1,S2)) 
      $display(" S2 : %s : found in :%s:",S2,S1); 

    S2 = "SystemVerilog"; 
    if(match(S1,S2)) 
      $display(" S2 : %s : found in :%s:",S2,S1); 

    S2 = "String matching"; 
    if(match(S1,S2)) 
      $display(" S2 : %s : found in :%s:",S2,S1); 

    S2 = "matching in "; 
    if(match(S1,S2)) 
      $display(" S2 : %s : found in :%s:",S2,S1); 

    S2 = "String matching in SystemVerilog"; 
    if(match(S1,S2)) 
      $display(" S2 : %s : found in :%s:",S2,S1); 
  end 
endprogram

function match(string s1,s2); 
  int len1,len2; 
  len1 = s1.len(); 
  len2 = s2.len(); 
  match = 0 ; 
  if( len2 > len1 ) 
    return 0; 
  for(int i = 0;i < len1 - len2 + 1; i ++) 
    if( s1.substr(i,i+len2 -1) == s2) 
  return 1; 
endfunction

Simulation Results:
 S2 : String : found in :String matching in SystemVerilog:
 S2 : SystemVerilog : found in :String matching in SystemVerilog:
 S2 : String matching : found in :String matching in SystemVerilog:
 S2 : matching in  : found in :String matching in SystemVerilog:
 S2 : String matching in SystemVerilog : found in :String matching in SystemVerilog:

SystemVerilog operations
There are variety of operations associated with SystemVerilog strings that you can perform to manipulate the  combination of string variables and string literals. Below are the basic operation that can be performed on strings.

1. Checking equality of two strings : S1 == S2
Checks whether the two strings are equal. Checking equality results 1 if they are equal and 0 if they are unequal. Both strings can be of type string. Or one of them can be a string literal. If both operands are string literals, the operator is the same Verilog equality operator as for integer types.

Example 3 : Checking Equality

// SystemVerilog Strings Equality
module str; 
  string S1 = "VLSI Encyclopedia"; 
  string S2 = "VLSI Encyclopedia";
  string S3 = "vlsi encyclopedia";
  initial begin 
    if(S1 == S2) 
      $display(" S1 and S2 are equal"); 
    else 
      $display(" S1 and S2 are not equal"); 
    if(S1 == S3) 
      $display(" S1 and S3 are equal"); 
    else 
      $display(" S1 and S3 are not equal"); 
  end 
endmodule 

Simulation Results 
S1 and S2 are equal
S1 and S3 are not equal

2. Checking equality of two strings : S1 != S2
Reverse to the equality operation this operation results 0 if two strings are equal and 1 if they are unequal.

Example 4: Checking Inequality

// SystemVerilog Strings Equality
module str; 
  string S1 = "VLSI Encyclopedia"; 
  string S2 = "VLSI Encyclopedia";
  string S3 = "vlsi encyclopedia";
  initial begin 
    if(S1 != S2) 
      $display(" S1 and S2 are not equal"); 
    else 
      $display(" S1 and S2 are equal"); 
    if(S1 != S3) 
      $display(" S1 and S3 are not equal"); 
    else 
      $display(" S1 and S3 are equal"); 
  end 
endmodule 

Simulation Results 
S1 and S2 are equal
S1 and S3 are not equal

3. Concatenation of strings : {S1, S2, S3,...,Sn}
To concatenate two or more strings, specify the string variable inside {} each separated by comma",". Each operand can be of type string or a string literal.

Example 5 : Concatenation


// SystemVerilog Strings Concatenation
module str; 
  string S1, S2, S3, S4, S5; 
  initial begin 
    S1 = "Con"; 
    S2 = "cate"; 
    S3 = ""; 
    S4 = "na"; 
    S5 = "tion"; 
    $display(" %s ",{S1,S2,S3,S4,S5}); 
  end 
endmodule 

Simulation Results
Concatenation

4. Replication of Strings : {N{S1}}
The result of replication is a string containing N concatenated copies of S1. N is the multiplier ans S1 can be of string type or string literal.

Example 6 : Replication

// SystemVerilog Strings Replication
module str; 
  string S1, S2; 
  initial begin 
    S1 = "w"; 
    S2 = ".vlsiencyclopedia.com"; 
    $display(" %s ",{{3{S1}},S2}); 
  end 
endmodule 

Simulation Results :
www.vlsiencyclopedia.com

5. String Indexing : S1[Index]
It returns a byte, an ASCII code at the given Index. Index can range from 0 to N where N is the number of characters in the string. If the Index is out of range then result will be 0.

Example 7 : Indexing

// SystemVerilog Strings Indexing
module str; 
  initial begin
    string S1; 
   S1 = "Indexing"; 
  for(int i =0 ;i < 8 ; i++) 
    $display("%s ",S1[i]); 
  end 
endmodule 

Simulation Result :
I
n
d
e
x
i
n
g

Previous : SystemVerilog Constants
Next : Net Type

Saturday, 24 January 2015

SystemVerilog Constants

In previous post of this SystemVerilog Tutorial we talked about enumerated type in detail. Now we will look at the constants in SystemVerilog. There are several types of constants in systemVerilog. The classic Verilog way to create a constant is with a text macro. 

On the plus side, macros have global scope and can be used for bit field definitions and type definitions.
On the negative side, macros are global, so they can cause conflicts if you just need a local constant. 
Lastly, a macro requires the ` character so that it will be recognized and expanded.

In SystemVerilog, parameters can be declared at the $root level so they can be global. This approach can replace many Verilog macros that were just being used as constants. You can use a typedef to replace those large macros. The next choice is a parameter. A Verilog parameter was loosely typed and was limited in scope to a single module. Verilog-2001 added typed parameters, but the limited scope kept parameters from being widely used.

SystemVerilog allows you to declare constant identifiers. You can declare an identifier as constant by prefixing the usual identifier definition with the keyword const. At the time of defining a constant, the user needs to provide a value for the identifier. At any later stage in the code, a SystemVerilog compiler disallows any modification to the value bound to the identifier.


// Constant bit 
const bit [63:0] data_bus='hB6AB31E0;
// Constant int bus width
const int bus_width = 8;
// Constant String VLSI Encyclopedia
const string name = "VLSI Encyclopedia";
// Constant method
function int count (const ref bytes[]);

In addition to a normal identifier declaration, the const modifier can be used to declare function/task arguments as constants. An argument to a function may be of either a pass-by-value or pass-by-reference type. When using pass-by-value semantics, the const modifier has the usual meaning; the locally bound parameter's value can not be changed in the given function.

When using pass-by-reference semantic (as is the case with const ref arrays), the SV compiler ensures that the referenced value is not modified by the code in the function. Normally arrays (even dynamic ones) are passed by value. 

Since arrays could be very big, SystemVerilog allows you to declare an array parameter type as a reference, by prefixing the function parameter with keyword ref. But this introduces the danger of a user inadvertently altering the arrays (actually it's elements) value. By prefix const to the reference array parameter, you can avoid this danger. The compiler would ensure that inside the function, a user can not alter the arrays value.

Note :
Constant identifiers in SystemVerilog are not compile time constants. As a result it is not allowed to use a constant as a range parameter for an array. This is much unlike C++, wherein constants are compile time constants. As an alternative, SystemVerilog users are allowed to use parameters (aka parameterized functions and classes) as range specifiers for an array.

Previous : SystemVerilog Enumerated Types
Next : SystemVerilog Strings