Actual argument passed as reference cannot be used within fork-join_any or fork_join_none

Some interesting caveats about fork/join and arguments, solutions and issues.

  1. In a task, if an actual argument is passed as reference then that task cannot be used within fork-join_any or fork_join_none blocks (see ILLEGAL example below)
  2. A potential solution is to use the inout instead of the ref (see INOUT example below)
  3. However, with the inout 1800:13.3 says: inout is a copy in at beginning and out at end,
    unlike the ref that ties the actual variable to the referred variable, and is thus immediate.
    The issue is important when mutiple instances of forks try to update individual bits of that referenced variable using the inout, instead of the ref. (see INOUT example below)

ILLEGAL example


module top; 
	bit clk, a, b;  
    task automatic t_top(); 
        automatic bit[1:3] vt_top=1; 
        fork t_2(vt_top); join_none   
        wait(vt_top==3'b110);    
    endtask :  t_top

    task automatic t_2(ref bit[1:3] vt_top);  
        fork t_3(1, vt_top); t_3(2, vt_top); join_none   // 2 forks 
        // Actual argument 'vt_top' passed as inouterence
        // cannot be used within fork-join_any or fork_join_none blocks               
    endtask

    task automatic t_3(int i, ref bit[1:3] vt_top); 
        vt_top[i]=1'b1; 
        // 1800:13.3 ref // pass reference (see 13.5.2)  
    endtask
    
    always_ff  @(posedge clk)  
        fork t_top(); join_none // (file http://SystemVerilog.us/vf/inout_illegal2.sv)
endmodule  

INOUT example


module top; 
	bit clk, a, b;  
    task automatic t_top(); 
        automatic bit[1:3] vt_top=1; 
        fork t_2(vt_top); join_none   
        wait(vt_top==3'b110);  // this will never happen 
        //  because will be either vt_top==3'b100 or vt_top==3'b010 
        //  depending upon which t_3 ends last     
    endtask :  t_top

    task automatic t_2(inout bit[1:3] vt_top);  
        fork t_3(1, vt_top); t_3(2, vt_top); join_none   // 2 forks 
        // Actual argument 'vt_top' passed as inouterence
        // cannot be used within fork-join_any or fork_join_none blocks               
    endtask

    task automatic t_3(int i, inout bit[1:3] vt_top); 
        vt_top[i]=1'b1; 
        // 1800:13.3 inout // copy in at beginning and out at end
        // Assume 1st fork: i==1, vt_top==3'b000 at beginning, vt_top==3'b1000 at end 
        // Assume 2nd fork: i==2, vt_top==3'b000 at beginning, vt_top==3'b0100 at end 
    endtask
    
    always_ff  @(posedge clk)  
        fork t_top(); join_none // (file http://SystemVerilog.us/vf/ref_inout.sv)
endmodule  

Ben Cohen
http://www.systemverilog.us/ ben@systemverilog.us
For training, consulting, services: contact Home - My cvcblr


  1. SVA Alternative for Complex Assertions
    Verification Horizons - March 2018 Issue | Verification Academy
  2. SVA: Package for dynamic and range delays and repeats | Verification Academy
  3. SVA in a UVM Class-based Environment
    SVA in a UVM Class-based Environment | Verification Horizons | Verification Academy