UVM Tutorial for Candy Lovers – 7. Virtual Sequence

Last Updated: March 26, 2016 (added the link to EDA Playground)

CakeDid you know the mix of two lemon and two coconut jelly beans will create the flavor of lemon meringue pie? And the mix of two strawberry and two vanilla jelly beans will create the flavor of strawberry shortcake? This post will provide an explanation on the virtual sequence to create these new jelly-bean recipes.

Overview

The first figure shows the relationship of the verification components used in this post. The jelly_bean_taster (DUT) from the previous posts was “enhanced” to take two jelly-bean flavors at the same time through two jelly_bean_ifs. This new DUT is referred to as the jelly_bean_taster_subsystem. To drive the two interfaces, two instances of jelly_bean_agent are used. The jelly_bean_recipe_virtual_sequence orchestrates the creation of jelly-bean flavors in order to make a new flavor. The second figure at the bottom of the page shows the verification components in a class diagram, and the third figure shows the verification objects in a class diagram.

Verification Platform

Virtual Sequence

The virtual sequence defines three new jelly-bean recipes (LEMON_MERINGUE_PIE, STRAWBERRY_SHORTCAKE, and CANDY_APPLE) on the second line. Each recipe requires two jelly-bean flavors. For example, to create the LEMON_MERINGUE_PIE recipe, two LEMON jelly beans and two COCONUT jelly beans are necessary. Two sub-sequences (same_flavored_jelly_beans_sequence) are created (line 19) to generate two flavors. The case statement on the line 21 prepares two jelly-bean flavors based on the recipe. At the end of the body task, the two sub-sequences are started in parallel (line 42).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
class jelly_bean_recipe_virtual_sequence extends uvm_sequence#( uvm_sequence_item );
   typedef enum bit[1:0] { LEMON_MERINGUE_PIE,   // 2 LEMON      + 2 COCONUT                           STRAWBERRY_SHORTCAKE, // 2 STRAWBERRY + 2 VANILLA                           CANDY_APPLE           // 2 APPLE      + 1 CINNAMON                           } recipe_e;   rand recipe_e recipe;
 
   jelly_bean_sequencer jb_seqr1;
   jelly_bean_sequencer jb_seqr2;
 
   same_flavored_jelly_beans_sequence jb_seq1;
   same_flavored_jelly_beans_sequence jb_seq2;
 
   function new( string name = "" );
      super.new( name );
   endfunction: new
 
   task body();
      jb_seq1 = same_flavored_jelly_beans_sequence::type_id::create( .name( "jb_seq1" ), .contxt( get_full_name() ) );      jb_seq2 = same_flavored_jelly_beans_sequence::type_id::create( .name( "jb_seq2" ), .contxt( get_full_name() ) );      case ( recipe )        LEMON_MERINGUE_PIE: begin           jb_seq1.flavor          = jelly_bean_transaction::LEMON;           jb_seq2.flavor          = jelly_bean_transaction::COCONUT;           jb_seq1.num_jelly_beans = 2;           jb_seq2.num_jelly_beans = 2;        end        STRAWBERRY_SHORTCAKE: begin           jb_seq1.flavor          = jelly_bean_transaction::STRAWBERRY;           jb_seq2.flavor          = jelly_bean_transaction::VANILLA;           jb_seq1.num_jelly_beans = 2;           jb_seq2.num_jelly_beans = 2;        end        CANDY_APPLE: begin           jb_seq1.flavor          = jelly_bean_transaction::APPLE;           jb_seq2.flavor          = jelly_bean_transaction::CINNAMON;           jb_seq1.num_jelly_beans = 2;           jb_seq2.num_jelly_beans = 1;        end      endcase // case ( recipe )      `uvm_info( get_name(), { "\n", this.sprint() }, UVM_LOW )
      fork         jb_seq1.start( .sequencer( jb_seqr1 ), .parent_sequence( this ) );         jb_seq2.start( .sequencer( jb_seqr2 ), .parent_sequence( this ) );      join   endtask: body
 
   `uvm_object_utils_begin( jelly_bean_recipe_virtual_sequence )
      `uvm_field_enum  ( recipe_e, recipe, UVM_ALL_ON )
      `uvm_field_object( jb_seq1,          UVM_ALL_ON )
      `uvm_field_object( jb_seq2,          UVM_ALL_ON )
   `uvm_object_utils_end
endclass: jelly_bean_recipe_virtual_sequence

Test

The jelly_bean_recipe_test class creates the above mentioned virtual sequence. Firstly, the test assigns two jelly_bean_sequencers to the virtual sequence (line 13 and 14). By doing this, the sub-sequence, jb_seq1, will run on the sequencer in the agent #1, and the sub-sequence, jb_seq2, will run on the sequencer in the agent #2. The test randomizes the virtual sequence and starts the sequence on the line 15 and 16. Note that the sequencer argument of the start task takes null since there is no sequencer associated with the virtual sequence.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class jelly_bean_recipe_test extends jelly_bean_base_test;
   `uvm_component_utils( jelly_bean_recipe_test )
 
   function new( string name, uvm_component parent );
      super.new( name, parent );
   endfunction: new
 
   task main_phase( uvm_phase phase );
      jelly_bean_recipe_virtual_sequence jb_vseq;
 
      phase.raise_objection( .obj( this ) );
      jb_vseq = jelly_bean_recipe_virtual_sequence::type_id::create( .name( "jb_vseq" ), .contxt( get_full_name() ) );      jb_vseq.jb_seqr1 = jb_env.jb_agent1.jb_seqr;      jb_vseq.jb_seqr2 = jb_env.jb_agent2.jb_seqr;      assert( jb_vseq.randomize() );      jb_vseq.start( .sequencer( null ) );      #100ns ;
      phase.drop_objection( .obj( this ) );
   endtask: main_phase
endclass: jelly_bean_recipe_test

Simulation

Let’s run a simulation to see what flavors the virtual sequence generates. In my case, the sequence generated a CANDY_APPLE recipe. It in turn made the first sequence (jb_seq1) generate two APPLE jelly beans, and made the second sequence (jb_seq2) generate one CINNAMON jelly bean.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
UVM_INFO jb.sv(266) @ 0: reporter@@jb_vseq [jb_vseq]
------------------------------------------------------------------------------------
Name                           Type                                Size  Value
------------------------------------------------------------------------------------
jb_vseq                        jelly_bean_recipe_virtual_sequence  -     @1196
  recipe                       recipe_e                            2     CANDY_APPLE  jb_seq1                      same_flavored_jelly_beans_sequence  -     @1200
    num_jelly_beans            integral                            32    'h2    flavor                     jelly_bean_transaction::flavor_e    3     APPLE    req                        object                              -
    rsp                        object                              -
  jb_seq2                      same_flavored_jelly_beans_sequence  -     @1204
    num_jelly_beans            integral                            32    'h1    flavor                     jelly_bean_transaction::flavor_e    3     CINNAMON    req                        object                              -
    rsp                        object                              -
  depth                        int                                 32    'd1
  parent sequence (name)       string                              0     ""
  parent sequence (full name)  string                              0     ""
  sequencer                    string                              0     ""
  req                          object                              -
  rsp                          object                              -
------------------------------------------------------------------------------------
Component View
Component Class Diagram
Object Class Diagram

I hope this tutorial helped you understand the virtual sequence. Oh, for those of you who are interested in more jelly-bean recipes, consult this site πŸ™‚

Get source code

EDA Playground

You can view and run the code on EDA Playground.

51 thoughts on “UVM Tutorial for Candy Lovers – 7. Virtual Sequence”

  1. Hi,

    I have a basic doubt related to raising an objection.

    In many examples i found the objection is raised from inside the sequences, or may be some other components.
    Here, in this example, the objection is raised from the testcase.

    How to decide on the point of raising an objection? What all factors incfluence that? Does it make any difference if i raise an objection from a sequence or from a testcase?

    1. An objection should be raised if a component or a sequence does not want to move on to the next phase. For example, the jelly_bean_recipe_test wanted to run for 100 ns, so it raised an objection. If a test pushes 100 requests to a request queue, but the test does not know when these requests finish, the request queue should also raise an objection as long as there is a request in the queue. A scoreboard is another candidate to raise an objection.

  2. Hi Keisuke,

    I found the post is very helpful for me to understand the uvm. I wonder what is the reason that seq1.start needs to provide parent_sequence, but the gift_box example, sequence of sequences does not need parent_sequence.

    Thanks.

    1. The jb_seq1 and jb_seq2 are children of the jelly_bean_recipe_virtual_sequence. If the parent_sequence is provided, the parent_sequence‘s pre_do, mid_do, and post_do methods will be called during the execution of the jb_seq1 and jb_seq2.
      Similarly the gift_boxed_jelly_beans_sequence should have provided the parent_sequence when it called jb_seq.start(). I have corrected the example (the line 15 of gift_boxed_jelly_beans_sequence of this article). Thank you for pointing this out.

  3. Hi Keisuke,

    I am new to virtual_seq. In line 1,
    class jelly_bean_recipe_virtual_sequence extends uvm_sequence#( uvm_sequence_item );

    Since virtual_seq does not work with a driver, why do we need uvm_sequence_item? Is it ok to leave it out.
    class jelly_bean_recipe_virtual_sequence extends uvm_sequence;

    Many thanks.

  4. Hi Keisuke,

    I have a few questions related to sequence. Can you give me some pointer?
    1. This is the problem. I want to test multiplexer interface in DUT. Each output is connection to a 4 deep FIFO. I don’t want to interface to be idle when any of the FIFO is full. The driver will drive 2bit control bit, and 8-bit data. (this is my sequence item) So I want to use 4 sema to keep track of each fifo assuming the I can put token back to sema when I drain out 1 entry from the fifo.

    1. should I pass the sema to a sequence, and In the body(), I try_put sema to randomize the 2bit control bit?
    2. should I use the sema info in the driver?
    What is the most practical way to implement this?

    2. When I compare the syntax of seq, and virtual seq, they are very similar except:
    a. virtual seq is not associated with a user-defined sequence_item.
    b. virtual seq has sequencer for each of the sub-seq.
    Are these the only different?

    Many thanks.

    1. Hi Loren,

      1. I’m afraid I might not understand your DUT well, but I would probably put control bit info in a transaction so that I can fully control the driver behavior.
      2. Yes, a virtual sequence is nothing but a sequence. The only difference is that it co-ordinates multiple sequences on different sequencers.

  5. Mr. Shimizu,
    Thanks for the wonderful explanation. Could also explain about Virtual Sequencers ? As per your explanation, I understood that Virtual Sequences co-ordinates multiple sequences on different sequencers. how does it differ from Virtual Sequencer.
    Thanks.

    1. A virtual sequencer also has the handles to the coordinated sequencers, and you can create a virtual sequence that runs on the virtual sequencer. However, this approach adds an unnecessary component (virtual sequencer) to the verification environment and it negatively affects the reusability of the environment. I would recommend not to use the virtual sequencer.

  6. Hi,
    I youe code you have not used virtual sequencer my question is

    Why do we need virtual sequencer when the same can be done with the above example.

    What are the disadvantage of using the above example.

  7. I’m new to UVM, and maybe not catch the idea really well. I have a basic question. What’s the benefit of using the virtual sequence? We can do pretty much do the same thing in the test, right? Is it just to group the sequences? Thanks, Cate

    1. There are a couple of benefits using the virtual sequence over doing the same in a test.

      • It is easier to reuse. You can reuse the virtual sequence used in the module level to the full-chip level, for example. If you coordinate the sequences in a test, you will need to modify the test because it is tightly coupled with the component hierarchy.
      • You can easily create hierarchical sequences if you need to do so in the future.
  8. Hi Keisuke san,

    I tried to read more the the sequencer arbitration, but I couldn’t find anything that can explain clearly to me how the SEQ_ARB_FIFO, SEQ_ARB_RANDOM work. Can you give an example to illustrate.

    For example, when I forked

    fork 
        begin repeat(2)
          #1;
          seqA.start(m_sqr, this, 500);
         end
         begin repeat(2)
          #2;
          seqA.start(m_sqr, this, 500);
         end
         begin repeat(2)
          #3;
          seqA.start(m_sqr, this, 200);
         end
    join
    

    I know that start will not return until seq’s body is completed. Let’s say it takes 10 time unit.

    I can see the seq thread should be
    @1 seqA
    @2 seqA, seqB
    @3 seqC
    @11 seqA finished. Then it is the only one that can request again. I can’t figure it out.

    Many thanks.

    Loren

  9. Hi Keisuke San,

    Can you explain how to parameterize a uvm_sequence_item? For example, I have a interface, and I want to have the address and data width parametrizable.

    I think I can write the base class like.

    class bus_item#( ADDR_WIDTH = 8, DATA_WIDTH=8) extends uvm_sequence_item
    `uvm_object_utils( bus_item#(ADDR_WIDTH, DATA_WIDTH))

    So when I create a derive class. Should it be?
    class d_bus_item extends bus_item#(ADDR_WIDTH, DATA_WIDTH)
    `uvm_object_utils( d_bus_item)

    Also when I use the class my_seq extends uvm_sequence#(packet), is the packet the parameter in uvm_sequence?

    These are my confusion.
    1. I am not sure where to place the parameter in the derived class. For example, `uvm_object_utils( d_bus_item#(ADDR_WIDTH, DATA_WIDTH)).
    2. If my base class is not parameterized, can I derived a class and parameterize it?

    Many thanks.

    1. A parameterized class needs to be specialized (meaning you need to specify the parameter values) before use. Your code won’t compile because the ADDR_WIDTH and the DATA_WIDTH are not specified.

      // This won't compile because ADDR_WIDTH and DATA_WIDTH are not specified.
      class d_bus_item extends bus_item#( ADDR_WIDTH, DATA_WIDTH );

      param1

      You can either make the d_bus_item parameterized:

      // make d_bus_item parameterized, too
      class d_bus_item#( ADDR_WIDTH, DATA_WIDTH ) extends bus_item#( ADDR_WIDTH, DATA_WIDTH );
        `uvm_object_param_utils( d_bus_item #( ADDR_WIDTH, DATA_WIDTH ) ) // make sure to use "param_utils"

      param2

      and specialize the d_bus_item when you instantiate it:

      d_bus_item#( 8, 8 ) d;

      Or, specialize the bus_item:

      // d_bus_item is no longer a parameterized class
      class d_bus_item extends bus_item#( 8, 8 );
        `uvm_object_utils( d_bus_item )

      param3

      Since the bus_item class has the default parameter values, you can also write:

      class d_bus_item extends bus_item; // < -- same as writing bus_item#( 8, 8 )

      Similarly, when you did:

      class my_seq extends uvm_sequence#( packet );

      you specialized the uvm_sequence class with the packet type.

      You can add new parameters to the derived class, too.
      param4

  10. Thanks Keisuke san. You explained the usage very well.

    If I understand it correctly, can I summarize it this way?
    For a derived class also can change the parameters, I need to declare it this way.
    class A_item#(int a) extends B_item#(int a)
    `uvm_object_param_utils(A_item#(int a)) <– I used the param_utils, and I included the param.

    If my drived class will use a fixed parameter like 8, I need declare it this way.
    class A_item extends B_item#(8) <– I used the fix parameter
    `uvm_object_utils(A_item) <– this is not parameterized class

    Many thanks.

    Loren

      1. Hi shimizu,
        In some pdfs like uvm_user_guide, i have seen people using virtual sequences contain only sub-sequences and virtual sequencers contain the subsequencers
        In the env, they set the virtual_sequecer.sub_seqr = agent.sequencer

        Then in test, they define the default_sequence of the virtual sequencer to be the virtual sequence using config_db

        Here you keep the sequencers in virtual sequence

        Which approach you would suggest

        Thanks
        Sasi

          1. Hi, I am just eager how a sequence will be run if sequencer handle is not passed.
            Say, if vir_seq.start(null) is called , please explain how does it start() method works.

  11. How I set a value to variable in the sequence, when i start the sequence with `uvm_do_* macro? Because I don’t need to create the sequence when I use uvm_do. I tried setting the variable as rand type and tried to use uvm_do_with, but it doesn’t work.

      1. Thanks, I was able to make it work with `uvm_do_with. But my requirement is that I don’t want to set the variable always, but only on certain occasions. Making it as rand type randomizes it always(even when I just use `uvm_do).

  12. HI KEISUKE,

    1) I recently came across an interview question regarding Virtual sequencer.I know the application of virtual sequencer.

    Interview Question : What is virtual sequencer? Is it possible to drive two different sequences with out using virtual sequences/sequencers on different agents?

    – If Yes,Then what is the purpose of virtual sequences/sequencers?
    – If No,what makes the advantage using it.

    can you let me know with some scenario ?

    -Raja.

  13. Hello Shimizu-san,

    Thank you very for your great tutorial.
    I have a question: can we start a virtual sequence in another virtual sequence (like in no3 I see sequence of sequences by using m_sequencer ). Can we do similar things with two (or more) virtual sequences. If possible could you please recommend the way ?

    Thank you.

    1. Yes, you can. This is a virtual sequence (gift_boxed_jelly_beans_virtual_sequence) that runs another virtual sequence (jelly_bean_recipe_virtual_sequence).

      class gift_boxed_jelly_beans_virtual_sequence extends uvm_sequence;
        `uvm_object_utils( gift_boxed_jelly_beans_virtual_sequence )
       
         rand int unsigned num_jelly_bean_flavors; // knob
         jelly_bean_recipe_virtual_sequence jb_seq;
       
         constraint num_jelly_bean_flavors_con { num_jelly_bean_flavors inside { [2:3] }; }
       
         function new( string name = "" );
            super.new( name );
            jb_seq = jelly_bean_recipe_virtual_sequence::type_id::create( .name( "jb_seq" ), .contxt( get_full_name() ) );
         endfunction: new
       
         task body();
            repeat ( num_jelly_bean_flavors ) begin
              assert( jb_seq.randomize() );
              jb_seq.start( .sequencer( null ) ); // start another virtual sequence
            end
         endtask: body
      endclass: gift_boxed_jelly_beans_virtual_sequence

      And this is a test that runs the above virtual sequence.

      class jelly_bean_recipe_test extends jelly_bean_base_test;
         `uvm_component_utils( jelly_bean_recipe_test )
       
         function new( string name, uvm_component parent );
            super.new( name, parent );
         endfunction: new
       
         task main_phase( uvm_phase phase );
            gift_boxed_jelly_beans_virtual_sequence jb_vseq;
       
            phase.raise_objection( .obj( this ) );
            jb_vseq = gift_boxed_jelly_beans_virtual_sequence::type_id::create( .name( "jb_vseq" ) );
            jb_vseq.jb_seq.jb_seqr1 = jb_env.jb_agent1.jb_seqr;
            jb_vseq.jb_seq.jb_seqr2 = jb_env.jb_agent2.jb_seqr;
            assert( jb_vseq.randomize() );
            jb_vseq.start( .sequencer( null ) ); // start the virtual sequence
            #100ns ;
            phase.drop_objection( .obj( this ) );
         endtask: main_phase
      endclass: jelly_bean_recipe_test
          1. Hi, If I create a virtual_seq with only one sequence and start this virtual_seq in my test with actual sequencer (instead of null), then will that be considered as normal sequence? If yes, then only way simulator knows it is a virtual sequence is by the way start is called?

          2. I would say your sequence is a non-virtual sequence, not because you started the sequence on a (non-null) sequencer, but because it is a sequence of another sequence.

            You can start a virtual sequence on a (non-null) sequencer. For example, the virtual sequence can send sequence items to the sequencer while it starts other sequences on their sequencers. My definition of virtual sequence is that it starts sub-sequences on multiple sequencers.

        1. You cannot start the same sequence on multiple sequencers in parallel unless you clone it because the sequence keeps track of its sequence state (once a sequence is started, it cannot be started again until it is finished or stopped).

  14. hi Mr. Shimizu,

    virtual sequencer and physical sequencer exit from main phase prematurely before test completes. have you seen this? if so, how to resolve it? Thank you.

    Ed

  15. Hi Keisuke: The definition of your “same_flavored_jelly_beans_sequence” class does not have a member called “flavor”. How were you able to assign some values inside your “jelly_bean_recipe_virtual_sequence” class for the “jb_seq1” and “jb_seq2” sequences?

    1. Actually, I slightly modified the original same_flavored_jelly_beans_sequence to have the flavor property for this tutorial. Sorry for the confusion.

      class same_flavored_jelly_beans_sequence extends uvm_sequence#( jelly_bean_transaction );
       
         // knobs
       
         rand int unsigned num_jelly_beans;
         rand jelly_bean_transaction::flavor_e flavor; 
         local same_flavored_jelly_beans_sequence self = this;
       
         constraint num_jelly_beans_con { num_jelly_beans inside { [1:4] }; }
       
         function new( string name = "" );
            super.new( name );
         endfunction: new
       
         task body();
            jelly_bean_transaction jb_tx;
            repeat ( num_jelly_beans ) begin
      	 jb_tx = jelly_bean_transaction::type_id::create( .name( "jb_tx" ) );
      	 start_item( jb_tx );
      	 assert( jb_tx.randomize() with { this.flavor == self.flavor; } );
      	 `uvm_info( get_name(), { "n", jb_tx.sprint() }, UVM_LOW )
      	 finish_item( jb_tx );
            end
         endtask: body
       
         `uvm_object_utils_begin( same_flavored_jelly_beans_sequence )
            `uvm_field_int ( num_jelly_beans,                          UVM_ALL_ON )
            `uvm_field_enum( jelly_bean_transaction::flavor_e, flavor, UVM_ALL_ON )
         `uvm_object_utils_end
      endclass: same_flavored_jelly_beans_sequence
  16. Hi Keisuke,

    /////////////////////
    In the virtual sequence, we do not create sequencer, but create sequence. jb_seq1, jb_seq2.
    //////////////////

    class jelly_bean_recipe_virtual_sequence extends uvm_sequence#( uvm_sequence_item );
      ...
       jelly_bean_sequencer jb_seqr1;
       jelly_bean_sequencer jb_seqr2;
     
       same_flavored_jelly_beans_sequence jb_seq1;
       same_flavored_jelly_beans_sequence jb_seq2;
     
       function new( string name = "" );
          super.new( name );
       endfunction: new
     
       task body();
          jb_seq1 = same_flavored_jelly_beans_sequence::type_id::create( .name( "jb_seq1" ), .contxt( get_full_name() ) );
          jb_seq2 = same_flavored_jelly_beans_sequence::type_id::create( .name( "jb_seq2" ), .contxt( get_full_name() ) );
    ....
    

    //////////////////////
    In the test, we create the virtual sequence jb_vseq.
    //////////////////////

          jb_vseq = jelly_bean_recipe_virtual_sequence::type_id::create( .name( "jb_vseq" ), .contxt( get_full_name() ) );
          jb_vseq.jb_seqr1 = jb_env.jb_agent1.jb_seqr;
          jb_vseq.jb_seqr2 = jb_env.jb_agent2.jb_seqr;
          assert( jb_vseq.randomize() );
          jb_vseq.start( .sequencer( null ) );
    

    I have some questions here

    1. When should we do create? From the code, it seems like we do not need to create sequencer. My understanding is that we do not need to do type override for sequencer so that we do not need to create it in the sequence? Please correct me.

    2. In the test, I think it only pass the handle of jb_env.jb_agent1.jb_seqr to jb_vseq.jb_seqr1? Am i correct? When could we just pass the handle?

          jb_vseq.jb_seqr1 = jb_env.jb_agent1.jb_seqr;
          jb_vseq.jb_seqr2 = jb_env.jb_agent2.jb_seqr;
    

    3. if we have, for example, 4 sequences in one virtual sequence: vseq , if we want to set the default sequence, we could use virtual sequencer in the test to control it together. Is that one of the usage for virtual sequencer? If we do not have virtual sequencer and the sequencer for virtual sequence is null
    (jb_vseq.start( .sequencer( null )) , does that mean we need to set default sequence one by one in the virtual sequence. Or for virtual sequence we should only do .start, but not default sequence to start a sequence.

     uvm_config_db#(uvm_object_wrapper)::set(this,  
                                                  "env.vsqr.main_phase",  
                                                  "default_sequence",  
                                                   vseq::type_id::get()); 
    

    Thank you very much

      1. You could use a virtual sequencer, but I did not do it in my article.
      2. Yes, these are object handle assignments.
      3. If you want to start a virtual sequence as the default sequence, you need to have a virtual sequencer.
  17. Hi Keisuke,

    For virtual sequence reused by different tests, should we put the virtual sequence in env? Is that a good way? Otherwise is there any better way to handle the virtual sequence?

    Thank you very much

    Best,

  18. Hi KEISUKE,
    Will please explain the difference between import a package and include a file with a good example?

    1. The `include is a compiler directive used to insert a file as if it is copy & pasted.

      `include "jelly_bean_pkg.sv" // contents of the jelly_bean_pkg.sv is inserted here

      On the other hand, the import declaration DOES NOT insert the contents of the package. It just provides direct visibility of identifiers within a package. For example, unless you import the package, you need to use the package name qualifier when you use the jelly_bean_transaction declared in the jelly_bean_pkg.

      jelly_bean_pkg::jelly_bean_transaction jb_xact; // note the "jelly_bean_pkg::"

      With the import declaration, you can use the jelly_bean_transaction without the package name qualifier.

      import jelly_bean_pkg::*; // all identifiers in the package are "visible" in this scope
       
      jelly_bean_transaction jb_xact; // no package qualifier is needed

Leave a Reply