Using wait(valid) in monitor get double transaction

In reply to Elaine_71:

Several issues:
You are using the virtual interface in the sequence. Your sequence should never access or use any parts of the vif. It is solely to generate untimed transactions. Remove the vif from your sequence and the @(vif.mon_cb).

In your monitor, you want to use the clocking block to synchronize signal values.


// Monitor
class alu_monitor extends uvm_monitor;
  ...
  function void build_phase(uvm_phase phase);
    super.build_phase(phase);
    // get intf
    if(!uvm_config_db #(virtual alu_if)::get(this,"","alu_if", intf)) begin
      uvm_report_fatal("", "");
    end
  endfunction
    
  task run_phase(uvm_phase phase);
    alu_op_tr tr;
    forever begin
      while ((intf.mon_cb.val != 1) || (intf.mon_cb.reset == 1)) @(intf.mon_cb);
      tr = alu_op_tr::type_id::create("tr")); // temp var
      tr.val = intf.mon_cb.val;
      tr.Opcode = intf.mon_cb.Opcode;
      tr.SrcA = intf.mon_cb.SrcA;
      mon_cnt=mon_cnt+1;
      `uvm_info("alu_mon:", $sformatf("[TIME===%4t] monitor alu: [cnt %4d] val:%d Opc:0x%x SrcA:0x%x",  $time, mon_cnt, tr.val, tr.Opcode, tr.SrcA), UVM_LOW)
      alu_op_ap.write(tr);
    end
  endtask
 
endclass