Manual
Manual
  Cadence Trademarks
  Trademarks and service marks of Cadence Design Systems, Inc. (Cadence) contained in this document are attributed to Cadence with the appropriate
  symbol. For queries regarding Cadence’s trademarks, contact the corporate legal department at the address above or call 800.862.4522.
  Other Trademarks
  Open SystemC, Open SystemC Initiative, OSCI, SystemC, and SystemC Initiative are trademarks or registered trademarks of Open SystemC Initiative, Inc.
  in the United States and other countries and are used with permission.
  All other trademarks are the property of their respective holders.
  Confidentiality Notice
  No part of this publication may be reproduced in whole or in part by any means (including photocopying or storage in an information storage/retrieval
  system) or transmitted in any form or by any means without prior written permission from Cadence Design Systems, Inc. (Cadence).
  Information in this document is subject to change without notice and does not represent a commitment on the part of Cadence. The information contained
  herein is the proprietary and confidential information of Cadence or its licensors, and is supplied subject to, and may be used only by Cadence’s customer in
  accordance with, a written agreement between Cadence and its customer. Except as may be explicitly set forth in such agreement, Cadence does not make,
  and expressly disclaims, any representations or warranties as to the completeness, accuracy or usefulness of the information contained in this document.
  Cadence does not warrant that use of such information will not infringe any third party rights, nor does Cadence assume any liability for damages or costs of
  any kind that may result from use of such information.
  RESTRICTED RIGHTS LEGEND Use, duplication, or disclosure by the Government is subject to restrictions as set forth in subparagraph (c)(1)(ii) of the
  Rights in Technical Data and Computer Software clause at DFARS 252.227-7013.
  UNPUBLISHED This document contains unpublished confidential information and is not to be disclosed or used except as authorized by written contract
  with Cadence. Rights reserved under the copyright laws of the United States.
This document is for the sole use of Sundaresan Chidambaram of Manipal University
       Table of Contents                                                                                                                      SystemVerilog for Verification
Table of Contents
Unions ........................................................................................................................................................ 36
Index .............................................................................................................................. i
Version 9.2
November 6, 2009
       Welcome to the “SystemVerilog for Verification” module of the “SystemVerilog Language and
       Application” training course. This is the second module of the three-part training course. This
       module focuses on the SystemVerilog features that increase the productivity of verification
       personnel.
November 6, 2009
       This first chapter introduces the training materials: The topics, agenda, and some training materials
       conventions.
What’s Coming...
                             Training Objectives
                               Introduce the SystemVerilog verification features
                             Chapter Format
                               Intro – Slides – Summary – Quiz – Lab
                             Timing Options
                               Real classroom: Coffee ... Breaks … Labs … Lunch …
                               “Virtual” classroom: On your own – but don’t forget!
       11/6/2009                                SystemVerilog for Verification                                3
       This training module focuses on the SystemVerilog features that increase the productivity of
       verification personnel. It covers the “nuts and bolts” of the features, and also contains helpful hints,
       and warnings about potential support and usage issues.
       At the end of all but the earliest chapters is a quiz. The quiz is not interactive. Please try to work
       the quiz yourself before referring to solutions in the appendix. There is a lab associated with all but
       the earliest chapters. Lab practice reinforces the features presented in the slides.
       In a real classroom, the instructor and students to some extent negotiate the class timing. In a
       “virtual” classroom you have a lot more control over this timing. For an optimal learning
       experience, you should study each chapter and do its associated quiz and lab in one session without
       significant interruption.
       This module focuses on the SystemVerilog features that increase the productivity of verification
       personnel. Those features include:
          Dynamic data types, such as classes and various kinds of arrays;
          Programming constructs, such as programs and final blocks and clocking blocks;
          Advanced use of interfaces for transaction-based verification (TBV);
          The direct programming interface (DPI); and
          Advanced verification methodologies, such as constrained randomization, coverage, assertions
           and interprocess synchronization.
       The instructor-led version if this module follows the agenda you see here. For self-paced learning,
       the agenda is an estimate of how much time you will need to complete the training.
       The “Design” module only briefly introduces the subroutine enhancements and interfaces. Those
       features are more applicable to verification, so the “Verification” module explores them in greater
       detail.
       As the “Design” and “Assertions” modules each contain more material than you can comfortably
       absorb in a day, your instructor can and should tailor this agenda to meet your actual needs.
Chapter 1
November 6, 2009
        Topics
          What is SystemVerilog?
       This chapter introduces the SystemVerilog scope, purpose, and features. It briefly describes what
       SystemVerilog is, explains why it exists, and segments the language into easily adopted subsets. It
       then briefly separately highlights some of the major features.
        SystemVerilog Introduction
        Aim:
         Unified hardware design, specification, and verification language
        Realization:
         Extends and adds to Verilog-2001 constructs …
          Extended data types                                Random constraints
       SystemVerilog is the IEEE Std 1800-2005 “IEEE Standard for SystemVerilog — Unified
       Hardware Design, Specification, and Verification Language”.
       SystemVerilog includes the IEEE Std 1364-2001 “IEEE Standard Verilog® Hardware Description
       Language” by reference.
       SystemVerilog makes it practical to more productively write readable and reusable code. For the
       design engineer, SystemVerilog provides constructs with which to more concisely and correctly
       describe hardware. For the verification engineer, SystemVerilog provides constructs with which to
       use transaction, randomization, assertion and coverage methodologies.
       The IEEE Std. 1364 standardized in 1995 what was previously the proprietary Verilog hardware
       description language.
       The 2001 update to the Verilog standard added several convenience features, still primarily
       targeted at hardware design.
       Accellera proposed an update to the Verilog standard that added many design convenience features
       and more than tripled the verification features. This slide illustrates just how much SystemVerilog
       adds to Verilog. To hopefully minimize confusion, Accellera requested and obtained the new IEEE
       standard number 1800 for these new features. The SystemVerilog standard incorporates the Verilog
       standard by reference – there is no such thing as “stand-alone” SystemVerilog.
SystemVerilog Segmentation
       The SystemVerilog standard incorporates the Verilog standard by reference, rather than repeating it
       and thus potentially diverging from the Verilog standard. You can easily segment SystemVerilog
       into just those parts you need to know for your product development role.
       The training materials focus first on the designer subset. This subset adds constructs with which
       you can more clearly and concisely code your RTL design.
       In the design verification role, you can take advantage of most of the new verification features,
       without getting involved with …
          The C++-like object oriented features, or
          Importing or exporting C routines.
       Of course, for advanced verification, you will want to take advantage of the object oriented
       features, such as overloaded operators, classes, polymorphism, and more …
       and you may even want to map SystemVerilog functions and tasks to C routines to reuse existing
       IP written in C.
                                              Functional
                                              Coverage
                                Generation                     Checking
                             Constrained Random          Assertions, Scoreboard
       The SystemVerilog verification methodology relies on three building blocks that you can use
       separately or together:
          You want to stimulate the design with random, yet meaningful combinations of address, data
           and other variables;
          During simulation, you want to automatically verify that your defined design properties do not
           fail to be true; and
          After simulation, or potentially during simulation, you want to measure how completely the test
           verifies the design functionality, and use those results to direct future test efforts.
              Data Abstraction
                    2-state, enumerated, structured and user-defined types
        SystemVerilog Randomization
         Automatic random generation of
            stimulus                                    ok
                                                        ok == randomize(data)
                                                              randomize(data) with
                                                                               with
         Range and probability of values can                 {mode
                                                              {mode == small -> data
                                                                    == small  -> data         <<   100;
                                                                                                   100;
            be controlled via constraints                      mode == large  -> data
                                                               mode == large -> data          >>   200;};
                                                                                                   200;};
                  Conditional
                  Distributed                                     ok
                                                                   ok == point.randomize()
                                                                         point.randomize()
                  Weighted
         SystemVerilog supports                          randcase
                                                          randcase
            randomization of simple variables or            20
                                                            20 :: gen_atm;
                                                                   gen_atm;
            complex object-oriented data                    30
                                                            30 :: gen_ethernet;
                                                                   gen_ethernet;
         Also additional constructs for                    10
                                                            10 :: gen_ipv4;
                                                                   gen_ipv4;
            randomization of events and                      55 :: gen_crc_error;
                                                                   gen_crc_error;
            sequence of data                              endcase
                                                          endcase
                                                                     randsequence
                                                                     randsequence (( main
                                                                                      main ))
                                                                       main
                                                                       main   :: inc | dec;
                                                                                 inc  | dec;
                                                                       inc
                                                                       inc    :: {{ do_inc();
                                                                                    do_inc(); };
                                                                                              };
                                                                       dec
                                                                       dec    :  {  do_dec(); };
                                                                               : { do_dec(); };
                                                                     endsequence
                                                                     endsequence
       You can randomize a scope variable, and you can at once randomize selected properties of a class
       instance, optionally using constraint blocks. Constraint blocks can include constraint expressions,
       that may involve conditional, distributed, and weighted constraints, and may also specify an order
       in which to solve the constraints. SystemVerilog also offers the randcase construct for randomly
       selecting branches of a case statement, and the randsequence construct, for generating a random
       sequence of statements.
                                                                       A1:
                                                                       A1: assert
                                                                           assert property
                                                                                  property (abcd);
                                                                                           (abcd);
       An assertion “asserts” that a property of the design holds. You use assertions mainly to verify
       design properties. You can also use “covers” to measure how completely the test environment
       exercises the properties, and for static formal verification, you can use “assumptions” to generate
       setup sequences on design inputs. These are all part of SystemVerilog Assertions.
          //
          // SV
              SV coverage
                 coverage group:
                           group:                               //
                                                                // SVA
                                                                    SVA functional
                                                                        functional coverage
                                                                                    coverage
          covergroup
          covergroup cg1
                      cg1 @(posedge
                           @(posedge clk);
                                       clk);                    property
                                                                property full2empty;
                                                                          full2empty;
            Addr:
             Addr: coverpoint
                   coverpoint addr
                                 addr                             @(posedge
                                                                   @(posedge clk)
                                                                              clk)
            {{ bins
                bins low
                     low    == {{ [0:’h0F],
                                  [0:’h0F], 19
                                             19 };
                                                 };                 fifo_full
                                                                    fifo_full ##[1:$]
                                                                               ##[1:$] fifo_empty;
                                                                                       fifo_empty;
                bins
                bins mid[]
                     mid[] == {{ 16,
                                  16, 17,
                                      17, 18
                                           18 };
                                              };                endproperty
                                                                endproperty
                bins
                bins high
                     high == {{ [’h14:’hFF]
                                  [’h14:’hFF] };
                                               }; }}            C1
                                                                C1 :: cover
                                                                      cover property
                                                                            property (full2empty);
                                                                                      (full2empty);
            AddrXvalid
             AddrXvalid :: cross
                           cross Addr,
                                   Addr, valid;
                                          valid;
          endgroup
          endgroup
          cg1
          cg1 cover_inst
               cover_inst == new;
                              new;
       Coverage is a measure of the percentage of verification objectives that have been met. You use this
       metric to evaluate the progress of your verification efforts, in order to redirect further efforts
       toward areas of the design that are less well tested.
       Coverage is in two general categories: tool-instrumented code coverage, that is, of lines,
       statements, blocks and expressions; and user-defined functional coverage, that is, of design
       behavior. All coverage described by the SystemVerilog standard refers to functional coverage.
       Functional coverage measures how well the test environment exercises user-defined design
       behavior. Functional coverage requires a structured approach to verification, and, often
       painstaking, manual effort.
                                  SystemVerilog                                                   C
                   module
                    module top;
                            top;                                                 #include
                                                                                  #include <stdio.h>
                                                                                            <stdio.h>
                   ...
                    ...                                                          #include
                                                                                  #include <svdpi.h>
                                                                                            <svdpi.h>
                   import
                    import "DPI-C"
                            "DPI-C" context
                                     context c_imp
                                              c_imp ==
                     function   int imp_func(...);
                      function int imp_func(...);                                int
                                                                                  int c_imp
                                                                                       c_imp (...)
                                                                                              (...)
                                                                                 {{
                    res
                     res == imp_func(...);
                             imp_func(...);                                         ...
                                                                                     ...
                        ...
                         ...                                                     }}
                   endfunction
                    endfunction                                                  ...
                                                                                  ...
       The Direct Programming Interface (DPI) is an interface between SystemVerilog and a foreign
       programming language that maps subroutine calls in either language to subroutine implementations
       in the other language. The standard defines the SystemVerilog layer and the foreign language layer
       separately: SystemVerilog does not know or care that its subroutines are called or implemented in
       some other language. The standard currently defines only a C foreign layer.
 97 new keywords
       Many design teams have not yet fully adopted the Verilog-2001 standard. As SystemVerilog is
       based on Verilog-2001, such teams will need to learn about Verilog-2001 as well as
       SystemVerilog.
       Having 97 new keywords means that existing Verilog designs may not compile with
       SystemVerilog compilers. For example, if you have a signal named “do”, then your code will not
       compile in SystemVerilog because “do” is a SystemVerilog keyword.
       However, SystemVerilog does not take features away from Verilog users. Verilog-2001 features
       are still available and work the same as before.
