Search code examples
system-veriloguvm

SystemVerilog UVM Hello World Testbench error: expecting an '=' or '<=' sign in an assignment [9.2(IEEE)]


I modified a hello world UVM testbench on Eda Playground to create hierarchy of uvm sequence. While creating object of base class sequence from the virtual task body of the child class, I get the following error:

xmvlog: *E,MISEXX (my_sequence.svh,72|29): expecting an '=' or '<=' sign in an assignment [9.2(IEEE)].

The offending line of code is:

base_sequence base_seq_obj = base_sequence::type_id::create("base_seq_obj");

The entire code is at this link. Only the UVM systemverilog code for the hierarchical sequences is as follows:

my_sequence.svh

class my_transaction extends uvm_sequence_item;

  `uvm_object_utils(my_transaction)

  rand bit cmd;
  rand int addr;
  rand int data;

  constraint c_addr { addr >= 0; addr < 256; }
  constraint c_data { data >= 0; data < 256; }

  function new (string name = "");
    super.new(name);
  endfunction

endclass: my_transaction

class base_sequence extends uvm_sequence #(my_transaction);
 `uvm_object_utils(base_sequence)
  
  rand int value;
  
  function new(string name = "base_sequence");
    super.new(name);  
  endfunction : new
  
  virtual task body;
    `uvm_info("UVM_SEQUENCE:base_sequence", "Body Started", UVM_MEDIUM);
    
    req = my_transaction::type_id::create("req");
    `uvm_info("UVM_SEQUENCE", "start_item call started", UVM_MEDIUM);
    start_item(req);
    `uvm_info("UVM_SEQUENCE", "start_item call ended", UVM_MEDIUM);


    `uvm_info("UVM_SEQUENCE", "before randomized", UVM_MEDIUM);
    if (!req.randomize()) begin
      `uvm_error("MY_SEQUENCE", "Randomize failed.");
    end

    `uvm_info("UVM_SEQUENCE", "after randomized", UVM_MEDIUM);

    // If using ModelSim, which does not support randomize(),
    // we must randomize item using traditional methods, like
    // req.cmd = $urandom;
    // req.addr = $urandom_range(0, 255);
    // req.data = $urandom_range(0, 255);

    `uvm_info("UVM_SEQUENCE", "Before finish_item call.", UVM_MEDIUM);
    finish_item(req);
    `uvm_info("UVM_SEQUENCE", "After finish_item call.", UVM_MEDIUM);
    
    `uvm_info("UVM_SEQUENCE:base_sequence", "Body Ended", UVM_MEDIUM);
  endtask : body
  
endclass: base_sequence

class my_sequence extends base_sequence;

  `uvm_object_utils(my_sequence)
  
  rand integer n_times;
  
  constraint times { n_times inside { [1:4] };}

  function new (string name = "");
    super.new(name);
  endfunction

  virtual task body;
    `uvm_info("UVM_SEQUENCE:my_sequence", "Body Started", UVM_MEDIUM);
    base_sequence base_seq_obj = base_sequence::type_id::create("base_seq_obj");
    base_seq_obj.randomize();
    value = base_seq_obj.value;    
    
    repeat(n_times) begin
      `uvm_do_with(base_seq, {base_seq_obj.value  == value;}) 
    end
    `uvm_info("UVM_SEQUENCE:my_sequence", "Body Ended", UVM_MEDIUM);
  endtask: body

endclass: my_sequence


Solution

  • Within any procedural block, variable declarations must precede any other statements. Change

    virtual task body;
        `uvm_info("UVM_SEQUENCE:my_sequence", "Body Started", UVM_MEDIUM);
        base_sequence base_seq_obj = base_sequence::type_id::create("base_seq_obj");
        base_seq_obj.randomize();
        ...
    

    to

    virtual task body;
        base_sequence base_seq_obj = base_sequence::type_id::create("base_seq_obj");
        `uvm_info("UVM_SEQUENCE:my_sequence", "Body Started", UVM_MEDIUM);
        base_seq_obj.randomize();
        ...
    

    or you can split the declaration from the initialization

    virtual task body;
        base_sequence base_seq_obj;
        `uvm_info("UVM_SEQUENCE:my_sequence", "Body Started", UVM_MEDIUM);
        base_seq_obj = base_sequence::type_id::create("base_seq_obj");
        base_seq_obj.randomize();
        ...