Ways to make calls of two tasks to execute concurrently?

Hi I’m SystemVerilog novice. For starter, I’m building a very simple testbench to verify a very simple RTL. I just want to get myself used to the structure, so i guess the complexity of rtl doesn’t matter (for now).

I’ve already built testbench.sv, testcase.sv, packet.sv, switch_interface.sv, and monitor.sv. Inside the env.sv, i have a run task that calls driver.send_packet() first and monitor.collect_packet() later. This implies that the output packets will be collected after packets have already sent in. they executes in order, serially. Is there a way to make the them executing concurrently and simultaneously so that packets can be collected and sent and the same time? I think i need some code-restructuring but don’t know where to start…
My code is here: https://drive.google.com/file/d/0B5eA_2-8U5JnaHF5aUdsTHV0NEE/view?usp=sharing
Also the env.sv

class env;
	driver 				drv;
	monitor				mon;
	virtual switch_interface	vi;
	virtual switch_interface	mi;

	function new(input virtual switch_interface vif,
		     input virtual switch_interface mif);
		this.vi = vif;
		this.mi = mif;
		
		drv	= new(vif);
		mon	= new(mif);
	endfunction

	task run(int num_packet=4);
		for(int i=0; i<num_packet;i++) begin
		  @(posedge vi.clk)
		  $display("==========time=%0d:Sending packet #%0d==========",$time, i+1);
		  drv.send_packet();

		  @(posedge mi.clk)
		  $display("==========time=%0d:Collecting packet #%0d=========",$time, i+1);
		  mon.collect_packet();
		end 
	endtask
endclass

In reply to tyyang:

Hello,

You can use “fork join” construct to run the two processes in parallel.

I would highly recommend that you use the UVM as part of your learning process. You are duplicating many of the UVM features (driver, monitor, environment, etc.) that have been designed and implemented by experts with many years of verification experience, and are encountering issues that have already been addressed in the most efficient manner.

While you might consider it a good learning experience to write your own testbench methodology, you could at least refer to the UVM source code to see how specific challenges have been implemented.

Hi
For the sake of completeness, an example of where the task forks to perform the two subtasks in parallel and then waits until they have both finished is below. You could also replace “join” with “join_none” to have the main task exit immediately, leaving the two subtasks to run completely asynchronously.

However, as has already been suggested, a purer UVM style of independent drivers and monitors would be a better investment of your time. While knowledge of fork/join is very useful, it leads to more convoluted and non-standard coding in this case with more potential for bugs or hidden dependencies which mean that the DUT is not stimulated as randomly as possible.

	
task run(int num_packet=4);
for(int i=0; i<num_packet;i++) begin
  @(posedge vi.clk)
  $display("==========time=%0d:Sending packet #%0d==========",$time, i+1);

  fork
    begin
      drv.send_packet();
      $display("==========time=%0d:Sent packet #%0d=========",$time, i+1);
    end
    begin
      mon.collect_packet();
      $display("==========time=%0d:Collected packet #%0d=========",$time, i+1);
    end 
  join
endtask

In reply to Richard Hamer (EnSilica):

That was a very thorough answer. Thx a ton!
Yeah I am actually learning UVM, slowly. Currently I reading this great tutorial UVM Guide for Beginners – Pedro Araújo not too hard to understand.