scopeverilog

Variable scope verilog: Why does $display inside the task print the global variable sig and not the local variable sig that was declared within task


When I run this I get sig value = 3 from both the displays Why does the $display within the task take the global variable sig = 3 instead of the local variable sig declared within the task signal = 2? Can someone please help me understand?

module tb; 
  reg[1:0] sig; 
  
  task task1(sig); 
    reg[1:0] sig = 2;
    $display("signal = %0b", sig); 
  endtask 
  
  initial begin 
    sig = 3; 
    task1(sig); 
    $display("signal after running display() task = %0b", sig); 
  end 
endmodule


Solution

  • The code you wrote is illegal in SystemVerilog. If fact, this is probably the only backward incompatible language feature of Verilog not allowed in SystemVerilog that I can think of.

    The problem is you think task1.sig is being initialized to 2 every time the task gets called. But it is a static variable that gets initialized once at time 0 before any initial or always blocks have started their processes. If you had declared the task with an automatic lifetime, or used an explicit automatic lifetime in the declaration on the variable, then it would get initialized upon each activation of the task. SystemVerilog requires variable declarations inside procedural blocks of code with initializations to either have an automatic lifetime, or an explciit static keyword.

    But in any case, you have declared sig as an input to the task (which is the implicit direction). So the actual argument tb.sig gets copied to the formal argument task1.sig.

    Reusing the same name for the actual and formal arguments is a poor programming practice. Also, you should be using the Verilog-2001 style of argument declarations.

    task task1(input reg [1:0] sig); 
    

    Now if you add an initialization

    task task1(input reg [1:0] sig = 2); 
    

    This gets interpreted in SystemVerilog as a optional argument whose default value is 2.