HOME

    Electronics Directory Articles/ Tutorials eBooks

About Us

FORUM Links Contact Us
   

1. Introduction

Verilog 1995 version has been in market for a very long time. IEEE extended the features of Verilog 1995 and released it as Verilog 2001. But this was no good for verification engineers, so verification engineers had to use languages like "e", VERA, Testbuider. It was rather painfull to have two languages, one for design and other for verification. SystemVerilog combines the Verification capabilties of HVL (Hardware Verification Language) with ease of Verilog to provide a single platform for both design and verification. 

Some of the new features in SystemVerilog are as listed below.

  • C type data types like int, typedef, struct, union, enum.
  • Dynamic data types: struct, classes, dynamic queues, dynamic arrays.
  • New operators and built in methods.
  • Enhanced flow control like, foreach, return, break and continue.
  • Semaphores, mailboxes, event extensions.
  • Classes for object oriented programming.
  • Assertions.
  • Coverage.
  • VPI extensions.

Now IEEE has accepted the SystemVerilog and it will be official intergrated into Verilog 2005, which is suppose to be released in year 2005.

Anyone with background of C++, or OO programming language will feel at home with SystemVerilog. But on other hand if you have been thinking C or C++ is not required, then you may be shocked to know that SystemVerilog is very much like C++.

 

This document specifies the Accellera extensions for a higher level of abstraction for modeling and verification with the Verilog Hardware Description Language. These additions extend Verilog into the systems space and the verification space. SystemVerilog is built on top of the work of the IEEE Verilog 2001 committee.

Throughout this document:

— “Verilog” or “Verilog-2001” refers to the IEEE Std. 1364-2001 standard for the Verilog Hardware Description Language

— “SystemVerilog” refers to the Accellera extensions to the Verilog-2001 standard.

This document numbers the generations of Verilog as follows:

“Verilog 1.0” is the IEEE Std. 1364-1995 Verilog standard, which is also called Verilog-1995

“Verilog 2.0” is the IEEE Std. 1364-2001 Verilog standard, commonly called Verilog-2001; this generation of Verilog contains the first significant enhancements to Verilog since its release to the public in 1990

“SystemVerilog 3.x” is Verilog-2001 plus an extensive set of high-level abstraction extensions, as defined in this document

— SystemVerilog 3.0, approved as an Accellera standard in June 2002, includes enhancements primarily directed at high-level architectural modeling

— SystemVerilog 3.1, approved as an Accellera standard in May 2003, includes enhancements primarily directed at advanced verification and C language integration

— SystemVerilog 3.1a, approved as an Accellera standard in April 2004, includes corrections and clarifications to the SystemVerilog 3.1 manual, as well as some additional enhancements to Verilog such as VCD and PLI specifications for SystemVerilog construct.

 

SystemVerilog is built on top of Verilog 2001. SystemVerilog improves the productivity, readability, and reusability of Verilog based code. The language enhancements in SystemVerilog provide more concise hardware Descriptions, while still providing an easy route with existing tools into current hardware implementation Flows. The enhancements also provide extensive support for directed and constrained-random testbench development, coverage driven verification, and assertion based verification.

 

SystemVerilog adds extended and new constructs to Verilog-2001, including:

      Extensions to data types for better encapsulation and compactness of code and for tighter specification

      C data types: int, typedef, struct, union, enum

      Other data types: bounded queues, logic (0, 1, X, Z) and bit (0, 1), tagged unions for safety

      Dynamic data types: string, classes, dynamic queues, dynamic arrays, associative arrays including automatic memory management freeing users from de-allocation issues

      Dynamic casting and bit-stream casting

      Automatic/static specification on a per variable instance basis

      Extended operators for concise description

      Wild equality and inequality

      Built-in methods to extend the language

      Operator overloading

      streaming operators

      set membership

      Extended procedural statements

      Pattern matching on selection statements for use with tagged unions

      enhanced loop statements plus the foreach statement

      C like jump statements: return, break, continue

      Final blocks that executes at the end of simulation (inverse of initial)

      extended event control and sequence events

      Enhanced process control

      Extensions to always blocks to include synthesis consistent simulation semantics

      Extensions to fork…join to model pipelines and for enhanced process control

      Fine-grain process control

      Enhanced tasks and functions

      C like void functions

      pass by reference

      default arguments

      pass by name

      Optional arguments

      import/export functions for DPI (Direct Programming Interface)

      Classes: Object-Oriented mechanism that provides abstraction, encapsulation, and   safe pointer capabilities

      Automated testbench support with random constraints

      Interprocess communication synchronization

      semaphores

      Mailboxes

