Event control for combinational circuits

Ive wriiten uvm testbench for full adder which does not operates on clk and reset. I used event control like @(posedge intf.a,intf.b,intf.cin) , is it the right way to do it?

In reply to Kamran:

Driver code:


class mem_driver extends uvm_driver #(mem_seq_item);
   `uvm_component_utils(mem_driver)

  // Virtual Interface
  virtual mem_if intf;

  mem_seq_item item;
   
  // Constructor
  function new (string name = "mem_driver", uvm_component parent);
    super.new(name, parent);
  endfunction : new

  function void build_phase(uvm_phase phase);
    super.build_phase(phase);
    if(!uvm_config_db #(virtual mem_if)::get(null,"*","vif",intf))
	begin
	`uvm_error("Driver Class","Failed to get vif from config_db")
	end
  endfunction: build_phase
  
   function void connect_phase(uvm_phase phase);
    super.connect_phase(phase);
    `uvm_info("DRIVER_CLASS", "Connect Phase!", UVM_HIGH)
    
  endfunction: connect_phase

  // run phase
   task run_phase(uvm_phase phase);
  
  item = mem_seq_item::type_id::create("item");

      super.run_phase(phase);
    `uvm_info("DRIVER_CLASS", "Inside Run Phase!", UVM_HIGH)

    forever begin
	seq_item_port.get_next_item(item);
    drive(item);
    seq_item_port.item_done();
    end
  endtask : run_phase

  // drive 
  virtual task drive(mem_seq_item item);
     
  `uvm_info(get_type_name(), "before Posedge", UVM_MEDIUM) 
   
   @(posedge intf.a,intf.b,intf.cin)
     
   `uvm_info(get_type_name(), "before Posedge", UVM_MEDIUM) 

	
   if(intf.a==8'bxxxxxxxx && intf.b==8'bxxxxxxxx && intf.cin==1'bx)
	  begin
	 intf.a = item.a;
	 intf.b = item.b;
	 intf.cin = item.cin;
	  end

  `uvm_info(get_type_name(),"Before Dont care",UVM_NONE)

`uvm_info(get_type_name(),$sformatf("a =%d,b=%d,cin=%d",intf.a,intf.b,intf.cin),UVM_NONE) 

   if(intf.a != 8'bxxxxxxxx && intf.b != 8'bxxxxxxxx && intf.cin != 1'bx)
	  begin
	 intf.a = item.a;
	 intf.b = item.b;
	 intf.cin = item.cin;
	 end
	 
 `uvm_info(get_type_name(),"After Dont care",UVM_NONE)

`uvm_info(get_type_name(),$sformatf("a =%d,b=%d,cin=%d",intf.a,intf.b,intf.cin),UVM_NONE) 
      $display("------------------------------------------------------------------");
	 
  endtask : drive
  

endclass : mem_driver

Monitor1 code:


class mem_monitor extends uvm_monitor;
  `uvm_component_utils(mem_monitor)

  // Virtual Interface
  virtual mem_if intf;
  
  bit[7:0] q[$]; // a
   //bit[7:0] q2[$]; // b
   //bit q3[$]; //cin

  uvm_analysis_port #(mem_seq_item) item_collected_port; // port for mon to scb
  mem_seq_item item;

  // new - constructor
  function new (string name = "mem_monitor", uvm_component parent); 
    super.new(name, parent);
    item_collected_port = new("item_collected_port", this);
  endfunction : new

  function void build_phase(uvm_phase phase);
    super.build_phase(phase);
    if(!uvm_config_db #(virtual mem_if)::get(null,"*","vif",intf))
	begin
	`uvm_error("Monitor1 Class","Failed to get vif from config_db")
	end
  endfunction: build_phase
  
    //connect 
    function void connect_phase(uvm_phase phase);
    super.connect_phase(phase);
    `uvm_info("MONITOR1_CLASS", "Connect Phase!", UVM_NONE)
      endfunction: connect_phase

  // run phase
  task run_phase(uvm_phase phase);
    item = mem_seq_item::type_id::create("item");

  super.run_phase(phase);

     forever begin
        
	  //sample inputs
  `uvm_info(get_type_name(), "before Posedge", UVM_MEDIUM) 
    @(posedge intf.a,intf.b,intf.cin)
  `uvm_info(get_type_name(), "after Posedge", UVM_MEDIUM) 
	 
   if(intf.a==8'bxxxxxxxx && intf.b==8'bxxxxxxxx && intf.cin==1'bx)
	  begin
	  item.a = intf.a ;
  	 item.b = intf.b;
	 item.cin = intf.cin;
       end	 
	 `uvm_info(get_type_name(),"Before Dont Care",UVM_NONE)

   if(intf.a != 8'b00000000 && intf.b != 8'b00000000  && intf.cin != 1'b0)
	 begin
	  item.a = intf.a ;
  	 item.b = intf.b;
	 item.cin = intf.cin;
	   end	 
	 `uvm_info(get_type_name(),"After Dont care",UVM_NONE)

	
q.push_front(item.a);
q.push_front(item.b);
q.push_front(item.cin);


if(intf.a== 8'bxxxxxxxx && intf.b== 8'bxxxxxxxx && intf.cin == 1'bx )
begin
item.s=8'bxxxxxxxx;
item.cout = 1'bx;
end

else
begin
item.s=q.pop_front();
item.cout=q.pop_front();
end
	 	  
	`uvm_info(get_type_name(),$sformatf("a =%d,b=%d,cin=%d",intf.a,intf.b,intf.cin),UVM_NONE) 

 
  `uvm_info(get_type_name(),"------------------------------------------------------",UVM_NONE)
	
	item_collected_port.write(item);
	end
  endtask : run_phase
  

endclass : mem_monitor

My output log is:

UVM_INFO @ 0: reporter [RNTST] Running test mem_model_test…

UVM_INFO scoreboard.sv(14) @ 0: uvm_test_top.env.mem_scb [Scb Class] Inside constructor

UVM_INFO scoreboard.sv(21) @ 0: uvm_test_top.env.mem_scb [Scb Class] Build phase

UVM_INFO driver.sv(24) @ 0: uvm_test_top.env.mem_agnt1.driver [DRIVER_CLASS] Connect Phase!

UVM_INFO monitor1.sv(31) @ 0: uvm_test_top.env.mem_agnt1.monitor [MONITOR1_CLASS] Connect Phase!

UVM_INFO test.sv(21) @ 0: uvm_test_top [TEST_CLASS] Connect Phase!

UVM_INFO scoreboard.sv(28) @ 0: uvm_test_top.env.mem_scb [Scb Class] Inside Run phase

UVM_INFO C:/questasim64_10.7c/verilog_src/uvm-1.1d/src/seq/uvm_sequencer_base.svh(1384) @ 0: uvm_test_top.env.mem_agnt1.sequencer [PHASESEQ] No default phase sequence for phase ‘run’

UVM_INFO monitor1.sv(43) @ 0: uvm_test_top.env.mem_agnt1.monitor [mem_monitor] before Posedge

UVM_INFO driver.sv(34) @ 0: uvm_test_top.env.mem_agnt1.driver [DRIVER_CLASS] Inside Run Phase!

UVM_INFO C:/questasim64_10.7c/verilog_src/uvm-1.1d/src/seq/uvm_sequencer_base.svh(1384) @ 0: uvm_test_top.env.mem_agnt1.sequencer [PHASESEQ] No default phase sequence for phase ‘pre_reset’

UVM_INFO driver.sv(46) @ 0: uvm_test_top.env.mem_agnt1.driver [mem_driver] before Posedge

UVM_INFO C:/questasim64_10.7c/verilog_src/uvm-1.1d/src/base/uvm_phase.svh(1215) @ 0: reporter [PH_READY_TO_END] Phase ‘uvm.uvm_sched.pre_reset’ (id=172) PHASE READY TO END

UVM_INFO C:/questasim64_10.7c/verilog_src/uvm-1.1d/src/seq/uvm_sequencer_base.svh(1384) @ 0: uvm_test_top.env.mem_agnt1.sequencer [PHASESEQ] No default phase sequence for phase ‘reset’

UVM_INFO C:/questasim64_10.7c/verilog_src/uvm-1.1d/src/base/uvm_phase.svh(1215) @ 0: reporter [PH_READY_TO_END] Phase ‘uvm.uvm_sched.reset’ (id=184) PHASE READY TO END

In reply to Kamran:

You still should use an external clock even if your DUT is purely combinational.

The problem with using input signals as events in your driver is your are waiting for your inputs to change, but it will never reach the code that changes the inputs that follows. It hangs. You need to apply stimulus at a regular interval giving enough time for the inputs values to propagate through the DUT to the outputs.

And there are problems using the input signals as events in your monitor. Even if you do fix your driver, you have a race condition with the outputs as you don’t know if they have been updated to reflect the new values of the inputs or still using the old values.

The best way to do this is creating an external clock (a clock that does not go into your DUT) and using that to synchronize driving each input transaction using nonblocking assignments, and have the monitor sample the inputs/outputs using the same external clock.