Chapter 2
November 6, 2009
        Topics
          Strings
 Time literals
 Immediate assertions
          fork…join enhancements
          Design features useful for verification
        Strings
         New data type string
                     \v – vertical tab
                     \a – bell
                     \xdd – hex ASCII
       For Verilog, you can assign a character string literal to a reg vector.
       SystemVerilog provides a string type, which is essentially a dynamic array of byte elements with
       some methods defined to manipulate it as a character string. You can still do the operations you
       would expect to do on a vector reg that happens to hold the ASCII representation of a character
       string. Just remember that indexing a string is selecting a byte instead of a single bit.
       Verilog provides escaped character sequences for including newline (\n), tab (\t), backslash (\\) and
       quote (\") characters, and any octal representation of a character, within a string literal.
       To these, SystemVerilog adds the form feed, vertical tab and bell characters, and any hexadecimal
       representation of a character.
       --------
       IEEE Std. 1800-2005 SystemVerilog LRM, Section 4.7
String Operators
All of these string operators are just Verilog operators, so they should look familiar to you.
String Methods
         putc()        Replaces ith character of the string with the integral      task putc(int i, byte c)
                       value c
                                                                                   str.putc(i, c);
         getc()        Returns ASCII code of the ith character in the string       function byte getc(int i)
                                                                                   x = str.getc(i);
         compare()     Compares strings with regard to lexical ordering            function int compare(string s)
                                                                                   str.compare(s); // compares str to s
         icompare() Compares strings with regards to lexical ordering              function int icompare( string s)
                    and is insensitive to character case                           str.icompare(s); // compares str to s
         substr()      Returns new string that is a substring formed by            function string substr(int i, int j)
                       characters in position i through j of str.
                                                                                   str.substr(i,j);
          The “length” ( len() ) method returns the length of the string. This length does not include any
           terminating character.
          The “put character” ( putc() ) method replaces the character at the specified location with the
           specified ASCII value of a character.
          The “get character” ( getc() ) method returns the ASCII value of the character in the string at
           the specified location.
          The “compare” ( compare() ) method compares the string with the specified string argument in
           exactly the same manner as the “string compare” (strcmp) function of the ANSI C string
           library, that is, negative if less, zero if equal, and positive if greater.
          The “insensitive compare” ( icompare() ) method is like the “compare” method but is not
           sensitive to character case.
          The “substring” ( substr() ) method returns a new string identical to the substring that starts at
           the first specified location and ends at the second specified location.
       --------
       IEEE Std. 1800-2005 SystemVerilog LRM, Section 4.7
          The “to upper” ( toupper() ) and “to lower” ( tolower() ) methods return the same string with all
           characters converted to upper or lower case, respectively. They do not modify the original
           string.
          The “ASCII to binary, octal, decimal and hexadecimal” methods return the value of a string
           representation of the value. The conversion scans leading digit and underscore characters and
           stops the scan at any other character. It does not accept other Verilog literal syntax. It returns 0
           if it finds no valid integer literal.
          The “ASCII to real” ( atoreal() ) method does accept all Verilog syntax that constructs a real
           literal, and stops at any other character. It returns 0 if it finds no valid real literal.
          The “binary, octal, decimal, hexadecimal and real to ASCII” methods construct a string
           representation of the argument value.
        Time Literals
        SystemVerilog provides a time literal construct                         100ns
                                                                                100ns
          Explicitly specifies time values                                     3.55ps
                                                                                3.55ps
                                                                                1step
                                                                                1step
          Integer or fixed point value
       You write a time literal as an integer or fixed-point number, followed immediately by a time unit
       (fs ps ns us ms s step) without an intervening space character. The new step time unit refers to the
       simulation step, that is, the simulation precision. SystemVerilog scales the time literal to the
       current time unit and rounds it to the current time precision. This implies that you must have a
       current time unit and precision specified for the interface, module or program in which the time
       literal appears.
       --------
       IEEE Std. 1800-2005 SystemVerilog LRM, Section 3.5
                   `timescale
                   `timescale 1ns
                               1ns // 100ps
                                      100ps
                   module  testmodule;
                   module testmodule;
                     reg
                     reg a,
                          a, sel,
                             sel, y,
                                  y, z,
                                      z, clk;
                                         clk;
                   initial
                   initial
                   begin
                   begin
                     #20ns
                      #20ns sel
                             sel == 0;
                                    0;             //
                                                   //   blocking
                                                        blocking assign
                                                                  assign
                     #5.18ns
                      #5.18ns sel
                               sel == 1;
                                       1;          //
                                                   //   rounded
                                                        rounded to
                                                                 to 5.2ns
                                                                    5.2ns in
                                                                           in this
                                                                              this example
                                                                                   example
                     YY == #1step
                           #1step z;
                                   z;              //
                                                   //   blocking
                                                        blocking assign
                                                                  assign using
                                                                          using "step"
                                                                                "step"
                   end
                   end
                   always
                   always @(posedge
                          @(posedge clk)
                                       clk)
                     #5.1ns
                     #5.1ns aa <=
                               <= aa ++ 1;
                                        1; //
                                            // non-blocking
                                               non-blocking assign
                                                            assign
                   endmodule
                   endmodule
       You can use a time literal anywhere you would use a unitless integer or real number to represent
       time.
       This example uses time literals to specify procedural and intra-assignment delays.
        Immediate Assertions
             A procedural assert statement
                Similar to an if statement
                                                               always
                                                               always @(negedge
                                                                       @(negedge clock)
                                                                                 clock)
                Ignored by synthesis                            A1:
                                                                 A1: assert !(wr_en &&
                                                                      assert !(wr_en && rd_en);
                                                                                        rd_en);
         May be labeled
                                                                                          immediate assertion
                Access label via %m formatter
         27   CADENCE CONFIDENTIAL
       11/6/2009                                SystemVerilog for Verification                                  27
       Immediate assertions are similar to if statements. The assertion succeeds if the asserted expression
       in unambiguously true, and fails if the assertion expression is false or unknown. Upon assertion
       failure, the tool must display the following minimum information:
          The file name and line number of the assertion;
          The assertion label, or if unlabelled, the scope of the assertion;
          The severity level of the assertion; and
          The simulation time at which the assertion failed.
       --------
       IEEE Std. 1800-2005 SystemVerilog LRM, Section 17.2
        Action Blocks
        You can provide an “action”
        block to execute upon success,                          always
                                                                always @(negedge
                                                                        @(negedge clock)
                                                                                  clock)
                                                                  rw_chk:
                                                                  rw_chk: assert
                                                                           assert !(wr_en
                                                                                  !(wr_en &&
                                                                                          && rd_en)
        failure or both                                             $display  ("%m:
                                                                                             rd_en)
                                                                                    success");
                                                                    $display ("%m: success");
                                                                  else
          else branch executes on                                else
                                                                  begin
                                                                  begin
               assertion failure                                    $display("read/write
                                                                    $display("read/write fail");
                                                                                          fail");
                                                                    err_count++;
                                                                    err_count++;
                                                                    ->
                                                                    -> rw_err_event;
                                                                        rw_err_event;
                                                                  end
                                                                  end
                                                                always
                                                                always @(negedge
                                                                       @(negedge clock)
                                                                                   clock)
                                                                  assert
                                                                  assert (valid)
                                                                          (valid)
                                                                  //
                                                                  // pass
                                                                     pass block
                                                                           block omitted
                                                                                  omitted
                                                                  else
                                                                  else $display("valid inactive");
                                                                       $display("valid    inactive");
                                                         always
                                                         always @(posedge
                                                                @(posedge clock)
                                                                          clock)
                                                           limit_check:
                                                           limit_check: assert
                                                                        assert (err_count
                                                                               (err_count << 14)
                                                                                             14)
                                                           else
                                                           else $display("errors >=
                                                                $display("errors >= 15");
                                                                                    15");
         28   CADENCE CONFIDENTIAL
       11/6/2009                              SystemVerilog for Verification                             28
       You can associate an action block with the assertion. In the action block, you place code to execute
       on either the success or the failure of an assertion. The pass block executes if the assertion
       succeeds. The fail block executes if the assertion fails. You have the option to include neither,
       either or both. It is very common to omit the pass block and just include the fail block.
Note in this example the use of the “percent m” (%m) formatter to display the assertion label.
        Severity Levels
         The action block may override the
              default reporting behavior
                $info                                            always
                                                                  always @(negedge
                                                                          @(negedge enable)
                                                                                    enable)
                                                                    assert
                                                                    assert (valid)
                                                                            (valid)
                $warning                                           else
                                                                    else
                                                                    begin
                                                                    begin
                $error                                               $warning("invalid
                                                                      $warning("invalid enable");
                                                                                         enable");
                       Default                                       err_count++;
                                                                      err_count++;
                                                                    end
                                                                    end
                $fatal
                       Terminates simulation
         29   CADENCE CONFIDENTIAL
       11/6/2009                                SystemVerilog for Verification                            29
       Assertion severity is error by default. The simulator reports assertion failure as an error and
       “should” return from execution with a non-zero error code. You can override the default severity
       by using these system tasks in the action block. You may use these system tasks only in an action
       block. The fatal severity has the effect of terminating the simulation. These system tasks accept the
       same arguments you would use with the $display system task. Just remember that prior to your
       own output you will also see all the other assertion failure information.
                                                                                                                 $error("short
                                                                                                                 $error("short CE  CE pulse");
        Extra code required – as if we had                                                                       disable    CHECK;
                                                                                                                 disable CHECK;
                                                                                                                                      pulse");
        used if                                                                                                end
                                                                                                                end
                                                                                                            @(posedge
                                                                                                             @(posedge CLK);
                                                                                                                          CLK);
          Timing controls                                                                                 end
                                                                                                           end
                                                                                                          assert
                                                                                                          assert (( !CE!CE &&
                                                                                                                            && !SCLK
                                                                                                                               !SCLK ))
          Loops                                                                                           else    //  long
                                                                                                           else // long pulsepulse
                                                                                                            $error("long
                                                                                                             $error("long CE  CE pulse");
                                                                                                                                 pulse");
                                                                                                         end  :  CHECK
                                                                                                         end : CHECK
         always
         always @(posedge
                 @(posedge CLK
                             CLK iff
                                 iff CE)
                                       CE)                sequence
                                                          sequence SCYC;
                                                                   SCYC;
          begin  :  CHECK
          begin : CHECK                                     (CE
                                                            (CE &&
                                                                && SCLK)
                                                                   SCLK) ##1
                                                                         ##1 (CE
                                                                             (CE &&
                                                                                 && !SCLK);
                                                                                    !SCLK);
           repeat
           repeat (16)
                    (16)                                  endsequence
                                                          endsequence
            begin
            begin
             assert
              assert (( CE
                        CE &&
                            && SCLK
                                SCLK ))                   SPI1
                                                          SPI1 :: assert
                                                                  assert property
                                                                          property ((   @(posedge
                                                                                        @(posedge CLK)
                                                                                                   CLK)
               else  // short  pulse
               else // short pulse                        !CE
                                                          !CE ##1 CE |-> SCYC[*16]
                                                              ##1  CE |->  SCYC[*16]    ##1
                                                                                        ##1 !CE
                                                                                            !CE );
                                                                                                );
                ...
                ...
             @(posedge
              @(posedge CLK);
                          CLK);
             assert
              assert (( CE
                        CE &&
                            && !SCLK
                               !SCLK ))
               else  // short  pulse
               else // short pulse
                ...
                ...
             @(posedge
              @(posedge CLK);
                          CLK);
            end
            end
           assert
           assert (( !CE
                      !CE &&
                           && !SCLK
                              !SCLK ))
            else
            else //// long
                      long pulse
                            pulse
             $error("long
              $error("long CECE pulse");
                                pulse");
          end
          end :: CHECK
                 CHECK
       Immediate assertions have limited functionality. They perform only an instantaneous boolean
       check, and so require extra code for complex or temporal checks. This extra code can be
       substantial, even for a simple protocol. The complexity of the assertion code can be comparable to
       that of the design, and require as much debugging.
       SystemVerilog also has concurrent assertions. They provide a syntax with which to concisely state
       complex multi-cycle design properties. This training module will further discuss only concurrent
       assertions.
                                                                         SystemVerilog
        join_none
                                                                            fork             a b       c       d
                                                                            fork
          Parent process does not block                                       a;b;c;
                                                                               a;b;c;
                                                                            join_none
                   All blocks left running                                 join_none
                                                                            d;
                                                                            d;
       With the conventional Verilog fork-join, all forked processes must complete before the procedure
       can continue.
       SystemVerilog adds the join_any and join_none variants:
          With join_any, the parent procedure continues when any forked process completes.
          With join_none, the parent procedure continues without waiting for any forked processes to
           complete. As join_none allows the parent procedure to continue while forked processes are still
           running, SystemVerilog adds statements to control forked processes from outside the
           fork…join_none statement.
       --------
       IEEE Std. 1800-2005 SystemVerilog LRM, Section 11.6
completes
                                                                   fork
                                                                   fork
        The wait fork statement stops                                a;b;c;
                                                                     a;b;c;
        further execution until all forked                         join_any
                                                                   join_any               a   b     c
        blocks complete                                            fork                       d          e
                                                                   fork
                                                                     d;
          Affects all forks in current                              d;
                                                                   join_none
                                                                   join_none
              scope                                                                                     wait
                                                                                                        fork
                                                                   e;
                                                                   e;
                                                                                                        f
                                                                   wait
                                                                   wait fork;
                                                                        fork;
                                                                   f;
                                                                   f;
       The disable fork statement terminates all sub-processes of the procedure that executes the
       statement.
       Using a fork...join_any with a later disable fork allows a SystemVerilog testbench to spawn several
       concurrent processes to wait for separate events, for example separate system interrupts, and as
       soon as one event is received, terminate the other outstanding processes to handle the received
       event.
       The wait fork statement causes the executing procedure to wait until all of its sub-processes have
       completed.
       With the combination of join_any, join_none, and wait fork, you can model complex concurrent
       and serial behavior. The lower example illustrates this. The parent procedure spawns three
       subprocesses, and upon the earliest to complete, spawns another subprocess and continues with its
       own execution. Note that without timing controls, no statement execution order between the parent
       and spawned processes is implied. At a later point where the parent needs the results from all
       subprocesses, it waits for all to complete before continuing its own execution.
       --------
       IEEE Std. 1800-2005 SystemVerilog LRM, Section 11.8
        Method                                                 Description
        static function process self()                         Return handle of calling process
        function state status()                                Return state of process
         enum state { FINISHED, RUNNING, WAITING, SUSPENDED, KILLED };
        task await()                                           Wait for a process to terminate
                                                               Note: Illegal to wait for self
        function void suspend()                                Suspend a process
        function void resume()                                 Resume a suspended process
        function void kill()                                   Forcibly terminate a process
       A process is a built-in class. As we have not yet discussed classes, you may want to review these
       notes after you have studied the chapter about classes. Briefly, a class describes data and methods
       that every object of that class has. Class methods typically manipulate the data that belongs to the
       class object for which the method is called.
       SystemVerilog creates the process object either statically, for example for initial and always
       blocks, or dynamically, for fork blocks. A variable of the process type is a handle for one of these
       process class objects. You obtain a process’s handle value by calling its self() method from within
       the process. The process can then store that handle value somewhere accessible to other processes,
       that can then manipulate the state of that process.
        Unions
        You use a union to store different data types at the same memory location.
        The union size is the size of its largest field.                             Fields of a packed
                                                                                     union must be all
         union                                                                       the same size.
          union {{
            logic
            logic [31:0]
                   [31:0] udata;
                          udata; //
                                 // unsigned
                                    unsigned data
                                             data
            integer  sdata;
            integer sdata;       //
                                 // signed data
                                    signed data
         }} inbus,
            inbus, outbus;
                    outbus;      //
                                 // 32-bit
                                    32-bit variables
                                           variables
         inbus.udata
         inbus.udata == 32’h00f3;
                         32’h00f3;
         outbus.sdata
         outbus.sdata = -44;
                       =  -44;
         typedef
          typedef union
                   union {{
                                int
                                 int i;
                                      i;
                                shortreal
                                 shortreal f;f;
                             }} num;
                                 num; //
                                       // named
                                           named union
                                                  union type
                                                         type
         num
          num n1,
               n1, n2;
                    n2;      //
                              // instances
                                  instances of
                                             of union
                                                 union type
                                                        type
         n1.f
          n1.f == 0.0;
                   0.0; //
                         // set
                             set n1
                                  n1 in
                                      in floating
                                          floating point
                                                    point format
                                                           format
         n2.i  =  -44;  //  set  n2  in  integer
          n2.i = -44; // set n2 in integer format format
       The union construct provides a way to view the same memory location as different data types
       without the need to cast the data types. The SystemVerilog union is identical to the C union, with
       two exceptions:
          First: You cannot provide a tag name for a SystemVerilog structure or union. You can
           alternatively use the typedef keyword to declare a type name for the structure or union.
          Second: You can further qualify the SystemVerilog union as “tagged”. A SystemVerilog tagged
           union is type-checked. The next slide has an example of a tagged union.
       --------
       IEEE Std. 1800-2005 SystemVerilog LRM, Section 4.11
       The IEEE draft standard P1800/D9 proposes to allow fields of a packed union to be different sizes
       if the union is also tagged so as to specify what size field is currently in use.
        Union Example
        Structures can contain unions and unions can contain structures.
         typedef
         typedef struct
                 struct {{
                                  union
                                  union {{
                                           int
                                           int i;
                                                i;
                                           shortreal
                                           shortreal f;f;
                                        }} n;
                                           n; //
                                               // anonymous
                                                   anonymous union
                                                             union type
                                                                    type
                                  bit
                                  bit isfloat;
                                      isfloat;
                               }} tagged_s;
                                  tagged_s; //// named
                                                 named struct
                                                        struct type
                                                               type
         tagged_s
         tagged_s a[9:0];
                  a[9:0]; //array
                          //array of
                                  of structure
                                     structure containing
                                               containing union
                                                          union
         typedef
         typedef union
                 union tagged
                       tagged {{
                                    int
                                    int i;
                                        i;
                                    shortreal
                                    shortreal               f;
                                                            f;
                                 }} tagged_u;
                                    tagged_u;
         tagged_u   value;  int j;  shortreal
          tagged_u value; int j; shortreal                  g;
                                                            g;
         value
          value == tagged
                   tagged ff 3.14156;
                             3.14156;
         gg == value.f;
               value.f; //
                        // legal
                            legal
         jj == value.i;
               value.i; //
                        // illegal
                            illegal
       The top example declares an array of a named structure type that contains a field that is a union.
       The other structure field is a bit that indicates whether the structure union field is currently being
       used as an int type or as a float type.
       SystemVerilog provides the tagged union qualifier to serve exactly that purpose. A tagged union
       stores both its current value and its current tag. Subsequent expressions accessing the tagged value
       must be of the current tag type. This type checking is generally done during run time.
        Summary
         With the string type, you can create and manipulate messages
            without having to worry about string sizes
         With time literals, you explicitly specify the time unit, which makes your
            code more robust and more readable
         Immediate assertions simplify verification and error checking
              Concurrent assertions provide more capability, as you will see …
       Pause here for a moment, and review what you have learned about the simple SystemVerilog
       verification features.
        About Lab 1
        For this lab you debug a 8X32 synchronous memory design.
        The lab introduces the design you will use for several subsequent labs.
        It uses no new verification features – you can do this lab any time.
clk
Verification Blocks
Chapter 3
November 6, 2009
        Topics
          Event scheduler
 Programs
 Final blocks
 Clocking blocks
       A simulation timeslot is divided into ordered regions to provide a predictable interaction between
       design constructs.
       The Verilog event schedule has four regions for each simulation time:
          The Active region is for executing process statements.
          The Inactive region is for executing process statements postponed with a “pound zero” (#0)
           procedural delay.
          The NBA region is for updating non-blocking assignments.
          The Monitor region is for executing $monitor and $strobe and for calling user routines
           registered for execution during this read-only region. You cannot within this region create
           additional events.
       The first three of these regions are iterative – they can schedule events that require return to the
       Active region. When no more events exist for the current simulation time, the simulator executes
       Monitor statements and then advances simulation time to the next time for which events are
       scheduled. The simulation terminates when no such future events exist.
       SystemVerilog adds regions to provide a predictable interaction between assertions, design code
       and testbench code. It adds the Observed region in which to evaluate assertions, and the Re-Active
       and Re-Inactive regions in which to execute assertion action blocks and testbench programs.
       The SystemVerilog event schedule has 13 regions for each simulation time. Some regions used
       only by the PLI are not shown on the slide and not described here:
          The Preponed region is for sampling signal values before anything in the time slice changes
           their values.
          The Active region is for executing interface and module process statements. It is the same as
           for Verilog.
          The Inactive region is for executing interface and module process statements postponed with a
           “pound zero” (#0) procedural delay. It is the same as for Verilog.
          The NBA region is for updating non-blocking assignments. It is the same as for Verilog.
          The Observed region is for assertion evaluation.
          The Reactive region is for executing program process statements and assertion action blocks.
          The Re-inactive region is for executing program process statements postponed with a “pound
           zero” (#0) procedural delay.
          The Postponed region is for system tasks that record signal values at the end of the time slice.
       The Active through Re-inactive regions are iterative. Most of these regions can schedule events
       that require return to the Active region.
       --------
       IEEE Std. 1800-2005 SystemVerilog LRM, Section 9.3
        Programs: program
        A new separately-compilable unit similar to a                        module
                                                                             module top;
                                                                                    top;
        module:                                                                clkgen
                                                                               clkgen cgen(clk);
                                                                                       cgen(clk);
                                                                               mem_interface
                                                                               mem_interface intfc(clk);
                                                                                               intfc(clk);
          Intended to separate test and design                                mem_design
                                                                               mem_design dut (intfc);
                                                                                           dut  (intfc);
                   Cannot instance or embed other units                       mem_test
                                                                               mem_test    tb
                                                                                           tb (intfc);
                                                                                                (intfc);
                                                                             endmodule
                                                                             endmodule :: top
                   Cannot have always, specify, etc.                                     top
       A program cannot contain hierarchy and cannot have an always block, but is otherwise similar to a
       module, with some additional restrictions. It is intended to remove testbench stimulus from the
       module construct and instead execute those statements in the Reactive region separately from the
       execution and update of design code. To further reduce the potential for user-induced clock/data
       races, the program construct requires the user to make only blocking assignments to program
       variables and only non-blocking assignments to module and interface variables.
       --------
       IEEE Std. 1800-2005 SystemVerilog LRM, Section 16
                    final
                    final begin
                           begin
                      if  (timeout_error)
                      if (timeout_error)
                         $display
                         $display ("ERROR:
                                  ("ERROR: %0t:
                                            %0t: Test
                                                 Test Timed
                                                       Timed Out",
                                                             Out", $time);
                                                                   $time);
                      else
                      else
                         $display
                         $display ("INFO:
                                  ("INFO: %0t:
                                           %0t: Test
                                                Test Complete",
                                                      Complete", $time);
                                                                 $time);
                      $display("Error
                      $display("Error Count:
                                       Count: %d",
                                               %d", error_count);
                                                     error_count);
                      $display("Fifo
                      $display("Fifo Overflow
                                      Overflow Count:
                                                Count: %d",
                                                        %d", fifo_overflow);
                                                             fifo_overflow);
                    end
                    end
       A final block cannot consume simulation time, but is otherwise similar to an initial block. You can
       place a final block anywhere you can place an initial block. SystemVerilog executes all final
       blocks exactly once at the end of simulation, in an unspecified but repeatable order.
       SystemVerilog executes the final blocks upon encountering $finish or upon running out of events
       to process. Any final block that itself calls $finish or calls a user-defined system task or function
       that terminates the simulation (invokes tf_dofinish() or vpi_control(vpi_finish…)), aborts
       execution of the final blocks. After SystemVerilog completes or terminates execution of the final
       blocks, it calls any PLI routines you have scheduled for execution at the end of the simulation.
       --------
       IEEE Std. 1800-2005 SystemVerilog LRM, Section 10.7
                             clocking
                             clocking cb
                                       cb @(posedge
                                          @(posedge clk);
                                                    clk);
                               input
                               input dout;
                                      dout;
                               output
                               output reset,
                                       reset, enable,
                                              enable, data;
                                                      data;
                             endclocking
                             endclocking
       A clocking block defines a set of timing, relative to a specified clock, for a set of signals. Any
       number of signals may appear in any number of clocking blocks. You declare a clocking block as
       an interface, module or program item. You can declare one clocking block in any scope to be the
       default clocking block for that scope. You apply the timing by referencing the signal hierarchically
       through the clocking block name.
       --------
       IEEE Std. 1800-2005 SystemVerilog LRM, Section 15
                                    clocking
                                    clocking cb
                                             cb @(posedge
                                                @(posedge clk);
                                                          clk);
                                                                                  default timing skew
                                       default
                                       default input
                                               input #1step
                                                      #1step                       for inputs/outputs
                                               output
                                               output #3;
                                                       #3;
                      input to
                   clocking block      input
                                       input dout;
                                              dout;
                                       output
                                       output reset,
                                               reset, data;
                                                       data;
                                       output
                                       output negedge enable;
                                               negedge  enable;
                    outputs from                                                           SystemVerilog
                   clocking block   endclocking
                                    endclocking                        explicit           keywords in bold
                                                                    timing skew
       A clocking block is both a declaration and instance of that declaration. You do not instantiate a
       clocking block.
       Pause here for a moment, and examine the clocking block syntax.
       --------
       clocking_declaration ::=
           [ default ] clocking [ clocking_identifier ] clocking_event ;
              { clocking_item }
           endclocking [ : clocking_identifier ]
       The IEEE draft standard P1800/D9 proposes to move output transitions to a new “Re-NBA” region
       after the Re-Inactive region.
                                                                           clocking
                                                                           clocking cb
                                                                                     cb @(posedge
                                                                                        @(posedge clk);
                                                                                                    clk);
                                                                             default  input  #1step
                                                                             default input #1step
                                                                                      output
                                                                                      output #3;
                                                                                              #3;
           clk                                                               input
                                                                             input dout;
                                                                                    dout;
                                                                             output
                                                                             output reset,
                                                                                     reset, data;
                   0        5                     10                                         data;
                                                                             output
                                                                             output negedge enable;
                                                                                     negedge  enable;
                           dout        reset enable                        endclocking
                                                                           endclocking
                                        data
           def                                                           clocking
                                                                         clocking cb
                                                                                  cb @(posedge
                                                                                     @(posedge clk);
                                                                                               clk);
           two                                                             output
                                                                           output         def;
                                                                                          def;
                                                                           output
                                                                           output #2
                                                                                  #2      two;
                                                                                          two;
           neq
                                                                           output negedge neg;
                                                                           output negedge neg;
                     @(cb) #1 // same result as                          endclocking
                                                                         endclocking
                         @(cb) @(negedge clk)
                                                                         initial
                                                                         initial
           def                                                             begin
                                                                           begin
                                                                             ...
                                                                             ... //
                                                                                 // timing
                                                                                    timing control
                                                                                           control
           two
                                                                             cb.def<=1;
                                                                             cb.def<=1;
           neq                                                               cb.two<=1;
                                                                             cb.two<=1;
                                                                             cb.neg<=1;
                                                                             cb.neg<=1;
                          @(cb) @(negedge clk) #1
                                                                           end
                                                                           end
           def
           two
           neq
       11/6/2009                               SystemVerilog for Verification                              50
       The year 2005 standard neglects to specify the clock from which the output skew is referenced.
       Most vendors drive outputs with reference to the current clock for assignments made in the same
       time slice in which the clock edge occurs.
       For this example, an output with the default “pound zero” (#0) skew is driven in the next NBA
       region of the current time slice if the assignment is scheduled in the same time slice in which the
       positive edge of the clock occurred. The first set of waveforms illustrates this. Likewise, an output
       with the “negedge” skew is driven in the next NBA region of the current time slice if the
       assignment is scheduled in the same time slice in which the negative edge of the clock occurred.
       The second set of waveforms illustrates this.
       You can use either of two methods to declare a clocking block to be the default clocking block of
       the scope:
          You can directly declare a default clocking block; or
          You can declare an already declared clocking block to be the default clocking block.
       Only one default clocking block can exist in a module, interface or program.
       A default clocking block is valid only in the scope declaring it and any nested declarations.
       --------
       IEEE Std. 1800-2005 SystemVerilog LRM, Section 15.11
          @(cb.dout)                                                              5   8 10
                   @(posedge clk iff cb.dout)                            clk
       To apply the timing of a clocking block, you hierarchically reference the signal through the
       clocking block name.
       To synchronize a process to a clocking block, you can either:
          Directly use the clocking block name in a sensitivity list. This triggers the sensitive process on
           the clocking block clock event.
          Use clocking block signal inputs, or slices of them, in a sensitivity list. This triggers the
           sensitive process on the clocking block signal event.
       --------
       IEEE Std. 1800-2005 SystemVerilog LRM, Sections 15.9, 15.13
       The semantics of the cycle delay (##N) operator differ depending upon how you use it:
          When used as a procedural or intra-assignment delay in an assignment to a clocking block
           signal, it refers to the clock event of the specified clocking block. These assignments must use
           the non-blocking operator.
          When not used as a procedural or intra-assignment delay in an assignment to a clocking block
           signal, it refers to the default clocking block. For this situation, the compiler shall issue an error
           if no default clocking block has been declared.
       --------
       clocking_drive ::=
              clockvar_expression <= [ cycle_delay ] expression
           | cycle_delay clockvar_expression <= expression
       The IEEE draft standard P1800/D9 proposes to make the use of cycle delay timing controls illegal
       for intra-assignment delays.
        Hierarchical Expressions
        A clocking block signal cannot be a hierarchical expression
        You can associate a clocking block signal with a hierarchical expression
                    clocking
                    clocking cb
                              cb @(posedge
                                 @(posedge clk);
                                             clk);
                      default  input #1step
                      default input #1step
                               output
                               output #3;
                                      #3;
                      input
                      input dout;
                             dout;
                      //data
                      //data associated
                              associated with
                                          with hierarchical
                                                hierarchical                    expression
                                                                                expression
                      output  reset, data  =  top.dut.data;
                      output reset, data = top.dut.data;                        //
                                                                                // Valid
                                                                                   Valid
                      //
                      // output
                         output top.dut.data;
                                 top.dut.data;                                  // Invalid
                                                                                // Invalid
                      output
                      output negedge
                              negedge enable;
                                      enable;
                    endclocking
                    endclocking
       You cannot within a clocking block directly declare a hierarchical signal. You must instead declare
       a clocking block virtual signal and associate it with an expression that references the hierarchical
       signal. The semantics of this association are much like those for a port connection – you can use
       any expression, including slices, concatenations and part selects, that you can legally connect to a
       port of that direction.
       --------
       IEEE Std. 1800-2005 SystemVerilog LRM, Section 15.4
        Summary
         What can you do with new verification blocks
          Clearly separate verification from design code with a program
                For potentially reducing user-induced races
       Pause here for a moment and review what you have learned about SystemVerilog programs, final
       blocks, and clocking blocks.
        Quiz
        1. What do the input, inout, and output clocking directions signify?
        2. How is a specific clocking block defined as the default?
        3. Given the clocking blocks, what do these delays represent?
               clocking
               clocking cb1
                         cb1 @(negedge
                             @(negedge clk);
                                        clk);        @(cb1);
                                                     @(cb1);
                 output
                 output posedge
                         posedge drive;
                                 drive;              ##2;
                                                     ##2;
               endclocking
               endclocking                           cb1.drive
                                                     cb1.drive <=
                                                               <= ##3
                                                                  ##3 1;
                                                                       1;
               clocking
               clocking cb2
                         cb2 @(negedge
                             @(negedge clk);
                                        clk);        ##3;
                                                     ##3; cb1.drive <=
                                                          cb1.drive <= 2’b10;
                                                                        2’b10;
               endclocking                           ##(j-2)
                                                     ##(j-2) cb1.drive
                                                             cb1.drive <=
                                                                        <= 1;
                                                                           1;
               endclocking
               default
               default clocking
                        clocking cb2;
                                 cb2;
               int j =  3;
               int j = 3;
Solutions in Appendix A
        About Lab 2
        For this lab you define a clocking block for the memory testbench and use
        the clocking block timing while testing the memory.
clk
Chapter 4
November 6, 2009
        Topics
          What is a Transaction?
 Transactors
 Transaction structure
          Interface review
          Interface transactors
       This chapter introduces transaction-based verification and discusses how you can use a
       SystemVerilog interface as a transactor.
        What is a Transaction?
         A transaction is a transfer of data between
           design blocks
         A transfer may be composed of many
                                                                               A                           B
           signal transitions over several cycles
         Working with data at the transaction level                               signal representation
           raises our abstraction level
                                                                       ADDR
              Transfers are easier to create, debug,                   AS
                   maintain and manage
                                                                        RW
         Transactions may have parameters                              DS
       Using transactions allow you to design and debug at a higher level of abstraction. That is, you
       develop and analyze your system-level design and test environment using transactions, rather than
       wading through a sea of signal waveforms.
       Transactions are most useful when you have well-defined interfaces for your design and test
       environment. Interface methods implement the transactions.
       The use of transactions is not a new concept. Transaction-based verification has been used for
       many years. Many HDL verification environments already do transaction-based verification.
             Stimulus
             Generator                        Transactor or TVM
                                                   do_burst_write
            ...
            proc.do_read      Transactions         address =
                                                   ff001000
            proc.do_write                          data = 00112233
                                                   00      11   22    33
            ...                                                                Signals
                                                                                         Design or DUV
                                                                                            Design
ff*
00 11 22 33
        Transactor Structure
        A transactor has three parts
          Transaction interface
                Stimulus generator             Transactions                          do_read
                   (transaction producer)                           Transaction
                                                                     Interface        do_write
                Response checker
                   (transaction consumer)
                                                                                      do_rmw
          Signal interface                                              Transactor
                DUV ports                                               Functional
                                                                           Code
          Transactor functionality
                                                                                       Signal
                Create data sequences
                   to drive signal interface                         Transactor       Interface
                                                                      or TVM
                Checks signal interface                                                          Signals
                   sequences for correct
                   operation
       For this example, a higher level wrapper module instantiates the testbench, interface, and design
       under verification.
       For more complex interfaces and transactions, you may find it easier to verify the design with
       direct access to the interface signals rather than relying solely upon interface methods. This permits
       more control over the design stimulus, for example, you can craft fork-join blocks “on-the-fly” that
       probably do not exist in the regular reusable interface methods.
       Most SystemVerilog testbenches utilize this flexible approach, using a combination of interface
       methods and testbench functionality.
        Utilizing a Modport
        You can define a modport to                            interface
                                                               interface spi_if(input
                                                                         spi_if(input clk);
                                                                                      clk);
        prevent the DUV from accessing                             logic
                                                                   logic sdi,
                                                                         sdi, sdo;
        the transaction interface                                  logic
                                                                   logic ce;
                                                                         ce;
                                                                              sdo;
       You would ideally like to define different views of the interface, to restrict what contents each user
       can access, and how that user can access that contents. For an interface, such a view is called a
       modport.
       This example interface defines one modport for the testbench, that treats the data input signal as an
       output and has access to the interface methods, and defines another modport for the design under
       verification, that treats the input signal as an input and has no access to the interface methods.
       You can define clocking blocks within an interface, and interface methods can then access design
       signals using the timing of the clocking block. Testbench modules can use the clocking block
       through a modport. The specified direction of the clocking block signals is from the perspective of
       the module connected to the modport that uses the clocking block. You would be more likely to use
       a clocking block for a module that represents testbench than for a module that represents design
       behavior.
        Virtual Interfaces
        virtual [interface] interface_type identifier;
        identifier = interface_instance;
        A virtual interface is a variable that represents an interface instance
          Your test code assigns actual interface instances to the interface
              variable at various time throughout the test
                   assignment (=) of interface instance, interface variable, or null
                   comparison (==,!=) to interface instance, interface variable, or null
 You test code can pass interface variables to tasks and functions
          Your test code procedurally accesses methods and variables (but not
              nets) of that interface instance through the interface variable
                   Each interface instance drives its own nets, through clocking blocks or
                    continuous assignments, that can reflect variable changes made by test
          Use of virtual interfaces promotes code reuse (write once, use often)
       A virtual interface is an interface variable that at various times throughout the test can represent
       different interface instances. By iterating through an array of interface variables and passing each
       element in turn to a test task, your one testbench task can test multiple instances of similar design
       blocks, each through its own interface instance.
       You can declare virtual interfaces in modules, programs, classes and packages. You can pass
       virtual interfaces by value, but not be reference, to tasks and functions.
       --------
       IEEE Std. 1800-2005 SystemVerilog LRM, Section 20.8
       This example defines an inverter interface and an inverter module and a test module. The test
       module declares two interface instances and two inverter instances and connects each inverter to its
       respective interface. It declares an interface variable and defines a test task to test the inverter
       connected to the interface that the interface variable currently represents. The test block, in turn,
       assigns each interface to the interface variable, and calls the test task to test the inverter connected
       to that interface.
        Benefits of TBV
         You can verify designs at transaction level instead of signal level
       Transaction based verification is all about doing your system-level development and verification
       with abstract transactions, without getting involved with an ocean of individual signal transitions.
       You can partition test development into stimulus, which deals solely with transactions, and the
       transactors, which do have to know about the design implementation. Personnel involved with
       stimulus development can be reasonably confident that they can reuse tomorrow, their work done
       yesterday, while the block designers continually refine their own designs.
       This methodology works only as well as your design team adheres to a top-down design flow,
       where the design specification is defined before it is implemented.
       Transaction-based verification (TBV) has been used for many years. What is relatively new is the
       increasing tool support, in simulators and waveform viewers, for the creation, recording and
       analysis of transactions, and recently developed high-level verification languages such as e,
       SystemC and SystemVerilog, that support more sophisticated transaction-based verification by
       borrowing from the software world, powerful proven concepts such as object-oriented design and
       dynamic resource generation.
        Summary
         Transaction Level Modelling raises abstraction level of the test
               Most of the test is not involved with low level signal transitions
         SystemVerilog interfaces are ideal for modelling transactors
       Pause here for a moment and review what you have learned about how SystemVerilog interfaces
       support a transaction based verification methodology.
        Quiz
        1. What is a transaction?
Solutions in Appendix A
        About Lab 3
        For this lab you use a program block, an interface and a clocking block to
        test a memory design. You move the write_mem() and read_mem()
        subroutines into the interface, thus making it a transactor.
read_mem()
clk
Classes
Chapter 5
November 6, 2009
        Topics
          Class overview
          Information hiding
          Virtual classes
          Polymorphism
       11/6/2009                               SystemVerilog for Verification                             74
       This chapter introduces the SystemVerilog Object-Oriented Programming (OOP) features, that is,
       classes and their associated features. A class is a dynamic data type, declaring data variables, but
       not nets, and methods to manipulate the data, that you can create and delete during run time. A
       class is an excellent type for representing such things as ATM cells and ethernet packets, things for
       which there might during simulation be an undetermined number of instances.
       This section describes SystemVerilog's implementation of classes and only very briefly mentions
       Object-Oriented Programming.
       --------
       IEEE Std. 1800-2005 SystemVerilog LRM, Section 7.
        Class Overview
         A class is a user-defined data type
 Inheritance
 Polymorphism
       A class is a user-defined type, that declares data variables, and methods to manipulate the data, and
       that you can dynamically create and delete during the simulation. You use classes for such things
       as transactions, where during simulation, an undetermined number may come into being and then
       disappear.
       --------
       IEEE Std. 1800-2005 SystemVerilog LRM, Section 7.3
       A class is a user data type. To use a class, you declare a variable of the class type. The variable is a
       handle that “points” to a location in memory that holds the class properties. An uninitialized handle
       has a null value. You create a class instance by calling a special class method called “new”. The
       “new” method is a function that allocates an area of memory for the class properties and places a
       pointer to that area in the class object handle variable.
       Unlike C++, SystemVerilog automatically deletes the dynamically created object, when either you
       explicitly assign the null value to the handle, or that handle “goes out of scope”, for example, when
       a subroutine that declares the handle locally, returns.
       --------
       IEEE Std. 1800-2005 SystemVerilog LRM, Section 7.4
       A SystemVerilog class handle is only somewhat like a C++ pointer. SystemVerilog, for ease of
       use, restricts what you can do with a class handle. Things you cannot do include:
          Arithmetic operations, for example incrementing and decrementing.
          Using with any arbitrary data type.
          Assigning the address of a variable.
          Dereferencing.
          Casting to any arbitrary pointer type.
       On the other hand, SystemVerilog automatically deletes class objects that your code can no longer
       access, thus helping you to prevent “memory leaks”, where you repeatedly create dynamic objects
       and forget to delete them when you no longer need them.
       --------
       IEEE Std. 1800-2005 SystemVerilog LRM, Sections 7.5, 7.26
       The class type declaration also declares class members. The members can be variables, called
       “properties”, and they can also be tasks or functions, called “methods”, to manipulate the class
       properties. You reference the members of a class object by using the “dot” (.) notation.
       --------
       IEEE Std. 1800-2005 SystemVerilog LRM, Section 7.5, 7.6
       A structure is a user-defined type, representing a collection of data. Structures offer only this
       simple data grouping mechanism. You declare nets and variables of the structure type.
       A class is a user-defined type, representing a collection of data and methods to manipulate the data.
       Classes offer Object Oriented features, such as dynamicism, data encapsulation, class inheritance,
       polymorphism, abstract classes and dynamic casting. You declare variables of the class type,
       whose value is a “handle” (pointer) to a class object. The handle is initially null. You assign to the
       variable the value returned by calling the class’ new() constructor method, which allocates memory
       for, and constructs, a class object.
       --------
       IEEE Std. 1800-2005 SystemVerilog LRM, Section 7.5, 7.6
                                                                      myClass
                                                                      myClass c2
                                                                              c2 == new;
                                                                                    new;
                                                                      initial
                                                                      initial
                                                                      begin
                                                                      begin
                                                                        c2.set(3);
                                                                        c2.set(3);
                                                                        $display("c2:
                                                                        $display("c2: %d",
                                                                                       %d", c2.get());
                                                                                            c2.get());
                                                                      end
                                                                      end
       11/6/2009                                   SystemVerilog for Verification                               80
       You can implement a class method outside of the class declaration. To do this, you must first
       prototype the method within the class declaration. A prototype is the extern keyword followed by
       the entire method header, exactly as if you were implementing the method, but without the method
       code body. You then implement the method, including the code body, outside the class declaration,
       exactly as if you were implementing it within the class declaration, but with one difference. As the
       method is not a member of the outside scope, but is a class member, you must declare its type as a
       type of the class. You do this by prefixing the method name with the class name and the scope
       resolution operator.
       --------
       IEEE Std. 1800-2005 SystemVerilog LRM, Section 7.22
        Class Constructor
        Method new is a special class method called a constructor
          Defined by default for all classes
          You can reimplement it to do initialize your class properties
                   No return type – otherwise like any other class method
                                  expcon
                                  expcon c2
                                         c2 == new;
                                               new;                  parcon
                                                                     parcon c3
                                                                            c3 == new(5);
                                                                                  new(5);
                                  //
                                  // c2.number
                                     c2.number == 55                 //
                                                                     // c3.number == 55
                                                                        c3.number
       Properties of 2-state types initially take on the 0 value and 4-state types take on the unknown value.
       You can initialize them to some other value as you declare them. To initialize properties on a per-
       instance basis requires you to reimplement the constructor. The constructor is like any other
       function, except that it does not have a return type, not even void.
       --------
       IEEE Std. 1800-2005 SystemVerilog LRM, Section 7.7
        Class Example
                                                                                Note the following:
         class
         class frame;
               frame;                                                             Initial property value
           logic
           logic [4:0]
                 [4:0] addr;
                        addr;
           logic                                                                  Constructor arguments
           logic [7:0] payload;
                 [7:0]  payload;
           bit                                                                       assigned to properties
           bit parity
               parity == 0;
                         0;
                                                                                  Constructor calls method to
            function
            function new
                      new (input
                           (input int
                                  int add,
                                      add, dat);
                                           dat);                                     get updated parity value
              addr =  add;
              addr = add;
              payload
              payload == dat;
                         dat;                                                     Application repeatedly calls
              parity
              parity == par({addr,
                        par({addr, payload});
                                    payload});                                       method to serialize frame
            endfunction
            endfunction
           function
           function bit
                    bit par
                        par (input
                             (input logic[12:0]
                                    logic[12:0] ip);
                                                ip);
             return (^ip);
             return (^ip);
           endfunction
           endfunction                           frame
                                                 frame one
                                                       one == new(add1,
                                                              new(add1, data1);
                                                                          data1);
                                                 frame
                                                 frame two
                                                       two == new(3,
                                                              new(3, 4);
                                                                      4);
           function
           function logic
                    logic [13:0]
                           [13:0] getframe();
                                  getframe();
               return({addr,
               return({addr, payload, parity});
                              payload, parity}); for
                                                 for (int
                                                     (int i=0;
                                                           i=0; i<14;
                                                                i<14; i++)
                                                                       i++) begin
                                                                             begin
           endfunction
           endfunction                             @(negedge  clk);
                                                   @(negedge clk);
         endclass
         endclass                                  serial
                                                   serial == one.getframe()[i];
                                                             one.getframe()[i];
                                                 end
                                                 end
       You can initialize class properties, and the constructor can then also update those values, usually
       using passed-in argument values. As SystemVerilog does not support method overloading, there
       can be only one implementation of each class type’s constructor.
       The frame serialization method depicted here is inefficient. A more efficient implementation would
       call the getframe method once and save the value in a local variable.
        Static Properties
        class
        class frame;
              frame;                                              Exactly one instance of a static
          static
          static int
                  int frmcount=0;
                      frmcount=0;                                 property always exists, not
          int
          int tag;
              tag;
          logic
                                                                  associated with any objects
          logic [4:0]
                 [4:0] addr;
                       addr;
          logic
          logic [7:0]
                 [7:0] payload;
                       payload;                                   This example uses a static property
          bit parity;
          bit parity;                                             to provide a unique identifier for each
                                                                  new frame
          function
          function new(input
                     new(input int
                                int add,
                                    add, dat);
                                          dat);
            addr  =  add;
            addr = add;                                              Initially 0
            payload
            payload == dat;
                        dat;
            parity
            parity = par({addr, payload});
                     = par({addr,  payload});                        Incremented by constructor
            tag
            tag == ++frmcount;
                    ++frmcount;                                                        one
          endfunction
          endfunction                                                               tag       1
                              frame
                              frame one
                                     one == new(1,
                                            new(1,                 0);
                                                                   0);              addr      1
        ...
        ...                                                                         payload   0
        endclass
        endclass              frame
                              frame two
                                     two == new(3,
                                            new(3,                 2);
                                                                   2);              parity    1   frmcount: 1
                                                                                       two
                                                                                    tag       2
                                                                                    addr      3
                                                                                    payload   2
                                                                                    parity    1   frmcount: 2
       Each class instance has its own unique copy of a “normal” property. Only one copy of a static
       property exists, and all class instances access that same copy, in fact, you can access that copy
       through the class name without having any instances of the class.
         <class_name>::<static_member>
       This example utilizes a static property so that it can assign a unique identity to each instance of the
       class. The constructor increments the frame count and assigns the new value to each instance’s tag.
       --------
       IEEE Std. 1800-2005 SystemVerilog LRM, Section 7.8
        Static Methods
        A static method knows nothing about the current object – so can access
        only static properties.
          class
          class frame;
                frame;
            static
            static int
                    int frmcount;
                         frmcount;
            int tag;                                              Access static members in two ways:
            int tag;
            logic
            logic [4:0]
                   [4:0] addr;
                          addr;                                      Through any handle of the class
            logic  [7:0]  payload;
            logic [7:0] payload;                                         type using the dot operator (.)
            bit
            bit parity;
                parity;
                                                                     Through the class type name
             function
             function new(input
                       new(input int
                                  int add,
                                      add, dat);
                                           dat);                         using the scope resolution
               addr
               addr == add;
                       add;                                              operator (::)
               payload
               payload == dat;
                          dat;
               parity
               parity == par({addr,
                         par({addr, payload});
                                     payload});                      frame
                                                                     frame one
                                                                            one == new(add1,
                                                                                   new(add1, data1);
                                                                                             data1);
               tag
               tag == ++frmcount;
                      ++frmcount;                                    frame
                                                                     frame two = new(3, 4);
                                                                            two =  new(3, 4);
             endfunction                                             int
                                                                     int frames;
                                                                          frames;
             endfunction
                                                                     initial
                                                                     initial begin
                                                                              begin
                                                                      two
                                                                      two == null;
                                                                             null;
            static
            static function
                   function int
                            int getcount();
                                 getcount();                          frames
                                                                      frames == one.getcount();
                                                                                 one.getcount(); //
                                                                                                 // 22
              return (frmcount);
              return (frmcount);                                      frames
                                                                      frames = two.getcount(); // 22
                                                                              = two.getcount();  //
            endfunction
            endfunction                                               frames
                                                                      frames == frame::getcount();
                                                                                 frame::getcount(); //
                                                                                                     // 22
          ...
          ...                                                        end
                                                                     end
          endclass
          endclass
       11/6/2009                               SystemVerilog for Verification                               84
       Only static methods can manipulate static properties, and they cannot manipulate anything other
       than static properties. You can access static methods through any handle of the class, or through the
       class name.
         <class_name>::<static_member>
       This example uses a static function to return the current frame count, which is a static property.
       --------
       IEEE Std. 1800-2005 SystemVerilog LRM, Section 7.9
       You can use the “this” keyword as a handle to the current object. Within SystemVerilog, the only
       practical application is to access class identifiers that have been locally redeclared.
       --------
       IEEE Std. 1800-2005 SystemVerilog LRM, Section 7.10
       Your class type declaration can itself declare handle variables of other class types. This is known
       as an aggregate class type.
       In this example, the tagframe class type declaration declares a handle variable of the frame class
       type. The tagframe constructor calls the frame constructor to initialize the frame object within the
       tagframe object. You can say that the tagframe object “has” a frame object, much as a truck “has”
       an engine.
       --------
       IEEE Std. 1800-2005 SystemVerilog LRM, Section 7.11
       Your class type declaration can extend the declaration of another class type. This is known as class
       inheritance. The parent class type declaration is known as the superclass or base class, and the
       extended child type declaration is known as the subclass or derived class. SystemVerilog supports
       inheritance of only a single parent class type.
       In this example, the tagframe class type declaration extends the frame class type declaration. The
       tagframe constructor calls the frame constructor to initialize the parent class’ part of its variable
       set. You can say that the tagframe object “is” a frame object, much as a truck “is” a vehicle, albeit
       one with additional properties.
       --------
       IEEE Std. 1800-2005 SystemVerilog LRM, Sections 7.11, 7.12
        Simple Inheritance
                                    super class            Subclass inherits superclass members:
        class
        class frame;
              frame;
          logic
          logic [4:0]
                [4:0]     addr;
                          addr;                                  Can add more members
          logic
          logic [7:0]
                [7:0]     payload;
                          payload;
          bit
          bit parity;
              parity;                                            Can redeclare superclass methods
          function
          function new(input
                    new(input int
                              int add,
                                   add, dat);
            addr = add;
                                        dat);              A subclass type is the superclass type –
            addr = add;
            payload
            payload == dat;
                       dat;                                   syntax to access members is identical
            parity
            parity == par({addr,
                      par({addr, payload});
                                  payload});
          endfunction
          endfunction
                                                                 e.g. a truck is a vehicle
        ...
                                                           Subclass constructor automatically calls
        ...
        endclass
        endclass
                                                              superclass constructor
                               sub- class                        For this example, entry into
                                                                    tagframe.new() immediately
        class
        class tagframe
              tagframe extends
                       extends frame;
          static
          static int
                 int frmcount;
                     frmcount;
                               frame;
                                                                    implicitly calls frame.new()
          int
          int tag;
                                                                 Why is this a problem?
              tag;
          function
          function new;
            tag
                    new;
            tag == ++frmcount;
                   ++frmcount;         Error                     tagframe
                                                                  tagframe one
                                                                           one == new;
                                                                                  new; //???
                                                                                       //???
          endfunction
          endfunction
        ...
        ...
        endclass                                                  one.addr
                                                                  one.addr == 0;
                                                                              0;
        endclass
       11/6/2009                                SystemVerilog for Verification                         88
       An object of the subclass can by default access all the members of the superclass as if they were
       members of the subclass. The subclass can redeclare superclass methods and variables, and objects
       of the subclass will by default access their own versions of those members. The subclass can also
       declare additional property and method members.
       Implicit subclass constructors, upon entry, immediately first call the constructors of their
       superclass. These implicit constructor calls do not know anything about your constructor
       arguments. If you reimplement the superclass constructor to accept arguments, then you must also
       reimplement the subclass constructor to provide those arguments to the superclass constructor.
       --------
       This example illustrates the failure to do that.
                              sub- class
        class
        class tagframe
              tagframe extends
                       extends frame;
                               frame;
          static int frmcount;
          static int frmcount;
          int
          int tag;
              tag;
                                                               tagframe
                                                               tagframe one
                                                                        one == new(add1,
                                                                               new(add1, data1);
                                                                                          data1);
                                                               tagframe two =  new(3, 4);
                                                               tagframe two = new(3, 4);
          function
          function new(input
                    new(input int
                               int add,
                                   add, dat);
                                        dat);
            super.new(add,  dat);                              one.addr
            super.new(add, dat);                               one.addr == 0;
                                                                           0;
            tag
            tag == ++frmcount;
                   ++frmcount;
          endfunction
          endfunction
        ...
        ...
       In this example, the reimplemented subclass constructor, upon entry, immediately explicitly calls
       its superclass constructor to pass “up” the initialization arguments. Use the super keyword within a
       subclass to reference the superclass version of the member methods that the subclass has
       redeclared.
       --------
       IEEE Std. 1800-2005 SystemVerilog LRM, Section 7.16
        Multi-Layer Inheritance
        You can layer inheritance to                     frame            class
                                                                           class frame;
                                                                                  frame;
                                                                                                       base class
       You can layer inheritance to an undetermined number of levels. Each subclass constructor must,
       upon entry, immediately call the constructor of its superclass, using the “super” keyword. As there
       is no such thing as “super.super”, you can reference only one higher level at a time.
       SystemVerilog class members are by default “public”, that is, code external to the class type
       declaration can access them. Data encapsulation, or “hiding”, is an important tenet of Object-
       Oriented Programming. You can declare class members “private” using the local keyword. Only
       member methods of the class type declaration can access those private members. You can declare
       other class members using the protected keyword. Only member methods of the class type
       declaration and their subclasses can access those protected members.
       In this example the frame class parity variable is protected, so only the frame class and its
       subclasses can access that variable. Application code cannot access the parity variable. The
       tagframe class frame count is local, so only methods declared within the tagframe class can access
       the frame count.
       --------
       IEEE Std. 1800-2005 SystemVerilog LRM, Section 7.17
       You can use a handle of a superclass type to “point” to objects of its subclasses. Remember that
       any of the subclass type declarations can redeclare members of its superclass, thus creating a
       hierarchy of member method implementations.
       For a “normal” method, the compiler selects which version to use based upon the handle type, so a
       handle of the superclass type, even if it “points” to a subclass object, accesses the methods declared
       in the superclass type.
       For a virtual method, the compiler creates a look-up table, so that during simulation, the method
       implementation is selected based upon the subclass type of the object that the superclass handle
       happens to “point” to during the method call, so a handle of the superclass type, if it “points” to a
       subclass object, accesses the methods declared in that subclass type. This mechanism is called
       “polymorphism”, literally, “having many forms”.
       --------
       IEEE Std. 1800-2005 SystemVerilog LRM, Section 7.20
          class
          class tagframe
                tagframe extends
                         extends frame;
                                  frame;
                                                                 Prototype only – no implementation
            ...
            ...
            function                                             Subclass provides implementation
            function logic
                     logic [13:0]
                           [13:0] getframe;
                                   getframe;
              //define for tagframe
              //define for tagframe                                     You instantiate the subclass
            endfunction
            endfunction
          endclass                      sub-class
          endclass
             class
             class errframe
                   errframe extends
                            extends tagframe;
                                     tagframe;                        frame
                                                                      frame one
                                                                             one == new(1,
                                                                                    new(1, 2);
                                                                                           2); //
                                                                                                // error
                                                                                                   error
               ...
               ...                                                    tagframe
                                                                      tagframe two
                                                                                two == new(3,
                                                                                       new(3, 4);
                                                                                               4);
               function
               function logic
                        logic [13:0]
                              [13:0] getframe;
                                      getframe;                       errframe
                                                                      errframe three
                                                                                three == new(5,
                                                                                         new(5, 6);
                                                                                                 6);
                 //define for errframe
                 //define for errframe                                frm =  two.getframe;
                                                                      frm = two.getframe;
               endfunction
               endfunction                                            frm
                                                                      frm == three.getframe;
                                                                             three.getframe;
             endclass
             endclass
       You can use the “virtual” keyword to declare a class type that cannot be instantiated. A virtual
       class type declaration would presumably declare the base variables upon which some other class
       type declaration that can be instantiated would build. A class you cannot instantiate is called an
       “abstract” class.
       Only an abstract class can declare “pure” virtual methods. A pure virtual method is a method
       declared with the virtual keyword, and prototyped, but not implemented. As it has no code body,
       you can declare it only in a class type that cannot be instantiated. A subclass type declaration must
       inherit the pure virtual method and provide its implementation. Only at a level in the class type
       declaration hierarchy where all pure virtual methods have been implemented, can you instantiate
       an object of that subclass type.
       --------
       IEEE Std. 1800-2005 SystemVerilog LRM, Section 7.19
       The IEEE draft standard P1800/D9 proposes the “pure” keyword be added to optionally indicate a
       pure virtual function.
        Class Parameters
        You can parameterize a class                  class
                                                      class stack
                                                            stack #(parameter
                                                                   #(parameter type
                                                                               type st
                                                                                    st == int);
                                                                                          int);
        declaration just like you                       local  st data[100];
                                                        local st data[100];
        parameterize an interface,                      static
                                                        static int
                                                                int depth;
                                                                    depth;
        module, or program. A parameter
                                                        task
                                                        task push(input
                                                              push(input st
                                                                          st indat...
                                                                             indat... );
        can be a value or any arbitrary                                                );
                                                          ...
        type – hence “template class”.                    ...
                                                        endtask
                                                        endtask
          You can override parameter                   task
                                                        task pop(
                                                              pop( output
                                                                   output st
                                                                           st outdat
                                                                              outdat ...
                                                                                      ... );
                                                                                          );
              values and types on an per-                 ...
                                                          ...
                                                        endtask
              instance basis                            endtask
                                                      endclass
                                                      endclass
          Methods using type
              parameters must work for all            //
                                                      // int
                                                         int stack
                                                              stack (default)
                                                                    (default)
                                                      stack
                                                      stack intstack
                                                             intstack == new;
              expected type overrides                                    new;
          Each combination of                        //
                                                      // 8-bit
                                                         8-bit vector
                                                               vector stack
                                                                      stack
              parameter types has its own             stack
                                                      stack #(logic[7:0]) bytestack
                                                            #(logic[7:0]) bytestack == new;
                                                                                       new;
              set of any static variables
                   They can share static
                    variables from an inherited
                    non-templated superclass
       11/6/2009                                  SystemVerilog for Verification                      94
       You can define a parameterized class, for example a queue, for which you can override the width,
       depth, and even the type, of the data that it contains, on a per-instance basis.
       --------
       IEEE Std. 1800-2005 SystemVerilog LRM, Section 7.23
        Summary
        With the SystemVerilog Object-Oriented testbench features, you can:
          Declare dynamic data types
                Create and destroy objects during simulation
 Covergroups
       Pause here for a moment and review what you have learned about how the SystemVerilog object-
       oriented testbench features help you to define temporary objects, such as transactions.
        Quiz
        1. What is the role of a class constructor?
4. What is inheritance?
        About Lab 4
        For this lab you explore the support
        SystemVerilog provides for object-
                                                                  counter_c
        oriented design:
                                                                  # count : int
          Class declaration                                      + new ( int )
                                                                  + putval ( int ) : void
          Class constructor                                      + getval () : int
          Class properties and class
              methods
                Class aggregates                         upcounter_c             downcounter_c
Random Stimulus
Chapter 6
November 6, 2009
        Topics
          Random and directed stimulus
          Scope randomization
          Constraints
          randcase
          randsequence
       This chapter explores SystemVerilog features for randomization of variables and randomly
       selecting statements for execution.
          4 registers
                REG0, REG1, REG2, REG3
                     15   14   13   12   11   10   9     8     7      6     5    4   3   2   1   0
                   | X | X | X |- opcode -|- reg -|- - - - - - data - - - - - - -|
       Let’s take a look at why you might want to generate random stimulus and constrain it to
       meaningful sets of values.
       The CPU instruction contains an 8-bit data field, a 2-bit register field to address four registers, and
       a 3-bit opcode field to specify one of seven immediate instructions.
             typedef
             typedef enum
                     enum {ADDI,
                          {ADDI, SUBI,
                                 SUBI, ANDI,
                                       ANDI, XORI,
                                             XORI, JMP,
                                                   JMP, JMPC,
                                                        JMPC, CALL}
                                                              CALL} opcode_t
                                                                    opcode_t ;;
             typedef
             typedef enum
                     enum {REG0,
                          {REG0, REG1,
                                 REG1, REG2,
                                       REG2, REG3}
                                             REG3} regs_t
                                                   regs_t ;;
             opcode_t
             opcode_t      opcode;
                           opcode;
             regs_t
             regs_t        regs;
                           regs;
             logic[7:0]
             logic[7:0]    data;
                           data;
             initial
             initial begin
                      begin
               //generate
               //generate stimulus
                             stimulus
               opcode
               opcode == ADDI;
                          ADDI;
               regs
               regs    == REG0;
                          REG0;
               data
               data    == 5;
                          5;
               //pass
               //pass toto transactor
                           transactor
       We can declare enumerated types for the opcode and reg values. We assume that a transactor will
       translate the opcode, reg and data values into a form where they can be applied to the design with
       the correct format and timing, all we have to do is to generate values for the three variables and
       pass them to the transactor.
        typedef
        typedef    enum
                   enum   {ADDI,
                          {ADDI,   SUBI,
                                   SUBI,     ANDI,
                                             ANDI,   XORI,
                                                     XORI,    JMP,
                                                              JMP, JMPC,
                                                                   JMPC, CALL}
                                                                         CALL} opcode_t
                                                                               opcode_t ;;
        typedef
        typedef    enum
                   enum   {REG0,
                          {REG0,   REG1,
                                   REG1,     REG2,
                                             REG2,   REG3}
                                                     REG3}    regs_t ;
                                                              regs_t ;
        opcode_t
        opcode_t      opcode;
                      opcode;                                                   Use nested loops to
        regs_t
        regs_t        regs;
                      regs;                                                     index through the
        logic[7:0]    data;
        logic[7:0]    data;
                                                                                7168 combinations
        initial
        initial
          for
          for (opcode=opcode.first();
              (opcode=opcode.first(); opcode<=opcode.last();
                                      opcode<=opcode.last(); opcode=opcode.next())
                                                             opcode=opcode.next())
            for (regs=regs.first(); regs<=regs.last(); regs=regs.next())
            for (regs=regs.first(); regs<=regs.last(); regs=regs.next())
              for
              for (data=0;
                  (data=0; data<=255;
                           data<=255; ++data)
                                      ++data)                   ADDI REG0 00 - FF
                @(posedge clk);
                @(posedge clk);                                 ADDI REG1 00 - FF
        ...
        ...                                                     ADDI REG2 00 – FF
                                                                                    ADDI   REG3   00   -   FF
                                                                                    SUBI   REG0   00   –   FF
                                                                                    SUBI   REG1   00   –   FF
                                                                                    SUBI   REG2   00   –   FF
                                                                                    SUBI   REG3   00   -   FF
                                                                                    AND1   REG0   00   –   FF
                                                                                    ...
       A simple approach uses nested loops to generate all possible values over the ranges of the three
       variables.
       The outer loop iterates over the opcode values, the middle loop over the reg addresses, and the
       inner loop over the range of data values.
       We then measure the structural and functional coverage of the 7168 patterns. Structural metrics,
       consisting of coverpoints and cover crosses in a covergroup (see a later chapter), look good – we
       have applied every possible value to each variable. Functional metrics, consisting of cover
       statements with design properties (see a later chapter), do not look good. We have missed most of
       the transitions between values.
       Applying all such transitions requires a much more complex set of stimulus loops!
       What we really want to do is to generate random sequences of operations, registers and data, and
       constrain those random combinations to meaningful combinations.
 Class-based randomization
       With randomization, you can with minimal testbench code produce large amounts of stimulus that
       thoroughly and effectively verifies the design.
       With constraints, you can restrict the generated values and value transitions to those that are
       meaningful.
       SystemVerilog offers two forms of randomization:
          Randomization of local variables, covered in this chapter, and
          Randomization of class properties, covered in the next chapter.
       A truly random sequence of values is largely useless for verification and debug of digital designs.
       For verification and debug of digital designs, we need a pseudo-random repeatable sequence.
       These sequences are generated algorithmically. The algorithm is typically a function that accepts a
       seed reference as an argument, and when called, generates a new seed, from which it returns a the
       new random value. Ensuring that the seed has the same initial value, ensures that the random
       sequence is the same.
             int
             int   value;
                   value;
             bit
             bit   [63:0]
                   [63:0] addr;
                          addr;
             value
             value == $urandom();
                       $urandom();                     //
                                                       //    32
                                                             32   bit
                                                                  bit     random
                                                                          random   number
                                                                                   number
             value  =  $urandom(8);
             value = $urandom(8);                      //
                                                       //    32
                                                             32   bit
                                                                  bit     random
                                                                          random   number
                                                                                   number with
                                                                                          with seed
                                                                                               seed
             addr
             addr == {$urandom,$urandom};
                      {$urandom,$urandom};             //
                                                       //    64
                                                             64   bit
                                                                  bit     random
                                                                          random   number
                                                                                   number
             value
             value   ==   $urandom_range(10,2);
                          $urandom_range(10,2);        //
                                                       // 32
                                                           32 bit
                                                               bit random
                                                                    random number
                                                                            number from
                                                                                    from 22 to
                                                                                             to 1010
             value
             value   ==   $urandom_range(16);
                          $urandom_range(16);          //  32  bit  random  number  from  0
                                                       // 32 bit random number from 0 to 16  to  16
             value
             value   ==   $urandom_range(1,9);
                          $urandom_range(1,9);         //
                                                        // 32
                                                            32 bit
                                                                bit random
                                                                     random number
                                                                             number from
                                                                                     from 11 to
                                                                                              to 99
       If all you want is a random integer value, you can use the new $urandom() system function to
       obtain a random unsigned 32-bit integer, or the new $urandom_range() system function to
       constrain the value to a range of values. These functions differ from the Verilog $random()
       function, in that they return unsigned values rather than signed values, and that the random
       sequences are independent of each other.
       --------
         function int unsigned $urandom [ (int seed) ] ;
         function int unsigned $urandom_range(int unsigned maxval, int
          unsigned minval=0);
       You can randomize only singular integral variables. For example, you cannot randomize unpacked
       structures, real variables, or any nets.
       --------
         [std::]randomize ( [variable_identifier_list] ) [ with
           {constraint_expression [; constraint_expression] } ] ;
        Random Stability
        Each design unit instance, class instance and process thread has its own
        independent Random Number Generator (RNG)
          Each package and instance of interface, module or program RNG is
              seeded with the implementation-dependent initial seed (usually 1)
          The RNG of each static thread or class object is upon creation seeded
              with the next random value of its parent design unit’s RNG
          The RNG of each dynamic thread or class object is upon creation
              seeded with the next random value of its parent thread’s RNG
          The RNG of thread and class objects are stable to the extent that their
              creation order and randomization order is stable
                   Add new threads and class objects and randomization calls after previous
                    threads and class objects and randomization calls or explicitly initialize the
                    RNGs
       Each design unit instance, class instance and process thread has its own independent Random
       Number Generator (RNG).
          Each package and instance of interface, module or program RNG is seeded with the
           implementation-dependent initial seed, usually 1.
          The RNG of each static thread or class object is upon creation seeded with the next random
           value of its parent design unit’s RNG.
          The RNG of each dynamic thread or class object is upon creation seeded with the next random
           value of its parent thread’s RNG.
          The RNG of thread and class objects are stable to the extent that their creation order and
           randomization order is stable.
             • To maintain random stability, add new threads and class objects and randomization calls
               after previous threads and class objects and randomization calls, or explicitly initialize the
               RNGs.
       --------
       IEEE Std. 1800-2005 SystemVerilog LRM, Section 13.13
                                                                   initial
                                                                   initial
                           self() is a static function of              //set
                           the built-in process class that
                                                                        //set aa seed
                                                                                 seed at
                                                                                      at the
                                                                                         the start
                                                                                             start
                           returns the process handle
                                                                       process::self.srandom(100);
                                                                        process::self.srandom(100);
                                                                       aa == randomize(x);
                                                                             randomize(x);
                                                                       ...
                                                                        ...
                                                                   end
                                                                   end
       This example uses the self() static function of the process class to obtain a process handle
       “pointing” to itself, and through that handle calls its srandom() function to set its random seed.
       A SystemVerilog process is a class, but severely restricted. A process is either static, created with
       the always or initial keywords; or dynamic, created with the fork keyword. You cannot instantiate a
       process, or create it on-the-fly with the new keyword. In fact, you can do very few class-like things
       with a process.
       --------
       class process;
           enum state {FINISHED, RUNNING, WAITING, SUSPENDED, KILLED};
           static function process self();
           function state status();
           function void kill();
           task await();
           function void suspend();
           task resume();
       endclass
       The initial seed of each process’ RNG is the next random value of its parent RNG. This allows you
       to declare static processes and spawn dynamic processes after all previous processes have been
       declared or spawned, without disturbing the RNG of previous processes. This also allows you to
       shuffle entire hierarchies around if you use the srandom() void function to manually set the initial
       seed of the hierarchy root.
       This example illustrates two important features:
          Hierarchical seeding – the RNG of each forked thread is seeded from the next random value of
           the parent’s thread RNG.
          Thread stability – the sequence of values for x, y and z are dependent upon their order in the
           hierarchy, but not dependent on the order of process execution.
        Constraint Blocks
        Use the with clause to attach a constraint block {…} containing:
          Constraint expressions
          Constraint expression ordering
            //type
            //type declarations
                    declarations as
                                 as before
                                    before
            opcode_t
            opcode_t    opcode;
                        opcode;
            regs_t
            regs_t      regs;
                        regs;
            logic[7:0]
            logic[7:0] data;
                        data;
            int
            int ok;
                ok;
            //
            // conditions:
                conditions: data
                            data only
                                  only between
                                       between 32
                                               32 and
                                                   and 126
                                                       126
            ok
            ok == randomize(data)
                  randomize(data) with
                                   with {data>=32;
                                        {data>=32; data<=126;};
                                                    data<=126;};
            //
            //     range:
                    range: opcode
                           opcode in
                                  in range
                                     range of
                                           of ADDI
                                                ADDI to
                                                     to     SUBI
                                                            SUBI or
                                                                 or JMP
                                                                    JMP to
                                                                        to JMPC
                                                                           JMPC
            ok
            ok     == randomize(opcode)
                      randomize(opcode) with { opcode
                                        with  {  opcode     inside {[ADDI:SUBI],[JMP:JMPC]};};
                                                            inside {[ADDI:SUBI],[JMP:JMPC]};};
            //
            // distribution:
               distribution: REG0-REG1
                             REG0-REG1 twice
                                        twice as
                                              as likely
                                                 likely as
                                                        as REG2-REG3
                                                           REG2-REG3
            ok
            ok = randomize(regs) with { regs dist { [REG0:REG1]:=2, [REG2:REG3]:=1};};
               = randomize(regs) with {  regs dist { [REG0:REG1]:=2, [REG2:REG3]:=1};};
       A constraint block can contain constraint expressions and statements defining an order in which to
       solve the constraints. The constraint expression can be almost any integral expression. It cannot
       have side-effects, so you cannot use assignment operators in a constraint expression. The functions
       you call in a constraint expression are further restricted. Refer to the LRM section 13.4.11 for those
       restrictions.
       --------
       constraint_block_item ::=
              solve identifier_list before identifier_list ;
           | constraint_expression
        Conditional Constraints
        Constraint expressions use two constructs for conditional constraints:
          implication: expression -> constraint_set
          if (expression) constraint_set [else constraint_set]
                   logic[7:0]
                   logic[7:0] data;
                               data;
                   ...
                   ...
                   //
                   // Randomize
                       Randomize data
                                 data with
                                       with values
                                             values << 100
                                                       100 when
                                                            when mode
                                                                 mode is
                                                                       is small
                                                                          small
                   //
                   // Randomize
                       Randomize data
                                 data with
                                       with values
                                             values >> 200
                                                       200 when
                                                            when mode
                                                                 mode is
                                                                       is large
                                                                          large
                   //  Don’t constrain  data  if mode  is  not small  or
                   // Don’t constrain data if mode is not small or large large
                   ok
                   ok == randomize(data)
                         randomize(data) with
                                          with
                                   {mode
                                   {mode == small
                                          ==  small ->
                                                     -> data
                                                        data << 100;
                                                                100;
                                    mode
                                    mode == large -> data >> 200;};
                                          ==  large ->  data    200;};
                   //
                   //   Payload
                         Payload can
                                 can be
                                      be constrained
                                         constrained in
                                                      in the
                                                         the same
                                                              same way
                                                                    way with
                                                                        with if/else
                                                                             if/else
                   ok
                   ok   == randomize(data)  with
                           randomize(data) with
                                     {{ if
                                        if (mode
                                           (mode ==
                                                 == small)
                                                     small) data
                                                             data << 100;
                                                                     100; else
                                                                          else
                                        if
                                        if (mode == large) data > 200; };
                                           (mode == large)  data  >  200; };
       It is very common to have the constraints upon a variable dependent upon the value of another
       variable. You can express this dependency using the SystemVerilog implication operator (->)
       and/or the if…else construct. Nothing about these constructs is specific to constraints. We mention
       them here because you will almost always use them in constraint blocks of any significant
       complexity.
       --------
       constraint_expression ::=
              expression_or_dist ;
           | expression –> constraint_set
           | if ( expression ) constraint_set [ else constraint_set ]
           | foreach ( array_identifier [ loop_variables ] ) constraint_set
           for
           for (int
               (int i=0;
                      i=0; i<50;
                            i<50; i++)
                                   i++)                      for
                                                             for (int
                                                                 (int i=0;
                                                                         i=0; i<50;
                                                                                i<50; i++)
                                                                                      i++)
             begin
             begin                                             begin
                                                               begin
                randcase
                randcase                                          randcase
                                                                  randcase
                   20
                   20 :: gen_atm;
                          gen_atm;                                   aa       :: gen_atm;
                                                                                 gen_atm;
                   30  :  gen_ethernet;
                   30 : gen_ethernet;                                aa ++ bb :: gen_ethernet;
                                                                                 gen_ethernet;
                   10
                   10 :: gen_ipv4;
                          gen_ipv4;                                  aa -- bb :: gen_ipv4;
                                                                                 gen_ipv4;
                    55 :: gen_crc_error;
                          gen_crc_error;                             bb       :: gen_crc_error;
                                                                                 gen_crc_error;
               endcase
               endcase                                           endcase
                                                                 endcase
Probability(gen_crc_error) = 5/65 ~ 8%
       You can use the randcase keyword to randomly select a statement for execution.
       You can provide different probabilities, that is, weights, for each branch.
       The randcase weights are non-negative integral expressions that may be constant or variable. An
       item that you do not weight assumes the weight of 1. A weight of 0 indicates that the item shall
       never be selected.
       --------
       IEEE Std. 1800-2005 SystemVerilog LRM, Section 13.15
       You can use the randsequence keyword to execute a random sequence of statements based on rules
       called a production list. The argument to the randsequence construct is the identifier of the
       production to start with. This defaults to the first listed production.
       Each production consists of a function declaration, with optional argument and return type
       declarations, followed by a colon, followed by rules for the production, where rules are separated
       by the bitwise OR (|) operator.
       Each rule is a production list of one or more productions, and may have a weight associated with it,
       and may have a code block associated with it.
       A code block is data declarations and statements between curley brackets ({}).
       Each randsequence construct creates its own automatic scope, which means that production
       declarations are not visible outside of the randsequence construct. Furthermore, each code block
       creates an anonymous automatic scope, so its declarations are also not visible outside the code
       block.
       The sequence in this example starts with the main production, which defines one production rule
       consisting of the arithmetic (arith), stack (stk), and last productions, in sequence. The arithmetic
       production defines the increment (inc) and decrement (dec) alternative rules, each equally likely to
       be selected. The stack production defines the push and pop alternative rules, each also equally
       likely to be selected.
       --------
       IEEE Std. 1800-2005 SystemVerilog LRM, Section 13.16.
                         randsequence
                         randsequence (( main
                                          main ))
                                                                               inc is twice as
                           main
                           main   :: arith
                                      arith stk
                                            stk last;
                                                  last;
                                                                                likely as dec
                           arith
                           arith :: inc:=2
                                      inc:=2 || dec:=1;
                                                dec:=1;
                           stk
                           stk    :: push:=3
                                      push:=3 || pop;
                                                  pop;
                           inc
                           inc    :: { do_inc(); };
                                     {  do_inc();   };                         push is thrice
                           dec
                           dec    :  {  do_dec();
                                   : { do_dec(); }; };                         as likely as pop
                           push
                           push   :: {{ do_push();
                                        do_push(); };};
                           pop
                           pop    :  {  do_pop();
                                   : { do_pop(); }; };
                           last
                           last   :: {{ do_check();
                                        do_check(); }; };
                         endsequence
                         endsequence
       You can weight production alternatives. These are the relative weights of production rules within a
       production list, and do not weight the production list itself relative to any other production list.
       --------
       IEEE Std. 1800-2005 SystemVerilog LRM, Section 13.16.1
        randsequence
        randsequence (( main
                          main ))                                                very limited
          main   :                                                              constructs in
          main    : repeat(5) arith
                    repeat(5)     arith stk
                                          stk last;
                                              last;
          arith                                                                 productions
          arith :: ifif (incr)
                        (incr) inc;
                                  inc; else
                                        else dec;
                                              dec;
          stk
          stk    :  case   (which)
                  : case (which)
                       0:
                       0: push;
                           push;
                       1:
                       1: pop;
                           pop;                                                  less limited
                    endcase;
                     endcase;                                                   constructs in
          inc
          inc    :: {{ do_inc();
                       do_inc(); }; };                                          code blocks
          dec
          dec    :  {  do_dec();
                  : { do_dec(); };  };
          push
          push   :: {{ do_push();
                       do_push(); }; };
          pop
          pop    :: {{ do_pop();
                       do_pop(); }; };
          last
          last   :: {{ do_check();
                       do_check(); };  };
        endsequence
        endsequence
       A production list may contain a restricted set of procedural constructs. It may contain the case and
       if...else constructs to make the production conditional, and may contain the repeat construct to
       repeat the production a number of times.
       Contrast this with code blocks, which may contain arbitrary procedural constructs.
                                                                       i == 1   produces    B B C
                                                                       i == 2   produces    A
       Your code blocks can use the break keyword and the return keyword to abort productions. These
       keywords have special semantics within a randsequence construct. Within a randsequence
       construct, the break keyword terminates the entire randsequence production, and not just any loop
       it happens to be in, and the return keyword terminates only the current production. As every
       production declaration is a local function declaration, and every production item is a task call, the
       code block of a production item can utilize those arguments and can return a value.
       --------
       IEEE Std. 1800-2005 SystemVerilog LRM, Sections 13.16.2, 13.16.3
           randsequence
           randsequence (( main
                             main ))
             main
             main      :  arith($urandom)
                       : arith($urandom)            {$display(arith);}
                                                    {$display(arith);} stk
                                                                        stk        last;
                                                                                   last;
             int
             int arith(int
                  arith(int i)i) :: inc(i)
                                     inc(i)         {return
                                                    {return inc;}
                                                            inc;} || dec(i)
                                                                     dec(i)        {return
                                                                                   {return dec;};
                                                                                           dec;};
             stk
             stk :: push
                      push || pop;
                              pop;
             int
             int inc(int
                  inc(int i)i) :: {{ return
                                     return         do_inc(i);
                                                    do_inc(i); };
                                                               };
             int
             int dec(int
                  dec(int i)i) :: {{ return
                                     return         do_dec(i);
                                                    do_dec(i); };
                                                               };
             push
             push : { do_push(); };
                   : {   do_push();   };
             pop
             pop :: {{ do_pop();
                         do_pop(); };};
             last
             last :: {{ do_check();
                         do_check(); }; };
           endsequence
           endsequence
       The syntax for declaring a production is similar to the syntax for declaring a function. However, a
       production is not a function; the production code block can consume time.
       The syntax for passing data to a production is similar to a task call.
       A production for which you have declared a type can return data. You return the data in the return
       statement. The data is available as the production item name after the production item “call” in the
       “calling” production.
       This example passes a random number to the arithmetic production and displays the returned value.
       The arithmetic production further exchanges this value with either the increment or decrement
       production. The increment and decrement productions each call a function to implement their
       operation.
        Summary
        With these simple randomization features, you can:
          Generate large amounts of stimulus data from compact code
                Run longer simulations with more stimulus
                    that more thoroughly tests the design
                Spend more of your own time crafting directed tests of corner cases
       You can use these SystemVerilog randomization features to easily generate large amounts of
       meaningful stimulus from very compact code, stimulus that more thoroughly tests the more easily
       controlled and observed functionality of the design, while allowing you to spend your time crafting
       directed tests to verify the less easily controlled and observed functionality of the design.
       Pause here for a moment and review what you have learned about the simple SystemVerilog scope
       randomization features.
        Quiz
        Define the output for each value of i:
                          randsequence()
                          randsequence()
                            top
                             top :: AA B;
                                        B;
                            AA   :: CC DD E;
                                           E;
                            BB   :: CC EE {{ if
                                              if (i
                                                 (i ==== 11 )) return;
                                                               return; }} D;
                                                                          D;
                            CC   :: {$display("C");        if(i  == 3) return;};
                                     {$display("C"); if(i == 3) return;};
                            DD   :: {if
                                     {if (i(i ==
                                               == 22 )) return;
                                                        return; $display("D");};
                                                                  $display("D");};
                            EE   :: {if
                                     {if (i(i ==
                                               == 00 )) break;
                                                        break; $display("E");};
                                                                 $display("E");};
                          endsequence
                          endsequence
                                      i == 0 produces ?
                                      i == 1 produces ?
                                      i == 2 produces ?
                                      i == 3 produces ?
                                                                              Solutions in Appendix A
        About Lab 5
        For this lab you randomize the data that the memory testbench writes to the
        memory. You use scope variable randomization with an in-line constraint
        block. Your constraint expressions will use “inside” expressions and
        distributions.
Chapter 7
November 6, 2009
        Topics
          Randomization of class properties
 In-line control
 Constraints
 Setting seeds
       This chapter explores randomization of class hierarchies. For this, SystemVerilog provides
       additional capabilities, such as the pre_randomize() and post_randomize() methods, enabling and
       disabling randomization on a per-property basis, and enabling and disabling individual named
       constraint blocks.
                                          class
                                          class RandClass;
                                                 RandClass;
                                            rand
                                            rand bit
                                                   bit [1:0]
                                                       [1:0] x;
                                                             x;
                                            randc  bit [1:0] y;
                                            randc bit [1:0] y;
                                          endclass
                                          endclass
                           rand                                              randc
            x: Each valid value (00,01,10,11)                 y: Each valid value (00,01,10,11)
            has an equal probability of being                 won’t repeat until all 4 values
            chosen of 1/4.                                    have been cycled through.
            01 11 00 10 // Valid                                01 11 00 10 // Valid
            01 11 01 10 // Valid                                01 11 01 10 // Error
       The following are direct quotes of portions of IEEE Std. 1800-2005 section 13.3. These portions
       are quoted here because there is no way to more concisely or better explain the rand and randc
       keywords:
          “The solver can randomize singular variables of any integral type.”
          “Variables declared with the rand keyword are standard random variables. Their values are
           uniformly distributed over their range.”
          “Variables declared with the randc keyword are random-cyclic variables that cycle through all
           the values in a random permutation of their declared range. Random-cyclic variables can only
           be of type bit or enumerated types and can be limited to a maximum size.”
          “To reduce memory requirements, implementations can impose a limit on the maximum size of
           a randc variable, but it should be no less than 8 bits.”
       --------
       IEEE Std. 1800-2005 SystemVerilog LRM, Section 13.3
                        module
                        module test;
                               test;
                          class
                          class RandClass;
                                 RandClass;                         x is a random variable
                            rand
                            rand bit
                                   bit [1:0]
                                       [1:0] x;
                                             x;
                            randc
                            randc bit
                                   bit [1:0]
                                       [1:0] y;
                                             y;                     y is a random-cyclic variable
                          endclass
                          endclass
                          RandClass
                          RandClass myRand
                                    myRand == new;
                                              new;                      Randomizes all rand
                                                                        and randc variables in
                          initial
                          initial                                       class object
                            begin
                            begin
                              int
                              int success;
                                  success;
                              success
                              success == myRand.randomize();
                                         myRand.randomize();
                            end
                            end
                        endmodule
                        endmodule :: test
                                     test
       Every class has a built-in virtual member function called randomize(), that returns an int value of 1
       to indicate successful randomization, or 0 to indicate randomization failure. You cannot redeclare
       this function.
       --------
       IEEE Std. 1800-2005 SystemVerilog LRM, Section 13.5.1
                            function
                            function void
                                       void pre_randomize;
                                            pre_randomize;
                              if
                               if (super)
                                   (super) super.pre_randomize();
                                           super.pre_randomize();
                              .. .. ..
                            endfunction
                            endfunction
                            function
                            function void
                                       void post_randomize;
                                            post_randomize;
                              if
                               if (super)
                                   (super) super.post_randomize();
                                           super.post_randomize();
                              .. .. ..
                            endfunction
                            endfunction
       The randomize() function of the class automatically calls the void pre_randomize() and
       post_randomize() functions of the class. You can redeclare these functions to do whatever you
       want to do before and after the class object is randomized.
       --------
       IEEE Std. 1800-2005 SystemVerilog LRM, Section 13.5.2
Application of pre_randomize()
                   class
                   class RandClass;
                          RandClass;
                     rand
                     rand bit
                           bit [1:0]
                                [1:0] x;
                                       x;
                     randc                                                     Overrides built-in
                     randc bit
                            bit [1:0]
                                [1:0] y;
                                       y;                                      pre_randomize()
                     function  void pre_randomize();
                     function void pre_randomize();
                       $display("x
                       $display("x was
                                     was ",x,"
                                          ",x," yy was
                                                   was ",y);
                                                       ",y);
                     endfunction
                     endfunction
                   endclass
                   endclass
                   RandClass
                   RandClass myRand
                             myRand == new;
                                       new;
                                                                               randomize()
                   initial
                   initial                                                     automatically calls
                     begin
                     begin                                                     pre_randomize()
                       int
                       int success;
                           success;                                            before randomizing
                       success                                                 variables
                       success == myRand.randomize();
                                  myRand.randomize();
                       $display("x
                       $display("x now
                                    now ",
                                        ", myRand.x,,
                                           myRand.x,,
                                 "y
                                 "y now
                                    now ",
                                        ", myRand.y);
                                           myRand.y);
                     end
                     end
       In this example, the class declaration reimplements the pre_randomize() function to display the
       values of its variables just before they are assigned their next random value.
                   class
                   class RandClass;
                          RandClass;
                     rand                                                       x, y are random variables
                     rand bit
                            bit [0:1]
                                [0:1]   x;
                                        x; //random
                                            //random variables
                                                     variables
                     randc  bit [1:0]
                     randc bit [1:0]    y;
                                        y;
                            bit
                            bit [1:0]
                                [1:0]   a,
                                        a, b;
                                           b; //
                                              // state
                                                 state variables
                                                       variables                a, b are not random variables
                   endclass
                   endclass
                   RandClass
                   RandClass myRand
                             myRand == new;
                                       new;                                     randomize x and y only.
                                                                                a and b not randomized.
                   initial
                   initial
                     begin
                     begin
                       int
                       int success;
                           success;
                                                                                randomize x only.
                       success
                                                                                y, a, b not randomized.
                       success == myRand.randomize();
                                  myRand.randomize();
                       success
                       success == myRand.randomize(x);
                                  myRand.randomize(x);                          randomize x and a only.
                       success =  myRand.randomize(x,a);
                       success = myRand.randomize(x,a);                         y and b not randomized.
                       success
                       success == myRand.randomize(a,b);
                                  myRand.randomize(a,b);
                     end
                     end
                                                                                randomize a and b only.
                                                                                x and y not randomized.
       Providing variable reference arguments to the randomize() function randomizes only those
       variables, regardless of whether you declare the variables rand or randc. Randomization of state,
       that is, non-random, variables, is performed in the normal fashion, that is, not random-cyclic.
       --------
       IEEE Std. 1800-2005 SystemVerilog LRM, Section 13.6
Application of rand_mode()
               class
               class RandClass;
                      RandClass;                                                 x and y are
                 rand
                 rand bit
                        bit [0:1]
                            [0:1]      x;
                                       x; //random
                                           //random variables
                                                    variables                    random vars
                 randc
                 randc bit
                        bit [1:0]
                            [1:0]      y;
                                       y;
                        bit [1:0]
                        bit [1:0]      a,
                                       a, b;
                                          b; //
                                             // state
                                                state variables
                                                      variables
               endclass
               endclass
                                                                              disable randomization of
               RandClass
               RandClass myRand
                         myRand == new;
                                   new;                                       all random variables of
                                                                              class object
               initial
               initial
                 begin
                 begin                                                            re-enable y
                   int
                   int success,
                       success, state;
                                 state;                                           randomization
                   myRand.rand_mode(0);
                   myRand.rand_mode(0);
                   myRand.y.rand_mode(1);
                   myRand.y.rand_mode(1);                                         y randomization
                   state
                   state == myRand.y.rand_mode();
                            myRand.y.rand_mode();                                 is enabled
                   success=myRand.randomize();
                   success=myRand.randomize();
                   state
                   state == myRand.a.rand_mode();
                            myRand.a.rand_mode();                                only y randomized
               end
               end
                                                                                 error – a is not a
                                                                                 random variable
       In this example, the class handle variable is not a class member variable, so cannot be declared
       rand. rand and randc apply only to class member variables. After disabling randomization of all
       random properties of the class object, the example re-enables randomization of one of its members.
       Subsequent randomization of the class object then randomizes only the one member variable that is
       still active.
        Constraint Blocks
        Constraints restrict the random data generation to meaningful values
        A constraint expression can be almost any integral expression
          Cannot have side effects – e.g. no assignment operators
               class
               class RandClass;
                      RandClass;
                 rand
                 rand bit
                       bit [1:0]
                            [1:0]      x;
                                        x;                                     Constrains x to the
                 randc  bit [1:0]
                 randc bit [1:0]       y;
                                        y;                                     values 01,10,11
                 constraint
                 constraint c1
                             c1 {{     xx !=
                                           != 2’b00;}
                                              2’b00;}
               endclass
               endclass
                                                                                ; after constraint
                                                                               expression but not
               RandClass
               RandClass myRand
                         myRand == new;
                                   new;                                        after constraint line
               initial
               initial
                 begin
                 begin                                                         Randomize x using
                   int
                   int success;
                       success;                                                constraint block c1
                   success
                   success == myRand.randomize();
                              myRand.randomize();
                   $display("x
                   $display("x now
                                now ",
                                    ", myRand.x,,
                                       myRand.x,,
                             "y
                             "y now ", myRand.y);
                                now ", myRand.y);
                 end
                 end
       You declare a constraint as a class member with the constraint keyword, followed by an identifier,
       followed by constraint block items enclosed within a set of curley ({}) braces. Constraint block
       items can be constraint expressions and can be statements ordering the constraint solution.
       Constraint expressions can be almost any integral expression. They are restricted to not have side
       affects, so you cannot use the assignment operators. The use of functions is also restricted. For
       these restrictions on functions please refer to section 13.4.11
       --------
       constraint_declaration ::=
              [ static ] constraint constraint_identifier constraint_block
       constraint_block ::=
              { { constraint_block_item } }
       constraint_block_item ::=
              constraint_expression
           | solve identifier_list before identifier_list ;
            class
            class RandClass;
                   RandClass;
              rand
              rand bit
                    bit [1:0]
                         [1:0]    x;
                                   x;
              randc                                                        c1 constrains x to not be 00
              randc bit
                     bit [1:0]
                         [1:0]    y;
                                   y;
              constraint
              constraint c1
                          c1 {{   xx !=
                                      != 2’b00;}
                                         2’b00;}
            endclass
            endclass
            class
            class RandClassX
                  RandClassX extends
                              extends RandClass;
              constraint
                                       RandClass;                          c2 constrains x to not be 11
              constraint c2
                         c2 {{ xx !=
                                  != 2’b11;}
                                     2’b11;}
            endclass
            endclass
            RandClassX
                                                                           object of extended class
            RandClassX myRand
                       myRand == new;
                                 new;
            initial
            initial
              begin
              begin
                int
                int success;
                    success;                                               x will be 01 or 10
                success
                success == myRand.randomize();
                           myRand.randomize();
                $display("x
                $display("x now
                             now ",
                                 ", myRand.x,,
                                    myRand.x,,
                          "y
                          "y now ", myRand.y);
                             now ", myRand.y);
              end
              end
       Constraints are class members and are inherited along with all other inherited class members.
       This example declares a class type with random variables and constraints on those random
       variables, then extends the class to add additional constraints. Objects of the extended class type
       utilize both sets of constraints.
       --------
       IEEE Std. 1800-2005 SystemVerilog LRM, Section 13.4.2
            class
            class RandClass;
                   RandClass;
              rand
              rand int
                    int x;
                        x;                                                           c1 constrains x to
              randc
              randc bit
                     bit [1:0]
                         [1:0] y;y;                                                 the set 3,7,11-20
              constraint
              constraint c1 {x inside
                           c1 {x  inside {3,
                                         {3, 7,
                                             7, [11:20]};}
                                                [11:20]};}
            endclass
            endclass
            RandClass
            RandClass myRand
                      myRand == new;
                                new;
            initial
            initial
              begin
              begin
                int
                int success;
                    success;
                success
                success == myRand.randomize();
                           myRand.randomize();
                $display("x
                $display("x now
                             now ",
                                 ", myRand.x,,
                                    myRand.x,,
                          "y now ", myRand.y);
                          "y now ", myRand.y);
              end
              end
       A constraint expression using the inside operator constrains the value of the random variable to be
       inside a list of one or more value ranges. A value range can be a single expression, or two
       expressions enclosed by square brackets ([]) and separated by a colon (:).
       --------
       constraint_expression ::=
              expression_or_dist ;
           | expression –> constraint_set
           | if ( expression ) constraint_set [ else constraint_set ]
           | foreach ( array_identifier [ loop_variables ] ) constraint_set
               class
               class RandClass;
                      RandClass;
                 rand
                 rand int
                       int x;
                            x;
                 randc
                 randc bit [1:0]
                        bit  [1:0] y;y;
                 constraint
                 constraint c1 c1 {x
                                  {x dist
                                      dist {7:=5,
                                           {7:=5, [11:20]:=3,
                                                  [11:20]:=3, [26:30]:/1};}
                                                              [26:30]:/1};}
               endclass
               endclass
       A constraint expression using the dist operator also constrains the value of the random variable to
       be inside a list of one or more value ranges. The dist operator differs from the inside operator, in
       that you can weight the value ranges. Using different weighting operators, you can apply the
       weight expression either to every value in the range, or to the range as a whole. For any range that
       consists of a single expression, either operator has the same effect. The default weight is 1.
       --------
       expression_or_dist ::= expression [ dist { dist_list } ]
       dist_list ::= dist_item { , dist_item }
       dist_item ::= value_range [ dist_weight ]
       dist_weight ::= := expression | :/ expression
             class
             class RandClass1;
                    RandClass1;                          class
                                                         class RandClass2;
                                                                  RandClass2;
               rand
                rand int
                     int x;
                          x;                               rand
                                                            rand int
                                                                   int x;
                                                                        x;
               bit
                bit mode;
                    mode;                                  bit
                                                            bit mode;
                                                                  mode;
               constraint
                constraint c1c1                            constraint
                                                            constraint c2  c2
               {{                                          {{
                  mode
                  mode ==
                       == 11 ->
                              -> xx << 100;
                                       100;                   if
                                                              if (mode
                                                                   (mode ==== 1)
                                                                              1)
                  mode ==  0  -> x  >  10000;
                  mode == 0 -> x > 10000;                        xx << 100;
                                                                       100;
               }}                                             else
                                                              else
             endclass
             endclass                                            xx >> 10000;
                                                                       10000;
                                                           }}
                                                         endclass
                                                         endclass
       It is very common to have the constraints upon a variable dependent upon the value of another
       variable. You can express this dependency using the SystemVerilog implication operator (->)
       and/or the if…else construct. Nothing about these constructs is specific to constraints. We mention
       them here because you will almost always use them in constraint blocks of any significant
       complexity.
       --------
       expression –> constraint_set
       if ( expression ) constraint_set [ else constraint_set ]
          class
          class RandClass2;
                 RandClass2;
            rand
            rand int
                  int A[];
                      A[];
            constraint
            constraint c1
                        c1 {{ foreach
                              foreach (A[i])
                                      (A[i]) (i
                                             (i <=
                                                 <= A.size()/2)
                                                    A.size()/2) ->
                                                                -> A[i]
                                                                   A[i] <=
                                                                        <= i;
                                                                           i; }}
            constraint
            constraint c2
                        c2 {{ foreach
                              foreach (A[i])
                                      (A[i]) (i
                                             (i >> A.size()/2)
                                                    A.size()/2) ->
                                                                -> A[i]
                                                                   A[i] >=
                                                                        >= i;
                                                                           i; }}
          endclass
          endclass
       You can use a loop variable to “customize” each array element’s constraint. The foreach construct
       iterates over the elements of an array. This is especially useful for an array for which you do not
       know the size. Of course you can always just use the size() method to obtain the size.
       --------
       foreach ( array_identifier [ loop_variables ] ) constraint_set
       Class variables declared rand are evaluated simultaneously, and then constraints are applied to
       select the valid subset of all possible combinations. This can cause almost all candidate solutions to
       be discarded. For example, solving for a bit and an int gives 233 different combinations. Only one
       of those satisfies the constraint that the int must be 0 if the bit is 1.
       You can control the solution order by using the solve…before… statement. If you solve the bit
       constraint first, the int will be unconstrained half the time. The other half of the time, the solver
       needs to try only 232 combinations, at worst, and intelligent implementations will recognize that
       there really isn’t any more solving to do.
       Keep in mind the following restrictions:
          You cannot order randc variables.
             • The solver solves randc variables first, then ordered rand variables, then unordered rand
               variables.
          You can order only rand variables of integral types.
          You must avoid circular dependencies (e.g {solve a before b; solve b before c; solve c before
           a;})
       --------
       IEEE Std. 1800-2005 SystemVerilog LRM, Section 13.4.9
       You can disable and re-enable all constraints of the class object, or just individual constraints.
       --------
       IEEE Std. 1800-2005 SystemVerilog LRM, Section 13.8
Application of constraint_mode()
           class
           class RandClass;
                  RandClass;                                               blue constrains x to not 00
             rand
             rand bit
                   bit [0:1]
                       [0:1] x;
                              x;
             constraint
             constraint blue {x
                         blue    {x       !=
                                          !=   2’b00;}
                                               2’b00;}
             constraint
             constraint green
                         green {x{x       !=
                                          !=   2’b11;}
                                               2’b11;}
           endclass
           endclass                                                       green constrains x to not 11
           RandClass
           RandClass myRand
                     myRand == new;
                               new;
       This example declares two constraint block members of the class. It disables all constraints of the
       class object, then enables just one of the constraints of the class object. The other constraint
       remains disabled.
                  this.srandom(seed)                              RandClass
                                                                  RandClass myRand
                                                                            myRand == new(7);
                                                                                      new(7);
                    or just srandom(seed)
                                                                  initial
                                                                  initial
          Use to get different random                              begin
                                                                    begin
              sequences with each run
                                                                      int
                                                                      int success;
                                                                          success;
                                                                      success
                                                                      success == myRand.randomize();
                                                                                 myRand.randomize();
          Use to preserve random sequences                           myRand.srandom(9);
                                                                      myRand.srandom(9);
              between hierarchy changes                               success
                                                                      success == myRand.randomize();
                                                                                 myRand.randomize();
                                                                    end
                                                                    end
       This example passes an initial random seed into the class object’s constructor. The constructor calls
       the object’s srandom() method to set the random seed, overriding the initial random seed obtained
       from its parent module. The test process later changes the object’s seed again, this time calling the
       srandom() method through the class variable.
       --------
       IEEE Std. 1800-2005 SystemVerilog LRM, Section 13.12.3
        Summary
        With these class randomization features, you can:
          Generate large amounts of stimulus data from compact code
                Run longer simulations with more stimulus
                    that more thoroughly tests the design
                Spend more of your own time crafting directed tests of corner cases
       Pause here for a moment and review what you have learned about the SystemVerilog class
       randomization features.
        Quiz
        The randomize call randomizes which variables?
        class ClassC;
          rand int intC;
          real realC;
          rand ClassB objB = new;
        endclass
Solutions in Appendix A
        About Lab 6
        For this lab you randomize the data that the memory testbench writes to the
        memory. You use class property randomization with an in-class constraint
        block. Your constraint expressions will use “inside” expressions and
        distributions. You will weight the distribution of data values and solve for
        data values before solving for address values.
Covergroup Coverage
Chapter 8
November 6, 2009
        Topics
          Introduction to functional coverage
 Simple coverage
          Cross products
          Coverage options
       Code coverage automatically measures whether, and potentially how many times, a line, statement,
       block or branch has executed. More advanced code coverage can measure whether, and potentially
       how many times, an expression term has a chance to control the outcome of the expression. Code
       coverage does not automatically check transitions between design states, as the transition space is
       extremely large
       That sort of check may be important. You, as the designer, may know that two consecutive
       SUBTRACT operations followed by a DIVIDE operation has caused an overflow error on previous
       designs similar to yours. This is where user-directed functional coverage becomes imperative.
       Functional coverage, as the name suggests, checks whether the test exercises the functionality of
       the design. You identify the critical combinations and sequences that should be exercised to verify
       the design functionality.
         covergroup
         covergroup cg cg @(posedge
                            @(posedge clk);
                                        clk);                     property
                                                                  property req_gets_gnt;
                                                                            req_gets_gnt;
            Addr:
             Addr: coverpoint addr
                    coverpoint     addr                             @(posedge
                                                                    @(posedge clk)
                                                                               clk)
            {{ bins
                bins low
                      low     == {{ [0:’h0F],
                                    [0:’h0F], 1919 };
                                                    };                req
                                                                      req |-> ##[1:$] gnt;
                                                                           |-> ##[1:$] gnt;
                bins
                bins mid[] = { 16, 17, 18 };
                      mid[]   =  {  16, 17,  18  };               endproperty
                                                                  endproperty
                bins
                bins high
                      high == {{ [’h14:’hFF]
                                    [’h14:’hFF] };}; }}           cover
                                                                  cover property
                                                                        property (req_gets_gnt);
                                                                                  (req_gets_gnt);
            AddrXvalid    :  cross   Addr,
             AddrXvalid : cross Addr, valid;valid;
         endgroup
         endgroup
         cg
         cg cg1
              cg1 == new;
                     new;
          The simulator measures whether (and optionally how many times) the
              test has caused the design variables of interest to hit or sequence
              through those scenarios
          It is purely a testbench construct – no concern about synthesis!
       Working with the design specification, you develop a test plan highlighting those data values,
       combinations of values, and sequences of values, whose occurrence provides an indication of how
       thoroughly the test exercises the design. You then translate those test plan items into the
       SystemVerilog data-oriented functional coverage syntax. The simulator keeps these counts and
       saves them in a database for an analysis tool to present to you.
        Automatic Bins
        The simulator tracks occurrences
        of coverpoint values – on each                         module
                                                               module example;
                                                                       example;
        sample clock it increments the                           logic
                                                                 logic clk;
                                                                        clk;
        associated “bin”. By default:                            logic
                                                                 logic [2:0] opcode;
                                                                        [2:0]  opcode;
                                                                 logic  [7:0] address;
          One for each coverpoint value                         logic [7:0] address;
                   Up to a preset limit                           covergroup
                                                                   covergroup cg1
                                                                              cg1 @(posedge
                                                                                  @(posedge clk);
                                                                                             clk);
          Named auto[<value>]                                       c1: coverpoint opcode;
                                                                     c1: coverpoint opcode;
                                                                     c2:
                                                                     c2: coverpoint
                                                                         coverpoint address;
                                                                                    address;
                                                                   endgroup : cg1
                                                                   endgroup : cg1
                                                                 cg1
                                                                 cg1 cover_inst
                                                                     cover_inst == new;
                                                                                   new;
                                                                 ...
                                                                 ...
                                                               endmodule
                                                               endmodule
       SystemVerilog by default automatically creates a single bin for every value in the coverpoint
       variable range. These are called automatic, or implicit, bins. For an enumerated coverpoint, there is
       one bin for each valid value. For an integral coverpoint variable, the number of automatic bins is at
       most 2M where M is the number of bits required to represent the variable. When 2M is greater than
       the preset limit, the values are distributed as evenly as possible, with the last bin getting any extra
       values. Later slides show how to define bins and how to change the preset limit for automatic bin
       creation.
       --------
       IEEE Std. 1800-2005 SystemVerilog LRM, Section 18.4.2
        Explicit Bins
        You can define the bins yourself:
          To track only a subset of                            c1:
                                                                c1: coverpoint
                                                                     coverpoint             var1
                                                                                            var1 {{
               values                                             bins
                                                                   bins VV == {1,
                                                                              {1,           2,
                                                                                            2, 5}
                                                                                               5} ;;
          To control what values                                 }}
               increment which bin
                                                                          bin V increments for var1 = 1, 2 or 5
          bin name
                                                         {{   [0:5],
                                                              [0:5], 10
                                                                      10 }}          --   values
                                                                                          values 0-5
                                                                                                  0-5 and
                                                                                                       and 10
                                                                                                            10
                                                         {{   [0:5],
                                                              [0:5], [9:14]
                                                                      [9:14]    }}   ––   values  0-5  and  9-14
                                                                                          values 0-5 and 9-14
          list of value ranges                          {{   ’h1,
                                                              ’h1, ’h2,
                                                                   ’h2, ’hF
                                                                          ’hF   }}   ––   values
                                                                                          values 1,
                                                                                                  1, 2,
                                                                                                      2, 15
                                                                                                         15
                                                         {{   [1:9], [7:12]
                                                              [1:9], [7:12]     }}   ––   range
                                                                                          range overlap allowed
                                                                                                overlap    allowed
                   a range can be a single value        {{   [16:$]
                                                              [16:$] }}              --   range
                                                                                          range 16
                                                                                                 16 to
                                                                                                    to max
                                                                                                        max value
                                                                                                             value
                   occurrence of listed value
                     increments bin
       You can explicitly declare bins enclosed in curley braces ({}) immediately after the coverpoint
       identifier. Note that if you do not explicitly specify coverpoint bins or options, you terminate the
       coverpoint declaration with a semicolon, but if you do explicitly specify coverpoint bins or options,
       you instead terminate each bin or option specification itself with a semicolon.
       --------
       IEEE Std. 1800-2005 SystemVerilog LRM, Section 18.4
       A scalar bin is one bin that counts occurrences of any of the values in its open range list.
       A vector bin is an array of bins, by default one array element for each unique value in the open
       range list.
               logic
               logic [3:0]
                     [3:0] var1;
                           var1;
               ce:
                ce: coverpoint
                    coverpoint var1
                                  var1 {{
                  illegal_bins
                  illegal_bins aa == {{ 0,0, 15
                                             15 };
                                                 };         //
                                                            //        11   bin
                                                                           bin for
                                                                                for illegal
                                                                                     illegal values
                                                                                              values
                  ignore_bins     b  = {  [13:15]
                  ignore_bins b = { [13:15] };     };       //
                                                            //        11   bin for   ignored  values
                                                                           bin for ignored values
                  bins
                  bins cc    == {{ 2,
                                    2, 33 };
                                          };                //
                                                            //        11   bin
                                                                           bin for
                                                                                for 2,
                                                                                     2, 33
                  bins
                  bins d[2]
                        d[2] == {{ [9:11],
                                    [9:11], 9,
                                             9, [12:15]
                                                 [12:15] };
                                                         }; //
                                                            //        22   bins
                                                                           bins - d[0] == {9,10,11,9}
                                                                                 -  d[0]    {9,10,11,9}
                                                            //
                                                            //                   -- d[1]
                                                                                    d[1] == {12}
                                                                                            {12}
                  bins e[]   =  {  [0:2],   2,
                  bins e[] = { [0:2], 2, 6 };  6  };        //
                                                            //        33   bins
                                                                           bins e[1], e[2], e[6]
                                                                                 e[1],  e[2],  e[6]
                  bins f
                  bins f     =  default;
                              = default;                    //
                                                            //        11   bin for   4,5,7,8
                                                                           bin for 4,5,7,8
               }}
         153   CADENCE CONFIDENTIAL
       11/6/2009                                SystemVerilog for Verification                            153
       a) The illegal_bins keyword specifies bins for illegal values. The simulator does not cover these
          values even if they appear in other bins, and issues an error upon occurrence of the illegal
          values.
       b) The ignore_bins keyword specifies bins for ignored values. The simulator does not cover these
          values even if they appear in other bins, but does not issue an error upon their occurrence
          unless they are also illegal values.
       c) A scaler bin is one bin for all the specified values.
       d) For a vector bin of a specified size, the values are distributed as evenly as possible by their
          appearance in the open range list, with the last bin getting any extra values. Duplicate values
          are retained, so can show up in multiple bins. Illegal and ignored values are removed after the
          values are distributed.
       e) For a vector bin of an unspecified size, the values are distributed each to their own bin. The
          standard implies this to mean unique values, with duplicate values not retained. Illegal and
          ignored values are removed after the values are distributed. Here, that results in an empty bin
          (e[0]), which is removed.
       f) The default keyword specifies bins for values that do not appear in any other bins. You cannot
          use the illegal_bins or ignore_bins keywords with the default keyword.
              module
              module example_with_bins;
                      example_with_bins;
              logic
              logic clk;
                     clk;
              logic
              logic [2:0]
                     [2:0] opcode;
                            opcode;
              logic
              logic [15:0]
                     [15:0] address;
                            address;                                                   How many bins in
                                                                                ?      this covergroup?
              covergroup
              covergroup cg1
                           cg1 @(posedge
                               @(posedge clk);
                                                                              Question What are their names?
                                           clk);
                 c1:
                 c1: coverpoint
                      coverpoint opcode;
                                   opcode;                                             Answers in appendix A
                 c2:
                 c2: coverpoint
                      coverpoint address
                                   address {{
                       bins
                        bins low[]
                             low[] == {{ [0:’h0F]
                                         [0:’h0F] }} ;;
                       bins
                        bins high = { [’h10:’hFF] }} ;;
                             high   = {  [’h10:’hFF]
                     }}
              endgroup
              endgroup :: cg1
                           cg1
              cg1
              cg1 cover_inst
                  cover_inst == new();
                                new();
              ...
              ...
              endmodule
              endmodule
        Cross Coverage
        You can track cross-products of:
          Coverpoints within the covergroup
                                                                   logic
                                                                   logic [1:0]
                                                                         [1:0] veca,
                                                                                veca, vecb;
                                                                                      vecb;
                                                                   ...
                                                                   ...
          Other scope variables                                   covergroup
                                                                   covergroup cg1
                                                                               cg1 @(posedge
                                                                                   @(posedge clk);
                                                                                             clk);
                   Creates implicit coverpoint                      c1: coverpoint  veca;
                                                                     c1: coverpoint veca;
                   Participates in cover cross                      c2:
                                                                     c2: coverpoint
                                                                         coverpoint vecb;
                                                                                     vecb;
                                                                     crossab:
                                                                     crossab: cross c1, c2;
                                                                               cross c1,
                   No coverage data reported for                                        c2;
                                                                   endgroup :  cg1
                    variable                                       endgroup : cg1
                                                                                            c1.auto[0]
                                                                                                         c1.auto[1]
                                                                                                                      c1.auto[2]
                                                                                                                                   c1.auto[3]
        Use the cross keyword, and provide a:
          cross name (optional)
          list of coverpoints and/or variables                                c2.auto[0]
                                                                               c2.auto[1]
                                                                               c2.auto[2]
                                                                               c2.auto[3]
       You can declare cover crosses of two or more already declared coverpoints within the covergroup
       and/or other integral variables. SystemVerilog automatically creates “virtual” coverpoints for cover
       cross variables for which you did not declare a coverpoint. It does not report coverage data for
       these “virtual” coverpoints.
       --------
       IEEE Std. 1800-2005 SystemVerilog LRM, Section 18.5
        reg
        reg [1:0]
             [1:0] a;
                    a;
        reg [3:0]
        reg [3:0] b;b;
        reg
        reg c;
             c;
        covergroup
        covergroup cgcg @(posedge
                         @(posedge clk);
                                     clk);
          bcp:
          bcp: coverpoint
                 coverpoint bb {{
              bins
               bins b1
                    b1    == {{ [9:12]
                                [9:12] };
                                       };       //one
                                                //one bin
                                                      bin       b1
                                                                b1
              bins
               bins b2[]
                    b2[] == {{ [13:15]
                                [13:15] };
                                        };      //3
                                                //3 bins:
                                                    bins:       b2[13],
                                                                b2[13], b2[14],
                                                                        b2[14], b2[15]
                                                                                b2[15]
              bins  restofb[]    = default;
               bins restofb[] = default;        //9
                                                //9 bins:
                                                    bins:       [0]
                                                                [0] ... [8] not in cross
                                                                    ... [8] not in cross
            }}
          ccp:
          ccp: coverpoint
                 coverpoint c; c;               //
                                                //   two
                                                     two automatic
                                                          automatic bins
                                                                     bins
          AxBxC:
          AxBxC: cross a, bcp, ccp;
                   cross  a,   bcp, ccp;        //
                                                //   32
                                                     32 bins = a(4) xx bcp(4)
                                                         bins = a(4)    bcp(4) xx ccp(2)
                                                                                  ccp(2)
        endgroup
        endgroup :: cg
                     cg
       This example declares a cover cross of one variable and two previously declared coverpoints:
          The variable has four possible values for which four “virtual” bins are automatically created.
          The first declared coverpoint has one explicit scalar bin, and one explicit vector bin containing
           three elements, for a total of four bins.
          The second coverpoint has two possible values for which two bins are automatically created.
       The cover cross thus has 32 automatic bins, one for each combination of coverpoint bins that make
       up the cross.
       Pause here and examine this cross coverage example.
                                                                   endgroup
                                                                   endgroup :: cgcg
                                                                          x1 = <cp2.mid,cp1.A[0], cp2.mid,cp1.A[1],
        cp2.high                                                                cp2.mid,cp1.A[2], cp2.mid,cp1.A[3]>
         cp2.mid                                                  x1      x2 = <cp2.low,cp1.A[2], cp2.mid,cp1.A[2]>
         cp2.low                                                  x2
       SystemVerilog by default automatically creates a single bin for every product of the cover cross. It
       does not include any default coverpoint bins or any declared as illegal or to ignore.
       You can explicitly declare cover cross bins enclosed in curley braces ({}) immediately after the list
       of coverpoints to cross. As with coverpoint bins, if you do not explicitly specify cover cross bins or
       options, you terminate the cover cross declaration with a semicolon, but if you do explicitly specify
       cover cross bins or options, you instead terminate each bin or option specification itself with a
       semicolon.
       You do not specify an open value range for a cover cross bin. Instead you use the binsof keyword
       to select those coverpoint bins that should participate in the cross, optionally filtered to an open
       value range with the intersect keyword. You can then perform conjunction, disjunction and
       negation operations on the resulting bin selections.
       The example declares the cover cross bin “x1” to include the bins of coverpoint “cp2” that contain
       the values 8 through 10, so only the “mid” bin of coverpoint “cp2” participates in the “x1” cover
       cross bin. The example declares the cover cross bin “x2” to include the “A[2]” bin of coverpoint
       “cp1” conjoined with the negation of the “high” bin of coverpoint “cp2”.
       Pause here and examine this selection of cross coverage bins.
       --------
       IEEE Std. 1800-2005 SystemVerilog LRM, Section 18.5
                                                                               ignore_bins    x4  = binsof(cp1.A[1]);}
                                                                               ignore_bins x4 = binsof(cp1.A[1]);}
                                                                           endgroup
                                                                           endgroup :: cg
                                                                                       cg
x4
       As with coverpoint bins, you can declare cover cross bins to be illegal or to be ignored. Coverpoint
       bins that participate in a cover cross bin to be ignored are removed from any other cover cross bin
       where they may otherwise participate. Coverpoint bins that participate in an illegal cover cross bin
       are also removed from any other cover cross bin where they may otherwise participate.
       Furthermore, the simulator must issue an error upon the occurrence of any such illegal cross-
       product.
       This example declares the cross coverage bin “x3” to exclude the bins of coverpoint “cp2” that
       contain the values 0 through 2, and the cross coverage ignore bin “x4” that removes from all cross
       bins the bins of coverpoint “cp1.A[1]”.
       Pause here for a moment to ensure you understand the effect of ignore and illegal bins.
       --------
       IEEE Std. 1800-2005 SystemVerilog LRM, Sections 18.5.2, 18.5.3
        Covergroup Options
        You can specify options to control the behavior
        of covergroups, coverpoints and cover crosses.                                         type option
                                                                        int a, b;
        Each of these constructs has two built-in                       int a, b;
                                                                        covergroup
                                                                        covergroup cg1
                                                                                    cg1 @(posedge
                                                                                        @(posedge clk);
                                                                                                   clk);
        structures:                                                       c1: coverpoint  a {
                                                                          c1: coverpoint a {
          Type-specific (static) options                                   type_option.comment
                                                                            type_option.comment == "a";}
                                                                                                     "a";}
                                                                          c2: coverpoint  b;
                                                                          c2: coverpoint b;
                  struct {)                                             endgroup
                                                                        endgroup :: cg1
                                                                                    cg1
                    ...
                  } type_option;                                        cg1::type_option.comment
                                                                        cg1::type_option.comment == "ab";
                                                                                                    "ab";
                                                                        cg1 one = new;
                                                                        cg1 one = new;
          Instance-specific options
                                                                                            instance option
                  struct {                                            int a, b;
                                                                      int a, b;
                    ...                                               covergroup
                                                                      covergroup cg1
                                                                                  cg1 @(posedge
                                                                                      @(posedge clk);
                                                                                                   clk);
                  } option;                                             c1: coverpoint  a
                                                                        c1: coverpoint a {{
                                                                          option.auto_bin_max
                                                                          option.auto_bin_max == 10;}
                                                                                                    10;}
                                                                        c2: coverpoint  b;
                                                                        c2: coverpoint b;
         See field definitions on following slides…                   endgroup
                                                                      endgroup :: cg1
                                                                                  cg1
                                                                      cg1
                                                                      cg1 one
                                                                          one == new;
                                                                                 new;
                                                                      one.c2.option.auto_bin_max
                                                                      one.c2.option.auto_bin_max == 256;
                                                                                                    256;
       11/6/2009                              SystemVerilog for Verification                              159
       The built-in covergroup base class declares for the covergroup, coverpoint, and cover cross, static
       structures named “type_option” with options that you set for the covergroup type, and automatic
       structures named “option” with options that you can modify for each covergroup instance. Within
       the covergroup declaration, you can reference these fields hierarchically as you would for any class
       member structure. You can later procedurally set most instance-specific options for each individual
       instance of the covergroup.
       --------
       IEEE Std. 1800-2005 SystemVerilog LRM, Section 18.6
       You set type-specific options only within the covergroup definition. Type-specific weight, goal and
       comment options you set at the covergroup level do not affect the values set at the coverpoint or
       cover cross level. You can also set weight, goal and comment options as instance-specific options.
       The next slide describes the instance-specific options.
          Set the weight field to modify the relative weight of the coverpoint or cover cross when
           calculating the enclosing covergroup coverage metric, and the relative weight of the
           covergroup when calculating the overall coverage metric, for a type-based coverage report.
          Set the goal field to modify the target goal for the element. The standard does not state how the
           vendor should use this field.
          Set the comment field to provide a string you want included in the coverage report.
          Set the strobe field to defer sampling to the end of the time slot, to where the $monitor and
           $strobe system tasks execute.
       --------
       IEEE Std. 1800-2005 SystemVerilog LRM, Section 18.9
       You can set instance-specific options within a covergroup definition, and except for the per_instance option, can also
       set them for each individual instance of the covergroup. Instance-specific options other than weight, goal and comment
       that you set at the covergroup level provide new default values for coverpoint and cover cross options for which you do
       not set a value.
          Set the name field to provide a name for the covergroup instance. The simulator generates a unique name for each
           covergroup instance for which you do not supply a name.
          Set the weight field to modify the relative weight of the coverpoint or cover cross when calculating the enclosing
           covergroup coverage metric, and the relative weight of the covergroup when calculating the overall coverage
           metric, for an instance-based coverage report.
          Set the goal field to modify the target goal for the element. The standard does not state how the vendor should use
           this field.
          Set the comment field to provide a string you want included in the coverage report.
          Set the at_least field to modify the hit count for considering a bin covered.
          Set the auto_bin_max field to modify the maximum number of bins to be automatically created.
          Set the cross_num_print_missing field to modify the number of uncovered cover cross bins that must be saved to
           the coverage database and printed in the coverage report.
          Set the detect_overlap field to have the simulator issue a warning when the values of two coverpoint bins overlap.
          Set the per_instance field to track coverage data for each covergroup instance as well as each covergroup type.
           You may want to track data on a per-instance basis if you differently parameterize each covergroup instance.
       --------
       IEEE Std. 1800-2005 SystemVerilog LRM, Section 18.9
       These are methods of the covergroup base class that you call for specific covergroup instances. The
       get_coverage() method is a static method that you can also call for the covergroup type using the
       scope resolution operator.
          Use the sample() method to force an immediate sample.
          Use the get_coverage() method to obtain the current percent coverage for all instances of the
           covergroup type. If you provide the optional reference arguments, the simulator places the
           covered bin count and total bin count in the referenced variables.
          Use the get_inst_coverage() method to obtain the current percent coverage for only the one
           specific instance of the covergroup type.
          Use the set_inst_name() method to provide a new instance name for the covergroup instance.
          Use the start() and stop() methods to start and stop collecting coverage data for the specific
           covergroup instance.
       --------
       IEEE Std. 1800-2005 SystemVerilog LRM, Section 18.7
       These are system tasks and functions that you can use to store and retrieve coverage information.
       With these routines you can display only the overall cumulative coverage calculated by covergroup
       type. As these routines are less than optimally useful, vendors typically provide proprietary means
       for managing coverage data.
       --------
       IEEE Std. 1800-2005 SystemVerilog LRM, Section 18.8
        Summary
        SystemVerilog data-oriented functional coverage with covergroups offers:
          Specification of the sampling event
          Specification of variables to sample
                Automatic and explicit binning of value counts
                    Explicit scalar and vector bins
                    Explicit bins for values and for transitions between values
                    Explicit (default) bins for unspecified values, transitions
                    Explicit bins, ignore_bins, and illegal_bins
          Specification of cross-products
                Automatic and explicit binning of cross counts
                Filtering and combining cross-product bins
       Pause here for a moment and review what you have learned about SystemVerilog data-oriented
       functional coverage.
Quiz
         bit
          bit [7:0]
               [7:0] avec,
                      avec, bvec;
                              bvec;
         covergroup
          covergroup cg cg @(posedge
                            @(posedge clk);
                                       clk);
         cpa:
          cpa: coverpoint
                coverpoint avec
                              avec
            {{ bins
               bins a1
                     a1 == {{ [0:63]
                              [0:63] };
                                     };                            How many bins in this
               bins
               bins a2 = { [64:127] };
                     a2  = {  [64:127]  };                  ?      covergroup cross c?
               bins  a3  = {  [128:191]
               bins a3 = { [128:191] };  };
                                                          Question What are their names?
               bins
               bins a4
                     a4 == {{ [192:255]
                              [192:255] };
                                         }; }}                     Solutions in Appendix A
         cpb:
          cpb: coverpoint
                coverpoint bvec
                              bvec
            {{ bins
               bins b1
                     b1 == {0};
                            {0};
               bins
               bins b2 == {{ [1:84]
                     b2       [1:84] };
                                     };
               bins
               bins b3
                     b3 == {{ [85:169]
                              [85:169] };
                                        };
               bins
               bins b4 = { [170:255] };
                     b4  = {  [170:255]  }; }}
         cc :: cross
               cross cpa,
                      cpa, cpb
                             cpb
            {{ bins
               bins c1 = ! binsof(cpa)
                     c1  = !  binsof(cpa) intersect
                                            intersect {[100:200]};
                                                      {[100:200]};
               bins
               bins c2 = binsof(cpa.a2) ||
                     c2  = binsof(cpa.a2)    || binsof(cpb.b2);
                                                binsof(cpb.b2);
               bins
               bins c3
                     c3 == binsof(cpa.a1)
                            binsof(cpa.a1) &&&& binsof(cpb.b4);
                                                binsof(cpb.b4); }}
         endgroup
          endgroup
        About Lab 7
        For lab 7 you collect and analyze data-oriented functional coverage of the
        memory address and data. You declare and instantiate a covergroup
        containing a coverpoint for the address and a coverpoint for the data and a
        cover cross of the coverpoint bins. You run the simulation and examine the
        resulting coverage data.
November 6, 2009
        Topics
          Dynamic arrays
 Associative arrays
 Queues
This chapter explores the SystemVerilog dynamic and associative arrays, and queues.
        Dynamic Arrays
        Use a dynamic array when the array size must change during the simulation
          Declare a dynamic array by leaving an unpacked dimension unsized
          Use the new[] operator to allocate and initialize (construct) the array
                   new[size] – allocates array and initializes to default initial values
                   new[size](array) – allocates array and initializes from existing array of the same
                     type (e.g. itself) when setting or changing the array size
          Dynamic arrays have the size() and delete() methods
                   function void delete() // delete all elements (sets size to 0)
                    logic
                    logic [7:0]
                           [7:0] dynarr[];
                                 dynarr[]; //
                                            // dynamic
                                               dynamic array
                                                        array of
                                                              of 8-bit
                                                                  8-bit vectors
                                                                        vectors
                    int index;
                    int index;
                    ...
                    ...
                    dynarr
                    dynarr == new[8];
                              new[8];            //initialize
                                                 //initialize
                    for
                    for (int i=0; i<8; i++) dynarr[i] == i+1;
                        (int  i=0; i<8; i++)  dynarr[i]    i+1;
                    index  = dynarr.size();
                    index = dynarr.size();       // 8
                                                 // 8
                    dynarr
                    dynarr == new[16]
                              new[16] (dynarr);
                                      (dynarr); //
                                                 // resize
                                                     resize array
                                                            array keeping
                                                                   keeping values
                                                                           values
                    index
                    index == dynarr.size();
                             dynarr.size();      //
                                                 // 16
                                                     16
                    dynarr.delete();
                    dynarr.delete();             //
                                                 // 00
       Use a dynamic array when the array size changes during the simulation. Declare the dynamic array
       by leaving an unpacked dimension unsized. Create, and re-create, the array during run time using
       the new operator. As an argument to the new operator, you can provide an existing array of the
       same type to initialize the new array. Dynamic arrays have the size() and delete() methods, as well
       as the standard array manipulation methods (see 5.15) and standard array query system functions
       (see 22.6).
       --------
       IEEE Std. 1800-2005 SystemVerilog LRM, Section 5.6
       The IEEE draft standard P1800/D9 clarifies that you can declare more than one unsized dimension,
       thus in effect declaring a dynamic array of dynamic arrays.
         parameter
         parameter num_vectors
                     num_vectors == 32;
                                     32;
         logic
         logic [7:0]
                [7:0] dyn[];
                       dyn[];                         //
                                                      // dynamic
                                                         dynamic array
                                                                  array declaration
                                                                          declaration
         bit
         bit    [4:0]  addr;
                [4:0] addr;
         logic
         logic [7:0]
                [7:0] wdata,
                       wdata, rdata;
                               rdata;
         initial
         initial begin
                  begin
           dyn
           dyn == new[num_vectors];
                  new[num_vectors];                   //
                                                      // array
                                                         array allocation
                                                                allocation size:32
                                                                             size:32
           $display("dyn.size():%d",
           $display("dyn.size():%d", dyn.size());// will print 32
                                         dyn.size());//  will  print   32
           for
           for (int
                (int i=0;
                      i=0; i<num_vectors;
                           i<num_vectors; i++)
                                            i++) begin
                                                  begin
             write_mem(i,    i+5);
             write_mem(i, i+5);
             dyn[i]
             dyn[i] == i+5;
                        i+5;                          //
                                                      // dynamic
                                                         dynamic array
                                                                  array write
                                                                          write
           end
           end
           for
           for (int
                (int i=0;
                      i=0; i<num_vectors;
                           i<num_vectors; i++)
                                            i++) begin
                                                  begin
             read_mem(i,   rdata);
             read_mem(i, rdata);
             if
             if (rdata
                 (rdata !==
                         !== dyn[i])
                              dyn[i])
                $display("Error
                $display("Error at at Addr:%h
                                      Addr:%h -- Wrote:%h,
                                                 Wrote:%h, Read:%h",
                                                           Read:%h",
                  i,  dyn[i]  rdata);
                  i, dyn[i] rdata);
           end
           end
           dyn.delete();
           dyn.delete();                              //
                                                      // deallocate
                                                         deallocate array
                                                                       array memory
                                                                             memory
           $display("dyn.size():%d",     dyn.size());//  should
           $display("dyn.size():%d", dyn.size());// should be 0  be  0
         end
         end
       This example declares a dynamic array to store 8-bit logic vectors. During run time, it allocates
       space for 32 elements. In a loop, it writes data to a memory component and stores the data in the
       dynamic memory. In a second loop, it reads data from the memory component and compares it to
       the data in the dynamic memory. It deletes the dynamic memory when finished with it.
        Associative Arrays
        Use an associative array when the data space is unbounded or sparsely populated
          Declare the array by specifying a type instead of a size for its one dimension
                   The key can be any type for which a relative order can be determined
                       Or ‘*’ to permit indexing by any integral type
           bit
           bit [3:0]
               [3:0] aa1
                     aa1 [int];
                         [int];       //
                                      //                   associative
                                                           associative array
                                                                        array of
                                                                               of 4-bit
                                                                                  4-bit      2-state
                                                                                             2-state
                                      //
                                      //                   with
                                                           with index type of int
                                                                index  type of  int
           logic
           logic [7:0]
                 [7:0] aa2
                       aa2 [integer];
                           [integer]; //
                                      //                   associative
                                                           associative array
                                                                        array of
                                                                               of 8-bit
                                                                                  8-bit      logic
                                                                                             logic
                                      //
                                      //                   with
                                                           with index type of integer
                                                                index  type of  integer
       Use an associative array when the address space is unbounded or sparsely populated. Declare the
       associative array by specifying a type instead of a size for its one dimension. The key can be any
       type for which a relative order can be determined, that is, any type to which SystemVerilog can
       apply a relational operator. Associative array elements do not exist until you assign them. You
       assign “pairs” of associated key and data values.
       --------
       IEEE Std. 1800-2005 SystemVerilog LRM, Sections 5.9 – 5.13
       The IEEE draft standard P1800/D9 adds that associative arrays using the wildcard index type shall
       not participate in a foreach loop or in an array manipulation method that returns an index value.
       Associative arrays have the num(), delete(), exists(), first(), last(), next(), and prev() methods, as
       well as the standard array manipulation methods (see 5.15) and standard array query system
       functions (see 22.6). Pause here for a moment and examine the associative array methods.
       --------
       IEEE Std. 1800-2005 SystemVerilog LRM, Section 5.10
         logic
         logic [7:0]
                [7:0] assoc[int];
                       assoc[int];               //
                                                 // associative
                                                     associative array
                                                                  array declaration
                                                                        declaration
         bit
         bit    [4:0]  rand_a;
                [4:0] rand_a;
         logic
         logic [7:0] rand_d,
                [7:0]  rand_d, rdat;
                                rdat;
         initial   begin
         initial begin
           for
           for (int
                (int i=0;
                      i=0; i<=31;
                            i<=31; i++)
                                   i++) begin
                                         begin
             success
             success == randomize(rand_a,
                         randomize(rand_a, rand_d);
                                             rand_d); //
                                                       // random
                                                          random data
                                                                  data gen
                                                                       gen
             write_mem   (rand_a,  rand_d);
             write_mem (rand_a, rand_d);
             assoc[rand_a]
             assoc[rand_a] == rand_d;
                                rand_d;           //
                                                  // associative
                                                      associative array
                                                                   array assign
                                                                         assign
           end
           end
           $display("Memory
           $display("Memory locations
                               locations to
                                          to check:%d",
                                             check:%d", assoc.num());
                                                         assoc.num());
           for  (int  i=0;  i<=31; i++)
           for (int i=0; i<=31; i++)
             if
             if (assoc.exists(i))
                 (assoc.exists(i)) begin
                                      begin       //
                                                  // only
                                                      only read
                                                           read address
                                                                 address if
                                                                         if written
                                                                             written
                read_mem(i,   rdat);
                read_mem(i, rdat);
                if
                if (rdat
                    (rdat !=
                           != assoc[i])
                              assoc[i])           //
                                                  // check
                                                      check against
                                                            against array
                                                                     array data
                                                                            data
                   $display("Error
                   $display("Error atat Addr:%h"
                                        Addr:%h" i);
                                                 i);
                assoc.delete(i);
                assoc.delete(i);                  //
                                                  // Deallocate
                                                      Deallocate memory
                                                                  memory at
                                                                         at index
                                                                             index
             end
             end
           $display("array
           $display("array size:%d",
                              size:%d", assoc.num());
                                         assoc.num()); //
                                                        // should
                                                           should display
                                                                   display 00
         end
         end
       This example declares an associative array to store 8-bit logic vectors with keys of the int type. In a
       loop, it randomizes address and data 32 times, writes the data to a memory component, and stores
       the address/data pairs in an associative memory. As the address vector is only 5 bits wide, it is very
       likely that some addresses are written multiple times. In a second loop, the example iterates
       through the potential address space. For each address, if the associative array has an entry for that
       address, it verifies that the memory component has the correct data, then deletes the entry for that
       address. Deleting entries individually is inefficient.
       This algorithm is more efficient. It utilizes associative array methods to iterate through only the
       assigned entries. It deletes the entire associative array at once when finished with it.
        Queues
        Use a queue “array” where insertion and extraction order are important
          Declare a queue by using $ as the size of its one dimension:
                  int q_int[$];
                  int q_int[$:200]; // optionally limit the queue size
          Use $ to reference the end of the queue: myInt = q_int[$];
          Queues have the size(), insert(), delete(), pop_front(),
              pop_back(), push_front() and push_back() methods
             integer
             integer           q_integer[$];
                               q_integer[$];            //
                                                        //   queue
                                                             queue      of
                                                                        of      integers
                                                                                integers
             logic
             logic [15:0]
                   [15:0]      q_logic
                               q_logic [$];
                                        [$];            //
                                                        //   queue
                                                             queue      of
                                                                        of      16-bit
                                                                                16-bit logic
                                                                                        logic
             int
             int               q_int[$:2000];
                               q_int[$:2000];           //
                                                        //   queue
                                                             queue      of
                                                                        of      int
                                                                                int –– max
                                                                                       max size
                                                                                            size of
                                                                                                 of 2000
                                                                                                     2000
             time
             time              q_time
                               q_time [$:10];
                                       [$:10];          //
                                                        //   queue
                                                             queue      of
                                                                        of      time
                                                                                time –– max
                                                                                        max size
                                                                                             size of
                                                                                                  of 10
                                                                                                      10
       Use a queue when insertion and extraction order are important. Declare the a queue by using the
       “dollar” ($) character as the size of its one dimension. You can optionally limit the queue size by
       appending a colon (:) followed by a constant expression after the “dollar” character. You can use
       the “dollar” character to represent the end of the queue in subsequent array subscript operations.
       --------
       IEEE Std. 1800-2005 SystemVerilog LRM, Section 5.14
Queue Methods
       Queues have the size(), insert(), delete(), pop_front(), pop_back(), push_front() and push_back()
       methods. Unlike the associative array, you cannot delete an entire queue in one statement. An
       index value that lies outside the current queue bounds or is otherwise invalid causes a read
       operation to return the default value for the queue type. An index value that lies outside the current
       queue bounds plus one or is otherwise invalid causes a write operation to issue a warning and not
       do the write. Indexing the element just past the current queue end for a write operation is the
       equivalent of a push_back() operation.
       --------
       IEEE Std. 1800-2005 SystemVerilog LRM, Section 5.14.2
       The IEEE draft standard P1800/D9 proposes that the delete() function delete the entire queue if no
       index argument is provided.
            initial
            initial begin
                     begin
              q_int.push_front(0);
              q_int.push_front(0);                      //
                                                        //   {0}
                                                             {0}
              q_int.push_back(1);
              q_int.push_back(1);                       //
                                                        //   {0,1}
                                                             {0,1}
              q_int.push_front(2);
              q_int.push_front(2);                      //
                                                        //   {2,0,1}
                                                             {2,0,1}
              q_int.insert(1,
              q_int.insert(1, 3);
                               3);                      //
                                                        //   {2,3,0,1}
                                                             {2,3,0,1}
              q_int.insert(3,  4);
              q_int.insert(3, 4);                       //
                                                        //   {2,3,0,4,1}
                                                             {2,3,0,4,1}
              q_int.delete(2);
              q_int.delete(2);                          //
                                                        //   {2,3,4,1}
                                                             {2,3,4,1}
              q_int.insert(2,5);
              q_int.insert(2,5);                        //
                                                        //   {2,3,5,4,1}
                                                             {2,3,5,4,1}
              data
              data == q_int.pop_back();
                      q_int.pop_back();                 //
                                                        //   {2,3,5,4}
                                                             {2,3,5,4} data
                                                                        data == 11
              data
              data == q_int.pop_front();
                      q_int.pop_front();                //
                                                        //   {3,5,4}
                                                             {3,5,4} data
                                                                       data == 22
              while
              while (q_int.size()
                     (q_int.size() >> 0)
                                      0)                //
                                                        //   checking
                                                             checking queue
                                                                       queue size
                                                                              size
                data
                data == q_int.pop_back();
                        q_int.pop_back();               //
                                                        //   loop
                                                             loop executes
                                                                   executes 33 times
                                                                                times
              q_bit.push_front(8’h01);
              q_bit.push_front(8’h01);                  //
                                                        //   {’h01}
                                                             {’h01}
              q_bit.push_back(8’h45);
              q_bit.push_back(8’h45);                   //
                                                        //   {’h01,’h45}
                                                             {’h01,’h45}
              q_bit.push_front(8’h89);
              q_bit.push_front(8’h89);                  //
                                                        //   {’89,’h01,’h45}
                                                             {’89,’h01,’h45}
            end
            end
       Queue methods support inserting and extracting elements. This example illustrates use of several of
       the methods.
           initial
           initial begin
                     begin
             q_int
             q_int = {0,q_int};
                     =  {0,q_int};                                              //
                                                                                //   {0}
                                                                                     {0}
             q_int
             q_int == {q_int,1};
                        {q_int,1};                                              //
                                                                                //   {0,1}
                                                                                     {0,1}
             q_int
             q_int == {2,q_int};
                        {2,q_int};                                              //
                                                                                //   {2,0,1}
                                                                                     {2,0,1}
             q_int   =  {q_int[0],3,q_int[1:$]};
             q_int = {q_int[0],3,q_int[1:$]};                                   //
                                                                                //   {2,3,0,1}
                                                                                     {2,3,0,1}
             q_int
             q_int == {q_int[0:2],4,q_int[3]};
                        {q_int[0:2],4,q_int[3]};                                //
                                                                                //   {2,3,0,4,1}
                                                                                     {2,3,0,4,1}
             q_int   =  {q_int[0:1],q_int[3:4]};
             q_int = {q_int[0:1],q_int[3:4]};                                   //
                                                                                //   {2,3,4,1}
                                                                                     {2,3,4,1}
             q_int
             q_int == {q_int[0:1],5,q_int[2:3]};
                        {q_int[0:1],5,q_int[2:3]};                              //
                                                                                //   {2,3,5,4,1}
                                                                                     {2,3,5,4,1}
             data
             data = q_int[$]; q_int
                   =   q_int[$]; q_int == q_int[0:$-1];
                                          q_int[0:$-1];                         //
                                                                                //   {2,3,5,4}
                                                                                     {2,3,5,4} data
                                                                                                data == 11
             data
             data == q_int[0];
                       q_int[0]; q_int
                                 q_int == q_int[1:$];
                                          q_int[1:$];                           //
                                                                                //   {3,5,4}
                                                                                     {3,5,4} data
                                                                                               data == 22
             while
             while (q_int.size()
                     (q_int.size() >> 0)
                                       0) begin
                                          begin                                 //
                                                                                //   checking
                                                                                     checking queue
                                                                                               queue size
                                                                                                      size
               data
               data == q_int[$];
                         q_int[$];                                              //
                                                                                //   loop
                                                                                     loop executes
                                                                                           executes 33 times
                                                                                                        times
               q_int
               q_int == q_int[0:$-1];
                          q_int[0:$-1]; end
                                         end
             q_bit   =  {8’h01,q_bit};
             q_bit = {8’h01,q_bit};                                             //
                                                                                //   {’h01}
                                                                                     {’h01}
             q_bit
             q_bit == {q_bit,8’h45};
                        {q_bit,8’h45};                                          //
                                                                                //   {’h01,’h45}
                                                                                     {’h01,’h45}
             q_bit   =  {8’h89,q_bit};
             q_bit = {8’h89,q_bit};                                             //
                                                                                //   {’89,’h01,’h45}
                                                                                     {’89,’h01,’h45}
           end
           end
       A queue is an array, so if you really want to, you can still use unpacked array indexing and
       concatenation to insert and extract elements. As this example illustrates, you probably don’t really
       want to. The queue methods are much more friendly.
        The iterator (default identifier item) references the current element at each
        iteration. It is visible only within the expression. See following slides...
       11/6/2009                              SystemVerilog for Verification                            179
       Built-in methods support searching, ordering, and reducing arrays. These methods apply to any
       unpacked array, with the exception that locator methods do not apply to associative arrays that use
       the wildcard index type and ordering methods do not apply to associative arrays at all. The locator
       methods return a queue and the reduction methods return a single value.
       Within the “with” expression you may refer to the current array element, using the “item” identifier
       by default, or using whatever name you pass to the method.
       Within the “with” expression you may refer to the current element’s index by using the iterator’s
       index() method and passing to it the dimension number for which you want the current index. The
       dimension number defaults to 1, that is, the first dimension.
       Array locator methods apply to any unpacked array except associative arrays using the wildcard
       index type. The min(), max(), and both unique methods further require that relational operators be
       defined for the expression to be evaluated. Where the “with” clause is optional, this expression is
       by default the array element itself.
       This example returns a queue of indexes of the strings whose last character is unique.
        Method                                                Description
        reverse()                                             Reverse array elements.
                                                              Specifying with is an error.
        sort()                                                Sort array elements (ascending).
        rsort()                                               Sort array elements (descending).
        shuffle()                                             Randomize array element order.
                                                              Specifying with is an error.
        The optional with clause specifies an alternative expression for evaluation, e.g.:
        typedef struct {string nm; int unsigned id; shortreal GPA;} student;
        student students[];
        ...
        students.rsort() with (item.GPA);
       Array ordering methods apply to any unpacked array except associative arrays. The sorting
       methods further require that relational operators be defined for the expression to be evaluated for
       sorting purposes. As this expression is by default the array element itself, for some array types you
       will want to specify some other appropriate expression.
       This example declares a dynamic array of an unpacked struct type. For sorting purposes, it uses the
       value of the GPA field of each element.
        Method                                                Description
        sum()                                                 Sum of expressions
        product()                                             Product of expressions
        and()                                                 Conjunction of expressions (bitwise)
        or()                                                  Disjunction of expressions (bitwise)
        xor()                                                 Parity of expressions (bitwise)
        The optional with clause specifies an alternative expression for evaluation, e.g.:
        int ia2d[2][2] = ’{default:2};
        int j;
        ...
        j = ia2d.product with (item.product); // 16
        Summary
        Features of SystemVerilog arrays allow efficient and flexible definition,
        storage and access to large test data sets
          Dynamic arrays useful for contiguous data which varies in size during
              simulation
                Track an undetermined number of dynamic objects
Pause here for a moment and review what you have learned about SystemVerilog arrays.
        Quiz
        Match the array that best meets each design need:
Solutions in Appendix A
        About Lab 8
        For lab 8 you implement a “scoreboard” for the memory write transactions.
        You implement it, using a:
          dynamic array
 associative array
 queue array
Interprocess Synchronization
Chapter 10
November 6, 2009
        Topics
          Non-blocking event trigger
 Event sequences
 Event variables
          Mailboxes
          Semaphores
          module
          module test();
                  test();
            event
            event e;
                   e;
            bit
            bit clk
                 clk == 1’b0;
                        1’b0;
              always
              always @clk
                     @clk
                #5
                #5 clk
                   clk <=
                       <= ~clk;
                          ~clk;
              always
              always @e
                     @e
                $display($time);
                $display($time);
              initial
              initial begin
                      begin
                  ->>
                  ->> #3
                      #3 e;
                         e;
                  ->>
                  ->> @(posedge
                      @(posedge clk)
                                clk) e;
                                     e;
                end
                end
          endmodule
          endmodule
       SystemVerilog adds a non-blocking event trigger (->>) that schedules the event for the NBA
       region. You can use intra-assignment delays just as you do with the non-blocking assignment
       operator.
       --------
       IEEE Std. 1800-2005 SystemVerilog LRM, Section 14.5.2
                   module
                   module test();
                           test();                             module
                                                               module test();
                                                                       test();
                     event
                     event e;
                            e;                                   event
                                                                 event e;
                                                                        e;
                     integer
                     integer ii == 0;
                                   0;                            integer
                                                                 integer ii == 0;
                                                                               0;
                      always
                      always @e
                             @e                                   always
                                                                  always @e
                                                                         @e
                        $display("i
                        $display("i is
                                    is %d",i);
                                       %d",i);                      $display("i
                                                                    $display("i is
                                                                                is %d",i);
                                                                                   %d",i);
                     initial
                     initial                                     initial
                                                                 initial
                       begin
                       begin                                       begin
                                                                   begin
                           ii <=
                              <= 1;
                                  1;                                   ii <=
                                                                          <= 1;
                                                                              1;
                           ->
                            -> e;
                               e; //
                                   // blocking
                                      blocking                         ->>
                                                                        ->> e;
                                                                             e; //non-blocking
                                                                                 //non-blocking
                       end
                       end                                         end
                                                                   end
                   endmodule
                   endmodule                                   endmodule
                                                               endmodule
output i is 0 output i is 1
       The non-blocking event trigger serves the same general purpose as the non-blocking assignment –
       to prevent a race between a block that triggers the event and a block that waits for the event in the
       same delta cycle.
                             “hangs”                                            completes
          module
          module test;
                  test;                                      module
                                                             module test;
                                                                     test;
            event
            event e1,
                   e1, e2;
                        e2;                                    event
                                                               event e1,
                                                                      e1, e2;
                                                                           e2;
            initial
            initial                                            initial
                                                               initial
              begin
              begin                                              begin
                                                                 begin
                 $display("fork");
                 $display("fork");                                  $display("fork");
                                                                    $display("fork");
                 fork
                 fork                                               fork
                                                                    fork
                   @e1;
                   @e1;                                               @e1;
                                                                      @e1;
                   ->
                   -> e1;
                      e1;                                             ->>
                                                                      ->> e1;
                                                                           e1;
                   ->
                   -> e2;
                      e2;                                             ->
                                                                      -> e2;
                                                                          e2;
                   @e2;
                   @e2;                                               wait(e2.triggered);
                                                                      wait(e2.triggered);
                 join
                 join                                               join
                                                                    join
                 $display("join");
                 $display("join");                                  $display("join");
                                                                    $display("join");
              end
              end                                                end
                                                                 end
          endmodule
          endmodule                                          endmodule
                                                             endmodule
       An event is not persistent. If a process “waits” for an event after it occurs, the process can go on
       waiting forever.
       The first example illustrates this. The forked blocks can be scheduled in any order. It is very likely
       that one of the event controls is too late – its associated event has already occurred.
       The second example utilizes the non-blocking event trigger, which schedules the event for the
       NBA region, after the event control has had a chance to “wait” for that event. The example also
       illustrates use of the triggered event property, which persists to the end of the time step. If the “e2”
       event has already occurred when the “wait” statement executes, the triggered property is still true.
       --------
       IEEE Std. 1800-2005 SystemVerilog LRM, Section 14.5.4
       A process can wait for a specific sequence of events. The first listed event can alternatively be the
       triggered state of an event. The wait_order statement has characteristics very similar to a
       concurrent assertion. Occurrence in turn of each event implies that the next event in the list has not
       yet occurred and will occur before any of the later events in the list. Re-occurrence of an event has
       no additional effect. Events out of order constitute an error by default. You can change this in an
       associated action block.
       --------
       IEEE Std. 1800-2005 SystemVerilog LRM, Section 14.6
        Event Variables
        A SystemVerilog event variable is a handle “pointing” to a synchronization queue.
          You can assign and compare these handles to each other.
                   Assignment causes both to “point” to the same queue
         module
         module test;
                 test;
           event
           event e1,
                   e1, e2;
                        e2;
           initial
           initial
             fork
             fork
                #1
                #1 e2
                    e2 == e1;
                          e1; //
                              // e1,
                                 e1, e2
                                     e2 both
                                         both now
                                              now have
                                                  have                    e1
                                                                          e1 synchronization
                                                                             synchronization queue
                                                                                             queue
                #2
                #2 @e1
                    @e1 $display
                         $display ("e1
                                  ("e1 triggered");
                                        triggered");
                #2
                #2 @e2
                    @e2 $display
                         $display ("e2
                                  ("e2 triggered");
                                        triggered");
                #3  -> e2;
                #3 -> e2;     //
                              // trigger e2
                                 trigger  e2 (and
                                             (and also
                                                  also                    e1)
                                                                          e1)
             join
             join
         endmodule
         endmodule
                                                                       output   e1 is triggered
                                                                                e2 is triggered
       A SystemVerilog event variable is a handle that “points” to a synchronization queue. The queue is
       a list of processes “waiting” for the event.
       This example declares two event variables and then assigns one to the other. This makes both event
       variables “point” to the same list of processes. Processes can access this synchronization queue
       through either variable.
       --------
       IEEE Std. 1800-2005 SystemVerilog LRM, Section 14.7
         module
         module test;
                 test;
           event
           event e1,
                   e1, e2;
                       e2;
           initial
           initial
             fork
             fork
                #1
                #1 @e1
                    @e1 $display
                         $display ("e1
                                  ("e1 triggered");
                                         triggered");
                #1
                #1 @e2
                    @e2 $display
                         $display ("e2
                                  ("e2 triggered");
                                         triggered");
                #2
                #2 e2 = e1; // e1, e2 both
                    e2 =  e1; // e1,  e2  both now
                                               now have
                                                   have e1
                                                        e1 synchronization
                                                            synchronization queue
                                                                            queue
                              //
                              // e2 synchronization queue is
                                 e2  synchronization  queue  is lost
                                                                lost
                #3
                #3 ->
                    -> e2;
                       e2;    //
                              // trigger
                                 trigger e2e2 (and
                                              (and also
                                                   also e1)
                                                        e1)
             join
             join
         endmodule
         endmodule
output e1 is triggered
       What the standard refers to as “event merging” is really just the merging of the event variables.
       The source synchronization queue is assigned to the target event variable, so that both variables
       “point” to the same queue. If no other variable still “points” to the synchronization queue of the
       target variable, processes on that queue can wait forever, and the queue can be reused.
       --------
       IEEE Std. 1800-2005 SystemVerilog LRM, Section 14.7.1
         module
         module test;
                 test;
           event
           event e1;
                   e1;
           initial
           initial
             fork
             fork                                                      Event e1 is set to null
                #1
                #1 @e1
                    @e1 $display
                         $display ("e1
                                   ("e1 triggered
                                         triggered once");
                                                   once");             Synchronization
                #2  ->  e1; //  trigger  e1                            queue can be released
                #2 -> e1; // trigger e1
                #3
                #3 e1
                    e1 == null;
                          null; //
                                 // e1
                                    e1 synchronization
                                        synchronization queue
                                                        queue lost
                                                                 lost
                #4  @e1  $display  ("e1  triggered twice");
                #4 @e1 $display ("e1 triggered twice");                At time 3 e1 is null. This
                #5  ->  e1; //  nothing  happens                       may not block at all or
                #5 -> e1; // nothing happens                           may block forever
             join
             join
         endmodule
         endmodule                                         Triggering null event
                                                                              e1 has no effect
       Assigning the null value to an event variable assigns a "null" synchronization queue. This
       disassociates the variable from its previous synchronization queue. When a synchronization queue
       is no longer associated with any event variable, the simulator can reuse the queue. The effect of
       waiting on a null event is undefined. An implementation may choose to wait forever or not wait at
       all, without warning, and triggering the null event has no effect.
       --------
       IEEE Std. 1800-2005 SystemVerilog LRM, Section 14.7.2
        Mailboxes
        Mailboxes are a message-based synchronization mechanism
        Used for passing messages where order is important (FIFO)
               Any process puts mail into the mailbox
                     Blocking: put(anytype message)
                     Non-Blocking: int try_put(anytype message)
        Mailbox Methods
         Method         Description                                      Syntax
         new()          Mailbox constructor which optionally specifies   function new(int bound = 0);
                        maximum size                                     Note by default no maximum size.
         num()          Returns the number of messages currently in      function int num();
                        the mailbox
         put()          Places a message in the mailbox                  task put (<message>);
                        – blocks if mailbox full
         try_put()      Places a message in a mailbox                    function int try_put (<message>);
                        – returns 0 if mailbox full
         get()          Retrieves a message from the mailbox –           task get (ref <variable>);
                        blocks if mailbox empty
                        – error if type mismatch
         try_get()      Retrieves a message from the mailbox             function int try_get (ref <variable>);
                        – returns +int if successful
                        – returns 0 if empty
                        – returns -int if type mismatch
         peek()         Copies a message from the mailbox                task peek (ref <variable>);
                        – blocks if mailbox empty
                        – error if type mismatch
         try_peek()     Copies a message from the mailbox                function int try_peek (ref <variable>);
                        – returns +int if successful
                        – returns 0 if empty
                        – returns -int if type mismatch
                                                      6
                     sender continues as     4        7             0    receiver gets
                     receiver gets mail                                  mail at time 7
                                             5        8             1
9 2
       At time 1, the sender starts putting six messages into the mailbox, at intervals one time unit apart.
       The mailbox can hold at most four messages, so the sender blocks at time 5.
       At time 0, the receiver attempts to retrieve a message from the mailbox. At that time, the mailbox
       is empty, so the receiver waits for seven time units, and then retrieves six messages, at intervals
       one time unit apart.
       As the receiver takes messages out of the mailbox, the sender resumes putting messages into the
       mailbox.
        Typeless Mailbox
                       common declarations        A mailbox can hold messages of different types
         class
         class pkt;
                                                    Blocking get() or peek() with
                pkt;
           rand
           rand bit
                 bit    [4:0]
                         [4:0] addr;
                               addr;
           rand
           rand logic [7:0] data;
                 logic  [7:0]  data;                     incompatible variable type results in
         endclass
         endclass                                        runtime error
         mailbox
         mailbox mbox
                  mbox == new;
         typedef  enum
                           new;
                                                    Non-blocking try_get() or try_peek()
         typedef enum
          {pass,
          {pass, fail,
                  fail, hung}
                          hung} state_t;
                                state_t;
                                                         with incompatible variable type returns a
         ...
         ...                                             negative integer
                                                           Possible solution – try all types?
                         sender
        string
        string pstring;
                pstring;
        pkt
        pkt ppkt
            ppkt == new;
                    new;                            receiver
        state_t
        state_t pstatus;
                 pstatus;                 string gstring;
                                          string gstring;
        ...
        ...                               pkt
                                          pkt gpkt;
                                              gpkt;                                                     ??
        pstring
        pstring == "test
                   "test one";
                         one";            state_t
                                          state_t gstatus;
                                                  gstatus;                ok
                                                                          ok == mbox.try_get(gstring);
                                                                                 mbox.try_get(gstring);
        assert(ppkt.randomize);
        assert(ppkt.randomize);           ...
                                          ...                             if
                                                                          if (ok
                                                                              (ok << 0)
                                                                                      0) begin
                                                                                         begin
        mbox.put(pstring);
        mbox.put(pstring);                mbox.get(gstring);
                                          mbox.get(gstring);                ok
                                                                             ok == mbox.try_get(gpkt);
                                                                                   mbox.try_get(gpkt);
        mbox.put(ppkt);
        mbox.put(ppkt);                   mbox.get(gpkt);
                                          mbox.get(gpkt);                   if
                                                                             if (ok
                                                                                 (ok << 0)
                                                                                        0) begin
                                                                                           begin
        mbox.put(pstatus);
        mbox.put(pstatus);                mbox.get(gstatus);
                                          mbox.get(gstatus);                   ok  = mbox.try_get(gstatus);
                                                                               ok = mbox.try_get(gstatus);
        ...
        ...                               ...
                                          ...                             ...
                                                                          ...
        Mailbox Parameters
                            common declarations          You can type-parameterize a mailbox
         class
         class pkt;
               pkt;
           bit
           bit    [4:0]
                  [4:0] addr;
                         addr;                              Define type upon declaration
           logic  [7:0]  data;
           logic [7:0] data;                                Holds messages of that and
         endclass
         endclass
         typedef
                                                                equivalent types
         typedef enum
                  enum
          {pass,
          {pass, fail,
                  fail, hung}
                         hung} state_t;
                                state_t;                    Compiler detects type mismatch
         mailbox
         mailbox #(string) smbox == new;
                  #(string)    smbox    new;
         mailbox  #(pkt)
         mailbox #(pkt)        pmbox =  new;
                               pmbox = new;
         mailbox
         mailbox #(state_t)
                  #(state_t) tmbox
                               tmbox == new;
                                        new;
         ...
         ...                             sender
                            string
                            string pstring;
                                    pstring;
                            pkt
                            pkt ppkt
                                ppkt == new;
                                        new;                                   receiver
                            state_t
                            state_t pstatus;
                                     pstatus;                       string gstring;
                                                                    string gstring;
                            ...
                            ...                                     pkt
                                                                    pkt gpkt;
                                                                        gpkt;
                            pstring
                            pstring == "test
                                       "test one";
                                             one";                  state_t
                                                                    state_t gstatus;
                                                                            gstatus;
                            assert(ppkt.randomize);
                            assert(ppkt.randomize);                 ...
                                                                    ...
                            smbox.put(pstring);
                            smbox.put(pstring);                     smbox.get(gstring);
                                                                    smbox.get(gstring);
                            pmbox.put(ppkt);
                            pmbox.put(ppkt);                        pmbox.get(gpkt);
                                                                    pmbox.get(gpkt);
                            tmbox.put(pstatus);
                            tmbox.put(pstatus);                     tmbox.get(gstatus);
                                                                    tmbox.get(gstatus);
                            ...
                            ...                                     ...
                                                                    ...
       You can simply use a separate mailbox for each message type.
       You specify the one type a mailbox may accept, by overriding its type parameter when you declare
       the mailbox variable.
       The compiler can now detect any attempt to store or retrieve messages of an incompatible type.
       --------
       IEEE Std. 1800-2005 SystemVerilog LRM, Section 14.4
        Semaphores
        Semaphores are a key-based synchronization mechanism.
        Used for mutual exclusion, controlling access to shared resources, and
        process synchronization.
          A process requests semaphore key(s) before accessing the resource
                   Requesting more keys than a semaphore currently has can block until
                    sufficient keys are returned
                   Blocking: get(int keyCount=1)
                   Non-blocking: int try_get(int keyCount=1)
Semaphore Methods
       The new() constructor constructs a semaphore with the specified number of keys. The default value
       of its argument is 0 – no keys.
       The blocking get() requests one or more keys and suspends the calling process if the key or keys
       are not available. The blocked process resumes when sufficient keys to meet its needs are put into
       the semaphore.
       The non-blocking try_get() returns 0 if the key or keys are not available.
       The put() method puts keys into the semaphore. The user is responsible for key management, for
       example, to ensure that a process returns only those keys that it previously retrieved.
       In this example:
          At time 0, process P1 requests a key, and gets it, and accesses the resource.
          At time 1, process P2 requests a key and blocks, waiting for the key.
          At time 2, process P1 completes its resource access and returns the key.
             • Process P2 now unblocks, gets the key, and accesses the resource.
          At time 3, process P2 completes its resource access and returns the key.
       Remember the user is responsible for defining, managing and utilizing the resource. Common user
       errors include:
          Writing procedural statements that access the resource without first obtaining the requisite
           number of keys.
          Writing procedural statements that fail to return keys after completing the resource access.
          Writing procedural statements that return keys to the semaphore that they never took out of the
           semaphore.
        Summary
        This chapter explored interprocess synchronization:
          Enhanced events
                Help prevent race conditions
                Provide more control over order of execution
          Mailboxes
                Multiple-type FIFO operations with built-in blocking synchronization
          Semaphores
                Multi-purpose synchronization mechanism with built-in blocking and request
                   “weighting” with keys
Pause here for a moment and review what you have learned about interprocess synchronization.
        Quiz
        1. Where would you use the non-blocking event trigger?
Solutions in Appendix A
Chapter 11
November 6, 2009
        Topics
          DPI Overview
 Data types
 Compilation
       This chapter describes the Direct Programming Interface. It shows you how to make task and
       function import and export declarations, and how to compile and use the foreign language code
       with your SystemVerilog simulation.
                      module
                      module top;
                             top;                                        #include
                                                                         #include <stdio.h>
                                                                                  <stdio.h>
                      ...
                      ...
                      $MySystemTask
                      $MySystemTask ...
                                    ...                                  int
                                                                         int MySystemTask
                                                                             MySystemTask ...
                                                                                          ...
                      ...
                      ...                                                ...
                                                                         ...
       The PLI is a true application programming interface. Through it you can access and navigate the
       full design hierarchy, and can synchronize a C application to any point of simulation time or to any
       simulation event. With this power comes difficulty of use, which typically limits its use to a
       handful of experts in any company.
              module
               module top;                                                            #include
                       top;                                                            #include <stdio.h>
                                                                                                 <stdio.h>
              ...                                                                     #include
               ...                                                                     #include <svdpi.h>
              import
               import "DPI-C"
                       "DPI-C" context
                                 context c_imp
                                          c_imp ==                      import                   <svdpi.h>
                function
                 function int
                            int imp_func(...);                                        int
                                 imp_func(...);                                        int c_imp
                                                                                            c_imp (...)
                                                                                                   (...)
                                                                                      {{
              export
               export "DPI-C"
                       "DPI-C" c_exp
                                c_exp ==                                                 ...
                                                                                          ...
                function  exp_func;
                 function exp_func;                                                   }}
              function
               function int
                         int exp_func
                              exp_func ...                                            extern
                                        ...                                            extern int
                                                                                               int c_exp
                                                                                                    c_exp (...);
                                                                                                           (...);
                  ...
                   ...                                                                ...
                                                                                       ...
              endfunction
               endfunction                                              export
       The direct programming interface is a “lightweight”, compared to the PLI, interface between
       SystemVerilog and foreign programming languages. It maps SystemVerilog subroutine calls to
       foreign language implementations, and SystemVerilog subroutine declarations to foreign language
       calls. The standard clearly separates the specification of the SystemVerilog “layer” from the
       specification of each foreign “layer” so that accommodation of additional foreign languages does
       not change the SystemVerilog view of the interface. The standard currently specifies only the C
       foreign layer.
        DPI Characteristics
        The SystemVerilog and foreign language layers are independent
          Each layer does its own data interpretation and conversion
          Each layer follows its own syntax and semantics rules
                e.g. for declaring and calling subroutines
       The mapping between SystemVerilog and foreign language data types is specified by the foreign
       layer. Here we present the mapping specific to the C foreign language.
       The mapping of simple SystemVerilog data types such as byte, int, real and string is
       straightforward, as they have obvious C counterparts. The logic type maps to an unsigned char on
       the C side to accommodate the four states. For consistency, the bit type also maps to an unsigned
       char. Your C code should not use the character value directly, but should instead include svdpi.h
       and use the text macros representing the four states. The SystemVerilog LRM describes the name
       and core functionality of svdpi.h and permits vendors to differ in their implementations.
       --------
       typedef     signed __int8 int8_t;
       typedef     uint8_t svScalar;
       typedef     svScalar svBit;
       typedef     svScalar svLogic;
       #define     sv_0 0
       #define     sv_1 1
       #define     sv_z 2
       #define     sv_x 3
                                                                                                   C
                              SystemVerilog                                   #include
                                                                              #include <stdio.h>
                                                                                       <stdio.h>
            module
            module top;
                   top;                                                       #include
            ...                                                               #include <svdpi.h>
                                                                                       <svdpi.h>
            ...
            import
            import "DPI-C"
                   "DPI-C"    context
                              context c_imp
                                       c_imp ==               DPI             int
                                                                               int c_imp
                                                                                   c_imp (...)
                                                                                         (...)
              function
              function int
                        int   imp_func
                              imp_func (...);
                                        (...);                                {{ ...
                                                                                 ...
                                                                              }}
       SystemVerilog enumerated types are accessible on the C side as the enumeration base type, but the
       enumeration value names are not available.
       SystemVerilog packed types are accessible on the C side as arrays of the svBitVecVal type or
       svLogicVecVal type as described in svdpi.h.
       SystemVerilog unpacked arrays, structures and unions having only the simple types map to their
       corresponding C arrays, structures and unions of their corresponding C types.
       --------
       typedef unsigned __int32 uint32_t;
       typedef uint32_t svBitVecVal;
       typedef struct vpi_vecval {
           uint32_t a;
           uint32_t b;
       } s_vpi_vecval, *p_vpi_vecval;
       typedef s_vpi_vecval svLogicVecVal;
                                                                      SystemVerilog
           module
           module parity_calculator()
                  parity_calculator()
           ...
           ...
           import
           import "DPI-C"
                  "DPI-C" function
                          function int
                                   int parityf
                                       parityf (input
                                               (input int
                                                      int a);
                                                          a);
           ...
           ...
           initial                                                                                C
           initial                                                      #include
                                                                        #include      <stdio.h>
                                                                                      <stdio.h>
           ...
           ...                                                          #include      <svdpi.h>
           parity                                                       #include      <svdpi.h>
           parity == parityf(var);
                     parityf(var);
           ...
           ...                                                          int
                                                                        int parityf
                                                                              parityf (int
                                                                                      (int a)
                                                                                           a) {{
           endmodule
           endmodule                                                     ...
                                                                          ...
                                                                         return
                                                                          return parity;
                                                                                  parity;
                                                                         }}
                                                                          SystemVerilog
               module
               module parity_calculator()
                      parity_calculator()
               ...
               ...
               import
               import "DPI-C"
                      "DPI-C" function
                              function int
                                       int parityf
                                           parityf (input
                                                   (input int
                                                          int a);
                                                              a);
               ...
               ...
               initial                                                                                C
               initial                                                        #include
                                                                              #include    <stdio.h>
                                                                                          <stdio.h>
               ...
               ...                                                            #include    <svdpi.h>
               parity                                                         #include    <svdpi.h>
               parity == parityf(var);
                         parityf(var);
               ...
               ...                                                            int
                                                                              int parityf
                                                                                    parityf (int
                                                                                            (int a)
                                                                                                 a) {{
               endmodule
               endmodule                                                       ...
                                                                                ...
                                                                               return
                                                                                return parity;
                                                                                        parity;
                                                                               }}
       As the SystemVerilog and C layers are compiled and elaborated or linked separately, there is no
       opportunity for the DPI to check function declarations or verify data type compatibility. It is
       therefore critical that you match the import declaration to the C function with respect to the
       function name, return type and argument types.
       A name mismatch will probably result in only a “symbol not found” error. A type mismatch error
       can be more serious and can lead to unpredictable effects as the C layer misinterprets the
       SystemVerilog arguments.
       By default, you call an imported subroutine using the same name as the C function. You can
       specify a different SystemVerilog name for the C function if you provide the C linkage name in the
       import declaration. This is useful when the C function name is a reserved word or illegal identifier
       in the SystemVerilog namespace. It also allows you to import a C function multiple times with
       different SystemVerilog names.
       The C linkage name must of course be a legal C identifier, and if not a legal SystemVerilog
       identifier, must be appropriately escaped.
       You can place import declarations in the compilation unit scope, packages, interfaces, modules or
       programs. Placing it in a package simplifies sharing it among multiple design and test units.
       You can import any C function. It is common to import functions from the C math library.
       SystemVerilog returns the function results by value, so restricts the function return types to the
       "small" types. It passes small arguments by value and large arguments by reference, which on the
       C side means by pointer.
       C functions imported as a SystemVerilog task must return the void type.
       You can give a C function imported as a SystemVerilog task or function the context property. You
       can give a C function imported as a SystemVerilog function the pure property. Following slides
       describe these properties.
        An imported subroutine that is not context and not pure can access
        variables only in its own name spaces and can make calls to the operating
        system, to for example, access the filesystem.
       The context property makes the imported task or function aware of the context, that is the scope, of
       its declaration. Do not confuse this with the scope of its invocation. A “context” import can,
       through exported subroutines or the PLI, access simulation objects in its own context. To access
       objects in other contexts, it needs to change its context. The svdpi.h header defines the
       svSetScope() routine for setting the context.
       An imported subroutine that is not context and not pure can access variables only in its own name
       spaces and can make calls to the operating system, to for example, access the filesystem.
        Pure Functions
        import "DPI-C" pure [ c_identifier = ] prototype ;
        The SystemVerilog implementation can optimize calls to pure functions.
        You can provide imported functions with the pure property if:
          They return a non-void value
          They have at least one input and no output or inout arguments
       The pure property informs the implementation that the imported function returns a non-void value
       and has at least one input argument and no output or inout arguments and has no side-effects
       whatsoever. The implementation can optimize the function call. The pure property cannot apply to
       imported tasks.
                                             SystemVerilog
         module
         module dpi_test()
                 dpi_test()
         ...
         ...
         export
         export "DPI-C"
                 "DPI-C" function
                         function parityf;
                                  parityf;
         ...
         ...
         initial
         initial                                                                                       C
           ...
           ...                                                          #include
                                                                        #include   <stdio.h>
                                                                                   <stdio.h>
           function
           function int
                     int parityf(input
                         parityf(input int
                                       int a);
                                           a);                          #include
                                                                        #include   <svdpi.h>
                                                                                   <svdpi.h>
             ...
             ...                                                        extern
                                                                        extern int
                                                                                 int parityf(int
                                                                                     parityf(int a);
                                                                                                 a);
           endfunction
           endfunction                                                  ...
         endmodule                                                      ...
         endmodule                                                      int
                                                                        int ii == parityf(val);
                                                                                  parityf(val);
                                                                        ...
                                                                        ...
       11/6/2009                               SystemVerilog for Verification                              219
       By default, you call an exported subroutine using the same name as the SystemVerilog subroutine.
       You can specify a different SystemVerilog name for the C function if you provide the C linkage
       name in the export declaration. This is useful when the SystemVerilog subroutine name is a
       reserved word or illegal identifier in the C namespace. As every call of an exported SystemVerilog
       task or function is associated with a context, you can export a SystemVerilog task or function
       multiple times to the same C identifier if the exports are declared in different scopes and have the
       same signature. that is, return type, name, and argument types.
       The C linkage name must of course be a legal C identifier, and if not a legal SystemVerilog
       identifier, must be appropriately escaped.
        Exported subroutines:
          Accept the same argument data types as imported subroutines
       You can place export declarations in the compilation unit scope, packages, interfaces, modules or
       programs. Placing it in a package simplifies sharing it among multiple design and test units.
       An export declaration can export only the subroutines declared in its own scope, and can export a
       subroutine at most once. An export declaration is illegal within a class type declaration and so
       cannot export a class method.
       An imported subroutine with the “context” property can call an exported subroutine. This is how
       you create a time layer in C. The time is actually consumed by the exported SystemVerilog task
       called by an imported task. A SystemVerilog function cannot of course call a SystemVerilog task
       regardless of what language actually implements the task.
        import
        import "DPI-C"
               "DPI-C" context
                         context c_func
                                 c_func ==
          function
          function int import_c_func ((
                    int  import_c_func
            input
            input bit
                   bit bin1,
                        bin1,
            inout
            inout bit bin2
                   bit  bin2 );
                             );
        export
        export "DPI-C"
               "DPI-C" sv_func
                       sv_func == function
                                  function export_sv_func;
                                           export_sv_func;
        function
        function int
                   int export_sv_func(input
                       export_sv_func(input       bit
                                                  bit   eb1,
                                                        eb1,    #include
                                                                #include <stdio.h>
                                                                         <stdio.h>
                                      inout
                                      inout       bit
                                                  bit   eb2
                                                        eb2 );
                                                             ); #include <svdpi.h>
          if  (eb1  != eb2)
                                                                #include <svdpi.h>
          if (eb1 != eb2)
            ...
             ...
        endfunction                                                 extern
                                                                    extern int
                                                                           int sv_func(svBit,
                                                                               sv_func(svBit, svBit*)
                                                                                              svBit*)
        endfunction
        initial
        initial begin
                begin                                               int
                                                                    int c_func
                                                                        c_func   (svBit
                                                                                 (svBit b1,
                                                                                        b1, svBit
                                                                                            svBit *b2)
                                                                                                  *b2)
          #2
          #2 res_top
             res_top == import_c_func(b1,
                        import_c_func(b1, b2);
                                          b2);                        int
                                                                      int res;
                                                                          res;
          $display("res_top
          $display("res_top :: %d\n",
                               %d\n", res_top);                       printf("   b1
                                      res_top);                       printf("   b1 == %d,
                                                                                       %d, b2
                                                                                            b2 ==   %d\n",
                                                                                                    %d\n",
         end
         end                                                                     b1,
        endmodule                                                                b1, *b2);
                                                                                      *b2);
        endmodule                                                      res
                                                                       res = sv_func(b1, b2);
                                                                           =  sv_func(b1,   b2);
                                                                       printf("
                                                                       printf(" b1
                                                                                 b1 == %d,
                                                                                       %d, b2
                                                                                            b2 ==   %d\n",
                                                                                                    %d\n",
                                                                                 b1,
                                                                                 b1, *b2);
                                                                                      *b2);
                                                                       return  res;
                                                                       return res;
       11/6/2009                              SystemVerilog for Verification
                                                                   }}                                    222
       The SystemVerilog initial block calls the “import_c_func”, which is linked to the C function
       named “c_func” in the import declaration. This function is imported with the context property so
       that it can in turn call exported SystemVerilog subroutines.
       The C implementation of the “c_func” function calls the “sv_func” function that it has previous
       declared to have external linkage. This function is linked to the SystemVerilog function named
       “export_sv_func” in the export declaration.
 The imported subroutine may not call any more exported subroutines
        You code this handshake for all imported subroutines that call exported subroutines.
        No handshake mechanism exists for disabled exported subroutines.
       The SystemVerilog statement calling an imported subroutine may become disabled. This is
       important if the imported subroutine calls exported subroutines, for a disabled statement must have
       no further visible effect in the SystemVerilog layer.
       Upon return from the exported subroutine call, SystemVerilog advises the imported subroutine that
       its call has been disabled. An exported task call returns 1 rather than 0 to flag the disable. The
       imported subroutine can also call svIsDisabledState() to check its status.
       A disabled imported subroutine must immediately cease any activity in the SystemVerilog layer
       and must acknowledge the disable. An imported task returns 1 rather than 0, and an imported
       function calls svAckDisabledState().
       Pause here to examine this disable handshake protocol.
           function
           function void
                     void voidExportFunc();
                          voidExportFunc();
             disable
             disable disableMe;
                      disableMe;
             $display("exportTask
             $display("exportTask exit");
                                   exit"); //
                                            // no
                                               no display
                                                  display
           endfunction  : voidExportFunc
           endfunction : voidExportFunc
           export
           export   "DPI-C"
                    "DPI-C"         function
                                    function      voidExportFunc
                                                  voidExportFunc                ;;
           import
           import   "DPI-C"
                    "DPI-C" context function void voidImportFunc()
                            context function void voidImportFunc()              ;;
           initial
           initial
             begin
             begin :: disableMe
                      disableMe
               voidImportFunc();
               voidImportFunc();
             end
             end
        endmodule
        endmodule :: test
                     test      #include
                                #include <stdio.h>
                                         <stdio.h>
                               #include
                                #include "svdpi.h“
                                         "svdpi.h“
                               extern
                                extern void
                                       void voidExportFunc();
                                            voidExportFunc();
                               void
                                void voidImportFunc()
                                     voidImportFunc() {{
                                  voidExportFunc();
                                  voidExportFunc();
                                  printf("svIsDisabledState()
                                  printf("svIsDisabledState() is
                                                              is %d\n",svIsDisabledState());
                                                                 %d\n",svIsDisabledState());
                                  if
                                  if (svIsDisabledState())
                                     (svIsDisabledState()) svAckDisabledState();
                                                           svAckDisabledState();
                               }}
       An imported subroutine that calls an exported subroutine must comply with the disable protocol.
       That protocol requires the imported subroutine, upon return from calling an exported subroutine, to
       check whether it, the imported subroutine, was disabled. If it is disabled, it may not call any more
       exported subroutines and must acknowledge the disable.
       This example calls an imported function from within a named block. The imported function in turn
       calls an exported function. The exported function disables the named block, causing the imported
       function call to terminate abnormally. Upon return from calling the exported function, the imported
       function must check its disabled status, and if disabled, must acknowledge it.
       Pause here to examine this disable of the call to an imported function.
           task
           task exportTask();
                exportTask();
             #1
             #1 disable
                disable disableMe;
                        disableMe;
             #1
             #1 $display("exportTask exit");
                $display("exportTask exit"); //
                                             // no
                                                no display
                                                   display
           endtask : exportTask
           endtask : exportTask
           export
           export "DPI-C"
                   "DPI-C"         task
                                   task      exportTask
                                             exportTask          ;;
           import
           import "DPI-C" context task
                  "DPI-C"  context task      importTask()
                                             importTask()        ;;
           initial
           initial
              begin
              begin :: disableMe
                       disableMe
                importTask;
                importTask;
              end
              end
        endmodule
        endmodule :: test
                     test      #include
                                #include <stdio.h>
                                         <stdio.h>
                               #include
                                #include "svdpi.h"
                                         "svdpi.h"
                               extern
                                extern int
                                       int exportTask();
                                           exportTask();
                               int
                                int importTask()
                                    importTask() {{
                                  int
                                  int disabled
                                      disabled == exportTask();
                                                  exportTask();
                                  printf("exportTask
                                  printf("exportTask returned
                                                      returned %d\n",disabled);
                                                                %d\n",disabled);
                                  printf("svIsDisabledState()
                                  printf("svIsDisabledState() isis %d\n",svIsDisabledState());
                                                                   %d\n",svIsDisabledState());
                                  return
                                  return disabled;
                                         disabled;
                               }}
       An imported subroutine that calls an exported subroutine must comply with the disable protocol.
       That protocol requires the imported subroutine, upon return from calling an exported subroutine, to
       check whether it, the imported subroutine, was disabled. If it is disabled, it may not call any more
       exported subroutines and must acknowledge the disable.
       This example calls an imported task from within a named block. The imported task in turn calls an
       exported task. The exported task disables the named block, causing the imported task call to
       terminate abnormally. Upon return from calling the exported task , the imported task must check its
       disabled status, and if disabled, must acknowledge it.
       Pause here to examine this disable of the call to an imported task.
        Compilation
        SystemVerilog recommends two alternatives for including the linked C object code:
          By directly providing the library name with the -sv_lib option
                                                                                           simulator
                   top.v                        top                              top
C compiler linker
                                 
               taskfunc.c                    taskfunc.o                         myLib.so
       The actual usage methodology is vendor dependent, but is likely to be something like this:
          You separately compile your C code and link it into a shared object library with a platform-
           specific extension, such as .sl or .so for UNIX variants and .dll for Windows.
          You compile, elaborate and simulate your SystemVerilog code as usual, and provide the
           shared-object library to the simulator.
       The standard recommends that command line options be provided for this purpose, and even
       suggests names for them:
          The -sv_lib option provides a pathname for the shared object library minus its extension – the
           tool provides the correct extension for the platform.
          The -sv_root option provides a single directory path that is prefixed to any relative path
           specified by the -sv_lib option.
        DPI Summary
          Advantages                                       Potential Issues
          Easy to use                                      No arbitrary data types
            Standard interface                               SystemVerilog types only
                    if no packed types                       Packed array and struct layout is
            Doesn’t require new simulator                       dependent upon platform and
               executable                                        implementation
       Pause here for a moment and review what you have learned about the direct programming
       interface.
        Quiz
        1. Write a function import statement to import the exp2f function (from the
           cmath library) with the base2exp SystemVerilog identifier. Assume the
           C function has no side effects. The C function prototype is:
            float exp2f(float x);
Solutions in Appendix A
        About Lab 12
        In lab 12, you replace a C++ transaction-level model with an equivalent
        SystemVerilog model that you create. To do this, you determine the
        appropriate SystemVerilog data type for the function arguments, write and
        export the functions, and on the C++ side declare the functions to have
        external linkage.
                   system_c :
                     system
                   system_c.h                                      packet_c :
                                                                     packet
                                                                   packet_c.h
                     producer_c :                                               consumer_c :
                       producer                                                   consumer
                     producer_c.h                                               consumer_c.h
Chapter 12
November 6, 2009
        Topics
          What is an assertion?
       This chapter introduces assertion-based verification: what it is, what it does, and why you might
       want to adopt the methodology.
        What is an Assertion?
        An assertion is a check embedded in, or
        bound to, a design unit
        During simulation, assertions watch to
        see:
                                                                                    Testbench
          If a specific condition occurs, or
       An assertion is just a statement that something is true. What’s important about an assertion is that it
       asserts that some design property holds, and the simulator reports the failure of that design property
       to hold. Stating the assertion is the easy part. Crafting useful design properties is more difficult.
       However, it’s far easier than debugging a broken system without the help of assertions.
       The graphic illustrates where you can place an assertion. Note that you can place them on design
       inputs and design outputs and design interconnect and in the design blocks. You do not typically
       see assertions on a testbench.
                                                                                                              DUV
        Assertions monitor and report:
          Expected behavior
       Assertion-based verification is a verification methodology that utilizes assertions. This slide pretty
       much reiterates what we have just said. It does also point out that assertions are not limited to just
       simulation tools. Formal verification tools, that do their verification statically, typically with very
       little helper test stimulus, if any, also use assertions.
                   `ifndef
                   `ifndef SYNTHESIS
                             SYNTHESIS
                   always   @GNT
                   always @GNT
                     @(negedge
                     @(negedge clk)clk)
                     if
                     if (( GNT
                            GNT !=!= 4’h0
                                      4’h0 ))
                        begin:    GNT_CHK
                        begin: GNT_CHK
                          integer
                          integer cnt,cnt, idx;
                                             idx;
                          cnt   =
                          cnt = 0 ;0  ;
                          for
                          for (( idx
                                   idx == 0;0; idx
                                               idx <=
                                                   <= 3;
                                                      3; idx
                                                           idx == idx+1
                                                                  idx+1 ))
                             if
                             if (( GNT[idx]
                                     GNT[idx] !=!= 1’b0
                                                   1’b0 )) cnt
                                                            cnt == cnt
                                                                   cnt++ 1;
                                                                         1;
                          if
                          if ( cnt > 1 ) $display ( "ERROR: Multiple GNT"
                              (   cnt   > 1  ) $display  (  "ERROR:  Multiple GNT" );
                                                                                   );
                        end
                        end
                   `endif
                   `endif
       Verification personnel writing Verilog testbenches have been using an informal type of assertion
       right along. They write a process, that upon appropriate events, checks that some expression has
       the desired value, and if not, takes appropriate action. They can even write a check that spans
       multiple cycles, although that is more difficult, and thus rare.
       The use of assertions is not new. What is relatively new is the standardization of language
       constructs with which you can concisely express temporal design behaviors, and consistent support
       of those constructs, with failure messages, statistics collection and reporting, and user-friendly
       debug features.
http://www.dac.com
       A quick revisit to the DAC archives will reveal that use of assertions is pretty much mainstream
       now.
            RTL                                Implementation has properties the When Read and Write pointers
                        Functional Property
          Designer                             RTL designer intended it to have. both 0, the FIFO indicates empty.
       A system architect develops abstract properties that represent the desired behavior of the system at
       the functional level. At this point the actual implementation is not known.
       The block designer develops objective properties that represent the desired behavior of the system
       at the register level. It is important to verify this reinterpretation of the architect’s properties.
       As an IP designer, the RTL designer will want to embed input assertions in the design to detect
       future misuse of the design.
       The verification engineer focuses on design functional coverage points, which should include that
       the testbench actually exercised the asserted properties. Thus, functional coverage is a fundamental
       part of an Assertion Based Verification methodology.
       You can place assertions anywhere in your design hierarchy, enabling you to monitor design
       behavior locally and highlight problems as soon as they occur at the source of the problem.
       Conventional testbenches need to propagate a problem to the design outputs to detect it, and then
       you have to trace the error back through the design, and probably back through time as well, to
       determine the source. Assertions have the potential to detect problems during the early stages of
       testbench development, when the testbench might not yet be sufficiently robust to even propagate a
       problem to the outputs.
       You can have the simulation terminate upon failure of critical assertions, thus permitting other
       projects to use the compute cycles that would otherwise be wasted.
       Writing design properties encourages you to think more clearly about your design. This itself can
       highlight problems before you even finish the property. Overall verification efficiency is improved
       by designers producing better designs to begin with.
       Your embedded assertions travel with your design as it is used in different projects, warning
       against unexpected or incorrect use of your design block.
       Your embedded assertions also travel with your design from tool to tool, for example from
       simulation to formal verification, avoiding duplication of the verification effort.
 The simulator can make only those checks that the test exercises
       The most prominent issue with the Assertion Based Verification methodology is that you, the user,
       must craft the design properties. It’s very easy to construct a property that is not really 100% true.
       It’s even easier, perhaps very common, to miss nuances of design behavior, some corner cases, that
       really ought to be checked. There is also the issue of “how do you know when your property set is
       sufficient”.
       The simulator can check only those properties that the testbench exercises, so testbench quality is
       critical. This demands coverage metrics, which help to solve the “how do you know when you have
       tested enough” question, but do nothing for the “how do you know when your property set is
       sufficient” question.
        Summary
         Complex properties are difficult to write using Verilog
 Documents interfaces
Pause here for a moment, and review what you have learned about assertion-based verification.
        Quiz
        1. What is an assertion?
Solutions in Appendix A
Chapter 13
November 6, 2009
        Topics
          Concurrent assertion structure
          Multi-cycle sequences
          Repetition in sequences
       This chapter introduces SystemVerilog Assertions: how to declare and assert design properties,
       some property operators, and some sequence operators with which you can construct more
       complex properties.
        Concurrent Assertions
         Embedded in functional code and ignored by synthesis
       We have previously learned that an immediate assertion is a procedural statement that some
       boolean condition is true. The assertion is checked when the procedural statement executes.
       You typically place concurrent assertions outside procedural blocks to execute concurrently with
       the procedural blocks and utilize their own clock event.
       A property is a design behavior that may span multiple cycles. It is a design requirement, similar to
       a synthesis constraint that the design must work with a 250MHz clock. SystemVerilog has special
       operators you use to develop concise property expressions to represent complex multicycle design
       behavior.
        rw_chk
        label : assert           property ( [clocking_event]
                                             @(negedge clock)  !(wr_en
                                                        property_spec  && rd_en)
                                                               property_expr                                        );
                                                          ((A
                                                          ((A ++ B)
                                                                 B) >=
                                                                    >= 42)
                                                                       42) &&
                                                                           && (C
                                                                              (C ||
                                                                                 || D);
                                                                                    D);
       A property expression can be simply a boolean expression. Use parentheses where needed to
       appropriately group the operands and to enhance readability.
       --------
       IEEE Std. 1800-2005 SystemVerilog LRM, Section 17.4
                   ASSERT1
                   ASSERT1 :: assert
                              assert property
                                     property (( @(EN1
                                                 @(EN1 or
                                                       or EN2)
                                                          EN2) EN1
                                                               EN1 ||
                                                                   || EN2
                                                                      EN2 );
                                                                          );
                                                                                                      assertion
                                                                                                     parentheses
                      property
                      property PROP1;
                                PROP1;
                        @(EN1
                        @(EN1 or EN2)
                               or EN2) EN1
                                       EN1 ||
                                           || EN2;
                                              EN2;
                      endproperty
                      endproperty
                      ASSERT1
                      ASSERT1 :: assert
                                 assert property
                                        property (PROP1);
                                                 (PROP1);
                                                                                      always label
                                                                                      assertions
        Labels are used to reference the assertion
       11/6/2009                               SystemVerilog for Verification                                247
       You can specify the property within the assertion statement itself. Be sure to label the assertion
       statement so that upon assertion failure the tool reports a name that is meaningful to you.
       Otherwise the tool reports the scope of the assertion.
       You can alternatively declare and name the property. You can parameterize a declared property.
       You can instantiate the declared property as an operand in a property expression that uses property
       operators. If you assert the named property and omit the assertion statement label, the tool can
       upon assertion failure report the property name.
       The assertion label and property name must be valid Verilog identifiers. They reside in the module
       name space and must not clash with other identifiers in that name space.
       --------
       property_declaration ::=
           property property_identifier [ ( [ tf_port_list ] ) ] ;
              { assertion_variable_declaration }
              property_spec ;
           endproperty [ : property_identifier ]
                   property
                   property PCLK1;
                            PCLK1;
                     @(posedge
                     @(posedge CLK)
                               CLK) EN1
                                     EN1 ||
                                          || EN2;
                                             EN2;
                   endproperty
                   endproperty
                                property
                                property PCLK2;
                                           PCLK2;
                                  @(EN1
                                   @(EN1 or
                                         or EN2)
                                             EN2) EN1
                                                  EN1 ||
                                                      || EN2;
                                                         EN2;
                                endproperty
                                endproperty
                                                    property
                                                    property PCLK3;
                                                             PCLK3;
                                                      @(negedge
                                                      @(negedge ADDR_EN)
                                                                ADDR_EN) ADDR
                                                                         ADDR <=
                                                                              <= 7;
                                                                                 7;
                                                    endproperty
                                                    endproperty
       All assertions must be clocked. You can specify the clock in a sequence expression that the
       property uses, or in the property specification.
       The clocking event is typically just the Verilog event control. The parenthesized syntax also
       accepts a sequence name and the SystemVerilog “if-and-only-if” (iff) clock qualifier. For a
       sequence name, it is the endpoint of the sequence that clocks the property. Of course that sequence
       itself must also be clocked.
       --------
       event_expression ::=
              [ edge_identifier ] expression [ iff expression ]
           | sequence_instance [ iff expression ]
           | event_expression or event_expression
           | event_expression , event_expression
       A SystemVerilog simulation time instant is divided into several regions. The regions separate
       various activities in order to help avoid races between the writing and reading of a variable.
       Assertion evaluation occurs in the Observed region, after all current variable updates complete, but
       uses sampled values from the Preponed region to evaluate the sequence and property expressions.
       This means that you can safely use the same clock edge to clock the assertions that you use to
       update the variables. Assertion evaluation uses the pre-clock values.
       This diagram omits several regions used only for PLI callbacks.
EN_1HOT_CLK succeeds
       Clock asynchronous properties on any change of any signal used in the property expression.
       Clock synchronous properties on the appropriate edge of the appropriate clock signal.
       Property expression evaluation uses the sampled values, that is, the values before the clock event.
       --------
       IEEE Std. 1800-2005 SystemVerilog LRM, Section 17.3
        Assertion Placement
        You can declare a property in a
        compilation unit scope, package,
        interface, module, program or                     module
                                                          module mod1
                                                                 mod1
        clocking block.                                     (input
                                                            (input logic
                                                                    logic CLK,
                                                                          CLK,
                                                             ...
                                                             ...
        You can assert a property only                       output
                                                             output logic
                                                                     logic EN1,
                                                                           EN1, EN2);
                                                                                EN2);
        within an interface, module or
                                                          `ifndef
                                                          `ifndef USING_OLD_TOOL
        program, or always or initial block.                      USING_OLD_TOOL
                                                            property
                                                            property PROP1;
                                                                     PROP1;
                                                              @(posedge
                                                              @(posedge CLK)
                                                                        CLK) EN1
                                                                             EN1 ||
                                                                                 || EN2;
                                                                                    EN2;
                                                            endproperty
                                                            endproperty
        What to do about old tools that do
                                                            ASSERT1:
                                                            ASSERT1: assert
                                                                     assert property
                                                                            property (PROP1);
        not know about SystemVerilog?                     `endif
                                                          `endif
                                                                                     (PROP1);
                                                          ...
          Does the tool pre-define a text                ...
              macro?
          Or use bind construct (later
              chapter) with new tool to bind
              separate assertion modules
       11/6/2009                              SystemVerilog for Verification                            251
       You can declare a property, as a type, in the compilation unit scope, package, interface, module,
       program or clocking block. You can assert the property only in an interface, module, or program,
       or in an always or initial block.
       SystemVerilog does not predefine a macro that you can use to “hide” code from compilers that do
       not support it. Perhaps the compiler itself defines a macro you can use to bypass compilation of the
       SystemVerilog assertions.
       SystemVerilog provides a “bind” construct with which you can externally, perhaps from the
       testbench, instantiate assertion components within a module without modifying the module
       description.
       --------
       IEEE Std. 1800-2005 SystemVerilog LRM, Sections 17.11, 17.13
        Sequences
        You cannot write a complex temporal property
        using only the property operators                                                         sequence
                                                                                @(negedge
                                                                                @(negedge     CLK)
                                                                                              CLK)
        Special operators that construct sequences                                AA ##1
                                                                                     ##1 BB   ##1
                                                                                              ##1 C;
                                                                                                   C;
        facilitate writing properties that span time
        Sequences are building blocks of properties                   CLK
 Matching
 Composition
       You cannot write a complex temporal property using only the property operators. The only
       property operator that connects two cycles is the next-cycle implication (|=>) operator, and you
       cannot chain this operator because the resulting expression is a property and the left operand must
       be a sequence.
       A sequence is a series of boolean conditions over successive cycles.
       The “pound pound” (##) token is the cycle delay operator. Here we are using it to construct the
       sequence “A followed by B followed by C” in successive evaluations. Here the inputs are boolean
       signals, but they could be boolean expressions or even sequences of boolean expressions.
       This chapter later more fully describes the cycle delay operator.
       SystemVerilog provides two sequence implication operators. This is the “same cycle” implication
       operator. For this operator, the consequent property must hold in the same cycle in which the
       antecedent sequence completes. This operator is a property operator, that is, the resulting
       expression is a property expression which you can use as an operand in yet another property
       expression.
       For this example, the left side sequence and right side property are both non-temporal, so you can
       replace this same-cycle implication with a simple boolean expression.
       --------
       property_expr ::= ... | sequence_expr |-> property_expr | ...
       SystemVerilog provides two sequence implication operators. This is the “next cycle” implication
       operator. For this operator, the consequent property must hold in the cycle after that in which the
       antecedent sequence completes. This operator is a property operator, that is, the resulting
       expression is a property expression which you can use as an operand in yet another property
       expression.
       --------
       property_expr ::= ... | sequence_expr |=> property_expr | ...
                                   property
                                   property STATE;
                                            STATE;
                                     @(negedge
                                     @(negedge CLK)
                                               CLK) (A
                                                    (A ##1
                                                       ##1 B)
                                                           B) |=>
                                                              |=> C;
                                                                  C;
                                   endproperty
                                   endproperty
1 2 3 4 5 6 7 8
CLK
         C
                   1-active   1-inactive   2-active    2-enabled 2-succeeded           3-active   3-enabled   3-failed
                                                                                                  4-active    4-inactive
       The cycle delay expression can be an integral constant expression or a range between two integral
       constant expressions. Here we have a three cycle delay. The property holds in any given cycle if
       either “A” is true in that cycle or if “A” is false and four cycles later “B” is true. Note that this
       example uses next-cycle implication.
       A delay of zero is valid and useful. A zero delay between the end of the left sequence and the start
       of the right sequence means that the left sequence ends and the right sequence begins in the same
       cycle. This is called sequence fusion.
       --------
       IEEE Std. 1800-2005 SystemVerilog LRM, Section 17.5
       SystemVerilog provides three sequence repetition operators for your convenience. This slide
       illustrates the consecutive repetition operator, which simply repeats its boolean for whatever many
       cycles is the constant integral expression or range between two constant integral expressions. You
       can use this consecutive repetition operator with a boolean expression, an instance of a declared
       sequence, and with an inline sequence specification enclosed within parentheses.
       --------
       sequence_expr ::=
         ...
         | expression_or_dist [ boolean_abbrev ]
         | ( expression_or_dist {, sequence_match_item } ) [ boolean_abbrev ]
         | sequence_instance [ sequence_abbrev ]
         | ( sequence_expr {, sequence_match_item } ) [ sequence_abbrev ]
         ...
       This example specifies a range for the consecutive repetitions. The property holds in any given
       cycle if “A” is either false in that cycle, or true in the next cycle, or false for the next two to four
       cycles and true in the cycle after that.
       This slide provides an example of how difficult it is to craft a property that truly represents your
       intentions. If the specification stated that “A” is low for between two and four cycles, then this
       property would not reflect that specification, as the property as defined also holds for all cycles if
       “A” is low at cycle zero and stays low. Note the difference between “is low” and “goes low”.
       SystemVerilog has several more advanced property and sequence operators and features. The
       “SystemVerilog Assertions” training covers these plus has coding guidelines and
       recommendations, functional coverage and working examples
        Summary
         SystemVerilog assertions are based on Verilog boolean conditions
         SVA has many features for defining multi-cycle and repeated sequences
               e.g. consecutive repetition [*N]
Pause here for a moment and review what you have learned about SystemVerilog assertions.
        Quiz
        Code this property and assert it:
         If the req…ack handshake occurs …
          gnt is true on only the 2nd cycle after the req…ack handshake
          end is true on only the 6th cycle after gnt is true
             clk
             req
                                                                                        req
             ack                                                                        ack
                                                                                        gnt
             gnt                                                                  A     data     B
                                                                                        end
             data
             end
Solutions in Appendix A
Chapter 14
November 6, 2009
       Congratulations upon finishing this SystemVerilog Verification training! We hope the information
       in this training module met your verification and system-level design needs. You should expect to
       become truly proficient with these constructs only after several months of practical application.
        What’s Next?
                        — SystemVerilog Language and Application —
          Design                      Verification Module                                 Assertion
          Module                                                                           Module
       Day 1           Day 2           Day 3              Day 4                 Day 5
       Overview        Overview        Random             Interprocess    Introduction to Assertion Based
                                       Stimulus           Synchronization Verification (ABV)
       Data Types      Verification
                       Features  Class-Based   Direct                           Immediate Assertions
       Procedures
                                 Randomization Programming
                    Verification                                                Simple Boolean Assertions
       Operators                               Interface (DPI)
                    Blocks       Coverage
                                                                                Sequences
       User-Defined                            Assertion-Based
                    Transaction- Arrays and
       Data Types                              Verification                     Sequence Composition
                    Based        Queues
       Hierarchy &  Verification               SystemVerilog                    Advanced Features
       Connectivity                            Assertions
                    Classes                                                     Coding Guidelines
       Subroutines
                                                                                Functional Coverage
       Interfaces
                                                                                Practical Application
                                                                                Static Verification
       Successful completion of the Verification training qualifies you to now move on to the
       SystemVerilog Assertions training. To complete this additional training will take approximately
       another two days of your effort.
        Additional Resources
        You can obtain additional information from the following sources:
          Standards
                IEEE Std. 1800-2005 http://www.ieee.org
          Advocacy groups
                Accellera http://www.accellera.org
                EDA.org http://www.eda.org
          News groups
                http://groups.google.com/group/comp.lang.verilog
                http://groups.google.com/group/SystemVerilog
          SystemVerilog Publications
                "SystemVerilog for Verification". Spear, C., Springer (http://www.springer.com), 2006.
                “SystemVerilog Assertions Handbook”, Cohen, B. (et al), VhdlCohen Publishing
                   (http://www.abv-sva.org), 2005.
          Cadence Documentation
                SystemVerilog Reference (http://sourcelink.cadence.com)
Quiz Solutions
Appendix M2A
November 6, 2009
        3. Verification Blocks
        1. What do the input, inout, and output clocking directions signify?
               The clocking directions specify whether the clocking applies to sampling the signal,
                driving the signal, or both sampling and driving the signal.
         clocking
         clocking cb1
                   cb1 @(negedge
                       @(negedge clk);
                                 clk);        @(cb1);
                                              @(cb1); //
                                                      // @(negedge
                                                          @(negedge clk);
                                                                     clk);
           output
           output posedge drive;
                   posedge drive;             ##2;
                                              ##2;    //
                                                      // repeat(2)
                                                          repeat(2) @(cb2);
                                                                     @(cb2);
         endclocking
         endclocking                          cb1.drive
                                              cb1.drive <=
                                                         <= ##3
                                                            ##3 1;
                                                                 1; //
                                                                    // repeat(3)
                                                                        repeat(3) @(cb1)
                                                                                  @(cb1)
         clocking
         clocking cb2
                   cb2 @(negedge
                       @(negedge clk);
                                 clk);        ##3;
                                              ##3; cb1.drive <= 2’b10; //
                                                   cb1.drive  <=  2’b10;  // repeat(3)
                                                                             repeat(3) @(cb2);
                                                                                        @(cb2);
         endclocking
         endclocking                          ##(j-2)
                                              ##(j-2) cb1.drive
                                                      cb1.drive <=<= 1;
                                                                     1; //
                                                                         // repeat(j-2)
                                                                            repeat(j-2) @(cb1)
                                                                                         @(cb1)
         default
         default clocking
                  clocking cb2;
                           cb2;
         int j =  3;
         int j = 3;
        4. Transaction-Level Modeling
        1. What is a transaction?
               A transaction is a transfer of data between design blocks.
        2. What components produce and consume transactions?
              A] RTL Design. B] System-level Design. C] Testbench. D] B & C.
               Testbenches and system-level designs utilize transactions.
        3. True of False: A transactor converts between a transaction interface and
           a signal interface.
               True: A transactor converts between a transaction interface and a
                signal interface.
        4. What features of SystemVerilog interfaces most prominently support
           transaction-based verification?
               SystemVerilog interface methods and clocking blocks prominently
                support transaction-based verification.
        5. Classes
        1.   What is the role of a class constructor?
                  The class constructor initializes the class properties.
        2.   What is the difference between a static and non-static property?
                  One instance of a non-static property exists for each instance of the class type.
                   One instance of a static property exists and is not associated with any class instance.
        3.   What is the difference between a static and non-static method?
                  A static method of a class can access only the static members of the class.
        4.   What is inheritance?
                  A subclass inherits the members of its superclass and can redeclare them.
        5.   What is the difference between a protected and a local class member?
                  A subclass method can access a protected member of its superclass.
                   Only class member methods can access local members of a class.
        6.   Give an example of polymorphism.
                  An implementation of a virtual method is selected dynamically based upon the
                   subclass object that the superclass handle “points” to.
        6. Random Stimulus
        Define the output for each value of i:
                          randsequence()
                          randsequence()
                            top
                             top :: AA B;
                                        B;
                            AA   :: CC DD E;
                                           E;
                            BB   :: CC EE {{ if
                                              if (i
                                                 (i ==== 11 )) return;
                                                               return; }} D;
                                                                          D;
                            CC   :: {$display("C");        if(i  == 3) return;};
                                     {$display("C"); if(i == 3) return;};
                            DD   :: {if
                                     {if (i(i ==
                                               == 22 )) return;
                                                        return; $display(
                                                                  $display( "D");};
                                                                             "D");};
                            EE   :: {if
                                     {if (i(i ==
                                               == 00 )) break;
                                                        break; $display("E");};
                                                                 $display("E");};
                          endsequence
                          endsequence
                                     i == 0      produces C D
                                     i == 1      produces C D E C E
                                     i == 2      produces C E C E
                                     i == 3      produces C D E C E D
8. Coverage (question)
              module
              module example_with_bins;
                      example_with_bins;
              logic
              logic clk;
                     clk;
              logic
              logic [2:0]
                     [2:0] opcode;
                            opcode;
              logic
              logic [15:0]
                     [15:0] address;
                            address;                                                   How many bins in
                                                                                ?      this covergroup?
              covergroup
              covergroup cg1
                           cg1 @(posedge
                               @(posedge clk);
                                                                              Question What are their names?
                                           clk);
                 c1:
                 c1: coverpoint
                      coverpoint opcode;
                                   opcode;
                 c2:
                 c2: coverpoint
                      coverpoint address
                                   address {{
                       bins
                        bins low[]
                             low[] == {{ [0:’h0F]
                                         [0:’h0F] }} ;;                         opcode:
                       bins
                        bins high = { [’h10:’hFF] }} ;;
                             high   = {  [’h10:’hFF]                             8 implicit
                     }}                                                           “c1.auto[0]” to “c1.auto[7]”
              endgroup
              endgroup :: cg1
                           cg1
                                                                                address:
              cg1
              cg1 cover_inst
                  cover_inst == new();
                                new();                                           16 explicit vectored
                                                                                  “c2.low[0]” to “c2.low[F]”
              ...
              ...                                                                1 explicit scalar
                                                                                  “high”
              endmodule
              endmodule
8. Coverage
         bit
          bit [7:0]
               [7:0] avec,
                      avec, bvec;
                             bvec;
         covergroup
          covergroup cgcg @(posedge
                           @(posedge clk);
                                       clk);
         cpa:
          cpa: coverpoint
                coverpoint avec
                             avec {{
            bins
             bins a1
                  a1 == {{ [0:63]
                           [0:63] };
                                   };                              How many bins in this
            bins
             bins a2 = { [64:127] };
                  a2 =  {  [64:127]   };                    ?      covergroup cross c?
            bins
             bins a3
                  a3 == {{ [128:191]
                           [128:191] };
                                                          Question What are their names?
                                       };
            bins
             bins a4
                  a4 == {{ [192:255]
                           [192:255] };}; }}
         cpb:
          cpb: coverpoint
                coverpoint bvec
                             bvec {{                                 c1: 4
            bins  b1 =  {0};
             bins b1 = {0};                                          <a1,b1>, <a1,b2>,
            bins
             bins b2
                  b2 == {{ [1:84]
                           [1:84] };
                                   };                                <a1,b3>, <a1,b4>
            bins
             bins b3
                  b3 == {{ [85:169]
                           [85:169] };};                             c2: 7
            bins
             bins b4 = { [170:255] };
                  b4 =  {  [170:255]   }; }}                         <a2,b1>, <a2,b2>,
         cc :: cross
               cross cpa,
                      cpa, cpb
                            cpb {{                                   <a2,b3>, <a2,b4>,
                                                                     <a1,b2>, <a3,b2>,
            bins
             bins c1
                  c1 == !! binsof(cpa)
                           binsof(cpa) intersect
                                          intersect {[100:200]};
                                                    {[100:200]}; <a4,b2>
            bins
             bins c2
                  c2 == binsof(cpa.a2)
                         binsof(cpa.a2) || || binsof(cpb.b2);
                                              binsof(cpb.b2);
            bins
             bins c3
                  c3 == binsof(cpa.a1)
                         binsof(cpa.a1) && && binsof(cpb.b4);
                                              binsof(cpb.b4); }}     c3: 1
                                                                     <a1, b4>
         endgroup
          endgroup
           clk
           req
                                                                                  req
           ack                                                                    ack
                                                                                  gnt
           gnt                                                                A   data   B
                                                                                  end
           data
           end
Index
                                                                      i
This document is for the sole use of Sundaresan Chidambaram of Manipal University
                                                                                                       ii
This document is for the sole use of Sundaresan Chidambaram of Manipal University
                                                                                              iii
This document is for the sole use of Sundaresan Chidambaram of Manipal University
                                            polymorphism, 93
            J                               post_randomize(), 126
          join_any, 32                      pre_randomize(), 126
          join_none, 32                     process
                                              synchronization, 186-205
                                                with event, 188-194
            L                                   with mailbox, 195-199
                                                with semaphore, 200-202
          linkage name (DPI), 215, 220
          local class property, 91          programs, 44
                                              $exit, 44
                                            property
            M                                 assertion, 242-261
                                              class, 78, 83, 91
          mailbox , 195-199                     local, 91
           methods, 196                         protected, 91
           parameters, 199                      static, 83
          methods                           protected class property, 91
           array manipulation, 179-182      ps (time literal), 25
              array locator, 180            pseudo-random, 105
              array ordering, 181           pure function (DPI), 216-218
              array reduction, 183
           associative array, 171-174
           class,                            Q
              external, 80
              static, 84                    queue, 175-178
              virtual, 92-93
           dynamic array, 169-170            R
           mailbox, 196
           in a modport, 65-66              rand, 124
           queue array, 187-190             rand_mode, 129-130
           semaphore, 201                   randc, 124
          ms (time literal), 25             randcase, 113
                                            random number generator, 105, 108
                                            randomize(), 107, 125
            N                               randomization
          new                                 $urandom(), 106
            class, 76, 81, 87                 $urandom_range(), 106
            covergroup, 147, 149              class object, 122-143
            dynamic array, 169-170              rand, 124
            mailbox, 227                        randc, 124
            semaphore, 201                      rand_mode(), 129-130
          ns (time literal), 25               constraint, 14, 104, 111-112, 131-140
          null                                  conditional, 112, 135
            class variable, 76-77               constraint_mode(), 138-139
            event variable, 194                 dist (distributions), 111, 134
            virtual interface, 67               inside operator, 111, 133
                                                inheritance, 132
                                                iterative, 136
            O                                   solve-before, 137
                                                weights, 111, 134
          Object-Oriented (OO) design, 75     randomize(), 107, 125
          option, 164, 166                    random number generator, 105, 108
          output                                seed, 110, 140
            in clocking block, 47-49            stability, 108
                                              scope variable, 98-112
            P                                 srandom(), 109, 140
                                            randsequence, 115-122
          parameter                           productions, 114-118
            class type, 79, 94                  break, 117
            mailbox, 199                        case, 116
            module, 35, 182                     if-else, 116
            property, 247                       passing values, 118
          PLI, 216                              repeat, 116
                                                                                      iv
This document is for the sole use of Sundaresan Chidambaram of Manipal University
            S
          s (time literal), 25
          scheduler (event) 42-43
          scope randomization (variable), 98-121
          semaphore , 200-202
            methods, 201
          sequence
            repetition, 255-256
          severity level, 29
          skew, 48-49
          solve-before, 137
          srandom(), 109, 140
          static
            class method, 84
            class property, 83
          std, 107
          step (time literal), 25
          struct
            vs. class, 79
          string, 21-24
          svdpi.h, 211-215, 219-220, 222, 224-225
          synchronous drive, 53
            T
          task
             context, 247-248, 252
          Transaction Level Modeling (TLM), 58-72
             transaction, 60
             transaction based verification (TBV), 61
             transaction verification model (TVM), 61
             transactor, 61
               as interface, 63-68
             benefits, 69
          transactor, 62-66
             using interface, 63-66
          triggered (event property), 190
          type_option, 159-160
            U
          us (time literal), 25
            V
          virtual
            class, 93
            interface, 67-68
                                                                                             v
This document is for the sole use of Sundaresan Chidambaram of Manipal University
vi