The task calling is not giving desired result

Hi,
When i run the below code I am expecting the result as addr12 = 25, addr34 = 5.
But I am getting the result is 0 0.

module tb;
  //bit clk;
  bit [3:0] addr1, addr2, addr3, addr4;
  bit [4:0] addr12, addr34;
  assign addr1 = 12;
  assign addr2 = 13;
  assign addr3 = 2;
  assign addr4 = 3;
    
  task automatic addr_add(input bit [3:0] a,b, output bit[4:0] c);
    c = a+b;
  endtask
  
  initial begin
    addr_add(addr1, addr2, addr12);
    addr_add(addr3, addr4, addr34);
    $display("addr12 = %d, addr34 = %d", addr12, addr34);
  end
   
endmodule

Can someone please explain what am I missing in this?

In reply to parvez ahmed:

This is a time 0 race condition. Continuous assign statements are in effect like concurrent processes that start at time 0 along with initial blocks. If the initial block begins execution first, then you get the 0 results.

A couple of ways of fixing this are instead of the using the continuous assignments:

  • use static variable initializations which are guaranteed to execute before any initial or always block.
bit [3:0] addr1 = 12, addr2 = 13, addr3 = 2, addr4= 3;
  • Put the initializations in the initial block before calling the tasks
initial begin
addr1 = 12;
addr2 = 13;
addr3 = 2;
addr4 = 3;
addr_add(addr1, addr2, addr12);
addr_add(addr3, addr4, addr34);
$display("addr12 = %d, addr34 = %d", addr12, addr34);
end
  • or use the continuous assignments, but add a delay before calling the tasks
initial begin #1
addr_add(addr1, addr2, addr12);
addr_add(addr3, addr4, addr34);
$display("addr12 = %d, addr34 = %d", addr12, addr34);
end

In reply to dave_59:

Hi Dave,
Thank you very much for you timely response.
The solutions you mentioned are working fine.
But my actual requirement is a bit complex than this.
The above mentioned is just a sample code.
I am posting a bit more complex than the above code.

module tb;
  bit clk1, clk2, clk3;
  bit [3:0] cnt1;
  bit [3:0] cnt2;
  bit clk1_2nd_pos_to_102_pos;
  bit clk2_2nd_pos_to_102_pos;
  
  initial begin
    forever begin
    	#10 clk1 = !clk1;
    end
  end
  
  initial begin
  	forever begin
    	#15 clk2 = !clk2;
  	end
  end
  
  initial begin
    forever begin
    	#5 clk3 = !clk3;
    end
  end
  
  task counter(bit [3:0] count, bit clk_local, enable);
    @(posedge clk_local);
    if(enable)
      count = count + 1;
    else
      count = 0;
  endtask
  
  task sec_to_102_edge_det(bit clk_lc, bit enable);
    if(!enable) begin //{
      repeat(2)
        @(posedge clk_lc);
      enable = 1;
    end //}
    else begin //{
      repeat(100)
        @(posedge clk_lc);
      enable = 0;
    end //}
  endtask
  
  initial begin
    fork
      forever counter(cnt1, clk1, clk1_2nd_pos_to_102_pos);
      forever sec_to_102_edge_det(clk1, clk1_2nd_pos_to_102_pos);
      forever counter(cnt2, clk2, clk2_2nd_pos_to_102_pos);
      forever sec_to_102_edge_det(clk2, clk2_2nd_pos_to_102_pos);
    join
  end
  
  initial begin
    $dumpfile("dump.vcd"); $dumpvars;
    #10000;
    $finish;
  end
  
  always@(posedge clk3)begin
    if(cnt1 < 5)
      $display("cnt1 = %d at timee = %t", cnt1, $time);
  end
  
  always@(posedge clk3)begin
    if(cnt2 < 5)
      $display("cnt2 = %d at timee = %t", cnt2, $time);
  end
  
endmodule

Your text to link hereā€¦

I am facing the same issue mentioned above here.
Can you please provide solution for this also?

Thanks and regards,
Parvez

In reply to parvez ahmed:

You have several significant flaws in you code. I recommend that you read Section 13.3 of the LRM regarding tasks and how they are utilized. Specifically, the direction of formal arguments and the difference between static and automatic tasks.