THE VLSI HOMEPAGE

A Practical guide to VLSI Design and Verification..

Procedural Statements and Operators in SystemVerilog

Posted in SystemVerilog by Nigam on the October 20th, 2007

Verilog includes most of C-like control flow statements except for do-while, break, continue and goto. Verilog in addition supports the repeat statement that C does not and the disable. SystemVerilog offers enhanced control flow statements that we will cover in this post.

Enhanced if-else

SV adds unique and priority keywords which can be used before an if clause. A priority if indicates that the logic will be intrepreted in the order listed - i.e. like priority encoder. A unique if indicates that all the expressions in the if-else are mutually exclusive i.e. only one of the expressions is true at any given time. These keywords make the design intent more intuitive and aid synthesis tools infer priority encoder logic only when required. If no condition matches with either of these keywords without an explicit else, it results in a runtime error.

SV:
  1. logic [3:0] mode_sel;
  2.  
  3. always_comb begin
  4.     unique if (mode_sel == 4'b0001) out = in1; // unique - mutually exclusive conditions, can be executed in parallel
  5.     else    if (mode_sel == 4'b0010) out = in2;
  6.     else    if (mode_sel == 4'b0100) out = in3;
  7.     else    if (mode_sel == 4'b1000) out = in4;
  8. end
  9.  
  10. always_comb begin
  11.    priority if (mode_sel == 4'b0001) out = in1; // priority - sequential order, first true expression takes precedence
  12.    else    if (mode_sel == 4'b0010) out = in2;
  13.    else    if (mode_sel == 4'b0100) out = in3;
  14.    else    if (mode_sel == 4'b1000) out = in4;
  15. end

Enhanced case statements
Similar to if-else statements, SV supports priority and unique keywords for case, casex and casez statements also. For synthesis, the unique case is similar to enabling the full_case and parallel_case pragmas and priority case is similar to enabling the full_case. However, by including these keywords in the SV language rather than use synthesis pragmas, any simulation/synthesis mismatches in how tools intrepret the logic can be avoided.

Enhanced for loops
In Verilog, the variable used in a for loop expression should be declared prior to the loop. Also, if multiple for loops are running concurrently, separate variables need to be used. SV simplifies the for loops by allowing to declare the variable in for loop expression itself.

SV:
  1. always_ff @(posedge clk) begin : label_count   // SV allows named begin-end blocks
  2.    for (int i = 0; i <16; i++)  // automatic variable int, i visible only within for loop
  3.    count = count + incr[i]
  4. end : label_count
  5.  
  6. //foreach loop construct
  7. logic [15:0] parity;
  8. logic [15:0] [7:0] data;
  9. foreach (parity[i]) parity[i] = ^data[i]; // generates parity for each data byte

SV adds a foreach loop construct which can be used to iterate over elements of single and multidimensional arrays without specifying the array dimension. SV also adds continue, break and return statements like C. SV also supports labels before any procedural statement.

SV supports a final block that is executed at the end of simulation time (unlike initial time) and is used to display statistical information about the simulation using $display.

Operators

SV includes increment (++) and decrement (--) operators similar to C - they can be used to post-increment or pre-increment a variable. The increment and decrement operators behave as blocking assignments and should be used only for combinatorial blocks to avoid race conditions i.e. the ++ or -- operators should not be used in always_ff blocks.

SV supports C like assignment operators like +=, ^=, !=, *=, <<= etc. These assigment operators behave like blocking assignments like the above. SV adds two new comparison operators ==? and !=? in addition to == and === operators.

The ==? referred to as wildcard equality operator makes a bit wise comparison of two operands but any logic X or Z in the right operand is treated as a wildcard and matches any value in the LHS operand's corresponding bit position.

In addition, SV supports inside keyword to test if a variable matches anywhere within a set of values.

SV:
  1. logic [2:0] count;
  2.   if (count inside (3'b001, 3'b010, 3'b100)) // similar to if ((count==3'b001) || (count==3'b010)..)
  3. int count [0:31];
  4.   if (100 inside (count)); // can also be an array

Sphere: Related Content

Procedural Blocks in SystemVerilog

Posted in SystemVerilog by Nigam on the October 19th, 2007

Verilog supports the always block that is used to model combinatorial as well as sequential logic. In addition to this, the always block is used to model clock oscillators and other verification tasks that are not synthesizable. Synthesis tools add strict guidelines that need to be followed while using always block to infer latches, flops or combinatorial logic correctly.

SystemVerilog adds three new procedural blocks - always_ff, always_comb and always_latch for clear logic inference.

SV:
  1. always_comb // Not necessary to specify sensitivity list
  2.   if (sel)
  3.     out = in1;
  4.   else
  5.     out = in2;
  6.  
  7. always_latch       // infer latch
  8.     if (en) q <= d;
  9.  
  10. always_ff @(posedge clk, negedge rstn)
  11.    if (!rstn)       q <= 0;
  12.    else             q <= d;

There are three key differences between always_comb and always blocks :

  • the variables on the LHS side of assignments in always_comb blocks cannot be assigned in multiple procedural blocks for true combinatorial logic behavior and
  • the always_comb block is automatically triggered at simulation time 0 after all initial and always blocks are active. This is necessary to prevent simulation deadlock that would exist if one were to use 2-state types in the always block that default to zero.
  • when including function calls inside always_comb blocks, Verilog always @* can infer incomplete sensitivity lists since it only adds signals read directly in the block and not any inputs called by the function. SV infers the sensitivity list correctly and supports calling functions without arguments.

Tasks and Functions

SV adds several enhancements to Verilog tasks and functions that include:

  • A return keyword that returns the value of the function. In verilog, the value assigned to the function name is returned. In SV, the return takes precedence over this. In addition, the return keyword can be used to abort the function at any time whereas in Verilog the function is executed until the endfunction is reached.
  • SV adds a void type to declare functions that have no return value.
  • SV infers begin - end for grouping multiple statements in functions and tasks.
  • SV allows function formal arguments to be input, output, inout or ref unlike Verilog where function arguments can only be input. By default, all arguments are input in SV unless explicitly declared otherwise.
SV:
  1. function automatic int expo (input int a = 2, b); // arguments can have default values
  2.    expo = a * b;
  3.    return a ** b; // return overrides the value written to function name expo
  4. endfunction
  5.  
  6. always_comb
  7.     x = expo (.a (m), .b(n) ); // can pass function arguments by name in SV
  8.  
  9. // allows unpacked arrays, packed/unpacked structures in functions/tasks
  10. typedef struct {
  11.     logic [23:0] addr;
  12.     logic [127:0] data;
  13.     byte crc;
  14. } packet_s;
  15.  
  16. function void packet_construct ( input logic [127:0] data_in,   output packet_s pkt_s );
  17.     pkt_s.data = data_in;
  18. endfunction

SV allows passing arguments by value and by reference to a function or a task. Pass by argument works by copying the argument into the subroutine area and any changes to the copy are only locally visible. To pass by reference, SV uses the ref keyword and the argument is not duplicated within the function or task and any changes within the subroutine is also visible to the function call. In order to have ref arguments, the function or task must be automatic.

Sphere: Related Content

Arrays in SystemVerilog

Posted in SystemVerilog by Nigam on the October 18th, 2007

An array is a collection of similar variables, accessible via indices and the array name. Verilog-2001 supports multi-dimensional arrays and net and variable type array declarations are valid. Verilog restricts access to only one element or a slice of an array at a time.

 

 

 

SV:
  1. reg r [0:63]; // 1 dimensional unpacked array
  2. wire [0:7] count [0:144]; // a 1-dimensional unpacked array 145 8-bit nets
  3. int i [0:7] [0:15]; // a 2-dimensional unpacked array
  4.  
  5. // Packed Arrays
  6. wire [3:0] count; // packed array of 4-bits
  7.  
  8. wire [3:0] [1:0] addr; // 2-dimensional packed array
  9. wire [7:0] addr_out = addr; //  entire packed array
  10.  
  11. // Initializing Packed array
  12. wire [7:0] [1:0] data = 16'h0;
  13. // Initializing Unpacked array
  14. wire data [0:1] [0:3] = '{ '{11, 12, 13, 14}, '{2, 3, 4, 5} }
  15. int addr [0:1] [0:15] = '{ default: 2'h3 } // initialize all elements to 2'b11

SV extends the unpacked arrays to new types like int, shortint, logic, bit, byte, real and shortreal. SV also allows accessing all elements of an array at a time unlike Verilog. For packed arrays, multi-dimensional arrays are supported by SV. The entire packed array is stored as contiguous order of bits and arithmetic/logical operations are supported.

Packed arrays can be assigned to another packed array even if their sizes do not match. However, unpacked arrays can be assigned to another unpacked array only if the vector and dimension size are equal. To assign an unpacked array to a packed array or vice versa, bit stream casting needs to be done. A bit-stream cast converts an unpacked array into a stream of bits using the SV static cast operator '. Both packed and unpacked arrays are synthesizable.

SV also supports dynamic arrays for higher levels of modeling (not synthesizable) - A dynamic array is one dimension of an unpacked array, the size of which is set or changed during runtime.

SV:
  1. bit [3:0] crc [];// Dynamic array of 4-bit vectors

SV supports new[], size() and delete() methods similar to C for dynamic arrays.

Associative arrays are also supported by SV - the array index is not restricted to integral values (like int, shortint) and can be any data type.

SV:
  1. integer assoc[*]; // * is wildcard indicates unspecified but integral value index
  2. bit [7:0] assoc [string]; // indexed by string

SV supports in-built methods for associative arrays as tabulated below.


Associative Methods

Description

<array>.num( )

 

Returns number of entries in the
associative array.

<array>.delete(N)

 

if index N is not specified, deletes all elements of the
array. If index N is specified, deletes only that particular element.

<array>.exists(N)

checks if element exists at that particular index of the array. returns
1 if true. index is mandatory

<array>.first(N)

assigns to the index variable N the value of the smallest
index in the array, returns 1 if array is not empty, 0 otherwise

<array>.last(N)

assigns to the index variable N the value of the largest index in the
array, returns 1 if array is not empty, 0 otherwise
<array>.next(N) finds the entry whose index is greater
than current index N and assigns the index variable to that next entry.
Retruns 1 if true
<array>.prev(N) finds the entry whose index is smaller
than current index N and assigns the index variable to that previous entry.
Retruns 1 if true
   
Sphere: Related Content

« Previous PageNext Page »

Close
E-mail It