Event extensions, event variables, and event sequencing

      Clarification and extension of the scheduling semantics

      Cycle-Based Functionality: Clocking blocks and cycle-based attributes that help reduce development ease maintainability, and promote reusability:

      cycle-based signal drives and samples

      Synchronous samples

      race-free program context

      Assertion mechanism for verifying design intent and functional coverage intent.

      Property and sequence declarations

      Assertions and Coverage statements with action blocks

      Extended hierarchy support

      Packages for declaration encapsulation with import for controlled access

      compilation-unit scope nested modules and extern modules for separate compilation support

      Extension of port declarations to support interfaces, events, and variables.

      $root to provide unambiguous access using hierarchical references

      Interfaces to encapsulate communication and facilitate “Communication Oriented” design

      Functional coverage

      Direct Programming Interface (DPI) for clean, efficient interoperation with other languages (C provided)

      Assertion API

      Coverage API

      Data Read API

      VPI extensions for SystemVerilog constructs

      Concurrent assertion formal semantics

 

 

 

 

 

 

 

 

  2. Operators

          System verilog adds the following operators ++ and – increment and decrement operators similar to C

 

           Loop variables can be declared inside a loop. In verilog, the variable has to be declared and  then used within a loop

 

 

Operator Type

Operator Symbol

Operation Performed

Arithmetic

*

Multiply

 

/

Division

 

+

Add

 

-

Subtract

 

%

Modulus

 

+

Unary plus

 

-

Unary minus

Logical

!

Logical negation

 

&&

Logical and

 

||

Logical or

Relational

>

Greater than

 

<

Less than

 

>=

Greater than or equal

 

<=

Less than or equal

Equality

==

Equality

 

!=

inequality

Reduction

~

Bitwise negation

 

~&

nand

 

|

or

 

~|

nor

 

^

xor

 

^~

xnor

 

~^

xnor

Shift

>>

Right shift

 

<<

Left shift

Concatenation

{ }

Concatenation

Conditional

?

conditional

 

Assignment operator

=, +=, -=,  *= ,  /=,  %=,  &=, |=, ^=,  <<=, >>=, <<<=, >>>=

 

Conditional_Expression

cond_predicate ? { attribute_instance } expression : expression

Unary_operator

+, -, !, ~, &, ~&, |,  ~|,  ^, ~^, ^~

Binary_operator

+,-, *, /, %, ==, !=, ===,!==, =?=, !?=, &&, ||, **

<, >, <=, >=, &, |, ^, ~^, ^~, >>, <<, <<<, >>>

Increment, decrement operators

++, --

Unary_module_path_operator

!, ~, &, ~&, |, ~|, ^, ~^, ^~

Binary_module_path_operator

==, !=, &&, ||, &, |, ^, ~^, ^~

 

Concatenation

Braces ( { } ) are used to show concatenation, as in Verilog. The concatenation is treated as a packed vector of bits. It can be used on the left hand side of an assignment or in an expression.

 

logic log1, log2, log3;

{log1, log2, log3} = 3’b111;

{log1, log2, log3} = {1’b1, 1’b1, 1’b1}; // same effect as 3’b111

 

SystemVerilog enhances the concatenation operation to allow concatenation of variables of type string. In general, if any of the operands is of type string, the concatenation is treated as a string, and all other arguments are implicitly converted to the string type. String concatenation is not allowed on the left hand side of an assignment, only as an expression.

 

string sv = "SystemVerilog";

string s;

