Search code examples
verilogsystem-veriloguvm

Why does begin/end allow me to declare a variable partway through a SystemVerilog task?


I am trying to execute a sequence within the run_phase() task of a uvm_test derived class. I raise an objection at the start of the task; declare, create, and execute a sequence on a sequencer; drop the objection.

task run_phase(uvm_phase phase);
  
  phase.raise_objections(this);
  
  uvm_sequence seq;
  seq = uvm_sequence::type_id::create("seq");
  seq.start(m_env.m_sequencer);
  
  phase.drop_objections(this);

endtask: run_phase

This gives me the error

expecting an '=' or '<=' sign in an assignment

referring to the statement uvm_sequence seq.

I know now that I can't declare a variable midway through a task unless I assign a value when I declare it. However, if I use begin/end statements, I can declare the sequence after I raise the objection, as such

task run_phase(uvm_phase phase);
  
  phase.raise_objections(this);
  
  begin
    uvm_sequence seq;
    seq = uvm_sequence::type_id::create("seq");
    seq.start(m_env.m_sequencer);
  end
  
  phase.drop_objections(this);

endtask: run_phase

This code compiles fine. What is it about the begin/end block that allows me to declare a variable mid-task?


Solution

  • IEEE Std 1800-2017, section 9.3.1 Sequential blocks shows the syntax for a begin/end block as:

    begin [ : block_identifier ] { block_item_declaration } { statement_or_null }
    end [ : block_identifier ]
    

    After the begin keyword, you can add an optional block name followed by declarations of variables, if any. These variables are local to the begin block.

    This means that you can declare variables inside the task body after other procedural statements, like the call to raise_objections.


    If you don't want to use begin/end there, you could place the seq declaration before the raise_objections call:

    task run_phase(uvm_phase phase);
      
      uvm_sequence seq;
    
      phase.raise_objections(this);
      
      seq = uvm_sequence::type_id::create("seq");
      seq.start(m_env.m_sequencer);
      
      phase.drop_objections(this);
    
    endtask: run_phase