s = {sv, " ", "is easy”};

$display (“%s\n", s);                           // displays 'SystemVerilog is easy’

s = {s, “, enjoy”};

$display (“%s\n", s);                          // displays 'SystemVerilog is easy, enjoy’

 

 

3. Structures and unions

 

Structures:

 

User can create a logical collection of objects using struct

      Not restricted to elements of same size and type as with arrays

      Can be referenced as a whole or by individual element

 

 

 

Unions:

  

 Unions also allow the user to create a collection of objects

      However, unions only store a single element

      Text Box: typedef struct packed {
    opc_t       opcode;
    reg_t       ra, rb, rc;
    logic [11:0] c3;
} instr_format_3;
 
typedef struct packed {
    opc_t       opcode;
    reg_t       ra, rb;
    logic [16:0] c2;
} instr_format_2;
 
typedef struct packed {
    opc_t       opcode;
    reg_t       ra;
    logic [21:0] c1;
} instr_format_1;

 

Advantage: single element stored with different representations

 

Text Box: typedef union packed {
    instr_format_1 IW1;
    instr_format_2 IW2;
    instr_format_3 IW3;
    logic [31:0] BITS;
} InstrType;
 
InstrType IR;
 
always_comb
        if (c1o)
            q = {{10{IR.IW1.c1[21]}}, IR.IW1.c1};
        else if (c2o)
            q = {{15{IR.IW2.c2[16]}}, IR.IW2.c2};
        else
            q = IR.BITS;

 

 

 

 

 

 

 

 

 

 

 

 


 

4. Control Statements

Wait, what's this? if, else, repeat, while, for, case - it's Verilog that looks exactly like C (and probably whatever other language you're used to programming in)! Even though the functionality appears to be the same as C, Verilog is an HDL, so the descriptions should translate to hardware. This means you've got to be careful when using control statements (otherwise your designs might not be implementable in hardware).

 if-else

if-else statements check a condition to decide whether or not to execute a portion of code. If a condition is satisfied, the code is executed. Else, it runs this other portion of code.

   // begin and end act like curly braces in C/C++.
if (enable == 1'b1)
 begin
  data = 10; // Decimal assigned
  address = 16'hDEAD; // Hexadecimal
enable = 1'b1; // Binary  
end 
else 
begin
  data = 32'b0;
   enable = 1'b0;
  address = address + 1;  
end

 

One could use any operators in the condition checking as in the case of C language. If needed we can have nested if else statements, statements without else is also ok, but then it has its own problem when modeling combinational logic, if statement without else results in a Latch (this is not always true).

 

 

case

Case statements are used where we have one variable which needs to be checked for multiple values. Like an address decoder, where the input is an address and it needs to check for all the values that it can take. Instead of using multiple nested if-else statements, one for each value we're looking for, we use a single case statement, and this is similar to switch statements in languages like C++.

Case statements begin with the reserved word case and end with the reserved word endcase (Verilog does not use brackets to delimit blocks of code). The cases, followed with a colon and the statements you wish executed, are listed within these two delimiters. It's also a good idea to have a default case. Just like with a finite state machine (FSM), if the Verilog machine enters into a non-covered statement, the machine hangs. Defaulting the statement with a return to idle keeps us safe.

 case (address)
  0: $display ("It is 11:40PM");
  1: $display ("I am feeling sleepy");
  2: $display ("Let me skip this tutorial");
  default : $display ("Need to complete");
endcase

Looks like address value was 3 and so I am still writing this tutorial. Note: One thing that is common to if-else and case statement is that, if you don't cover all the cases (don’t have else in if-else or default in case), and you are trying to write a combination statement, the synthesis tool will infer Latch.

While

A while statement executes the code within it repeatedly if the condition it is assigned to check returns true. While loops are not normally used for models in real life, but they are used in test benches. As with other statement blocks, they are delimited by begin and end.

 while(free_time) begin
         $display ("Continue with webpage development");
 end

 As long as free_time variable is set, code within the begin and end will be executed. i.e. print "Continue with web development". Lets look at a stranger example, which uses most of the constructs of Verilog. Well you heard it right. Verilog has very few reserve words then VHDL, and in this few, we use even lesser few for actual coding.

 

module counter (clk,rst,enable,count);
input clk, rst, enable;
output [3:0] count;
reg [3:0] count;
                                  
always @ (posedge clk or posedge rst)
if (rst) begin
  count <= 0;
end else begin : COUNT
  while (enable) begin
    count <= count + 1;
    disable COUNT;
  end
end
 
endmodule

The example above uses most of the constructs of Verilog. You'll notice a new block called always - this illustrates one of the key features of Verilog. Most software languages, as we mentioned before, execute sequentially - that is, statement by statement. Verilog programs, on the other hand, often have many statements executing in parallel. All blocks marked always will run - simultaneously - when one or more of the conditions listed within it is fulfilled.

In the example above, the always block will run when either rst or clk reaches a positive edge - that is, when their value has risen from 0 to 1. You can have two or more always blocks in a program going at the same time (not shown here, but commonly used).

We can disable a block of code, by using the reserve word disable. In the above example, after each incrementation of the counter, the COUNT block of code (not shown here) is disabled.

  for loop

For loops in Verilog are almost exactly like for loops in C or C++. The only difference is that the ++ and -- operators are not supported in Verilog. Instead of writing i++ as you would in C, you need to write out its full operational equivalent, i = i + 1.

   for (i = 0; i < 16; i = i +1) 
    begin
             $display ("Current value of i is %d", i);
    end

 

This code will print the numbers from 0 to 15 in order. Be careful when using for loops for register transfer logic (RTL) and make sure your code is actually sanely implementable in hardware.. and that your loop is not infinite.

   

repeat

Repeat is similar to the for loop we just covered. Instead of explicitly specifying a variable and incrementing it when we declare the for loop, we tell the program how many times to run through the code, and no variables are incremented (unless we want them to be, like in this example).

repeat (16)