Sanjeev Singh
Sanjeev Singh

Reputation: 151

Unexpected behavior with force statement inside interface task

I am seeing side affect of other unrelated signals getting affected when I use force inside a task. In the example below, I try forcing 2 independent variables "a" and "b" inside the module "dut". To do this I use the helper task "force1" inside the interface 'intf'. However I find that changing 'b' also causes 'a' to change as shown in the output.

Test case on edaplayground. https://www.edaplayground.com/x/23LM


    module dut(intf i1);
        logic a;
        logic b;
    endmodule
    interface intf;
       task force1(bit sel, int value);
         if(sel == 0) begin
            $display("[%0t]:forcing a to %0d", $stime, value);
            force dut1.a = value;
        end
        else begin
            $display("[%0t]:forcing b to %0d", $stime, value);
            force dut1.b = value;
        end
       endtask
    endinterface
    module test();
       intf intf1();
       dut dut1(intf1);
       always@(dut1.a) begin
           $display("[%0t]:Changing value of a=%0d", $stime, dut1.a);
       end
       always@(dut1.b) begin
           $display("[%0t]:Changing value of b=%0d", $stime, dut1.b);
       end
       initial begin
            intf1.force1(.sel(0), .value(1));// Change value of a to 1
            #10;
            intf1.force1(.sel(1), .value(0));// Change value of b to 0
            #10;
            $finish;
        end
    endmodule

[0]:forcing a to 1
[0]:Changing value of a=1
[10]:forcing b to 0
[10]:Changing value of a=0     ----------> WHY DID THIS CHANGE?
[10]:Changing value of b=0

I expected the output 'a' not to change to 0.

Upvotes: 1

Views: 1425

Answers (1)

Unn
Unn

Reputation: 5098

The problem is that value is a static variable. When you declare a task in Verilog, unless you specify the task to be automatic, all the variables in the task will be static, meaning each call to the task that modifies a variable does so for all calls to that task (its like creating a static local variable in C).

Its also important to note that force procedural assignments dont just resolve the RHS and set the LHS to that value, but instead forces the LHS to be set to the expression on the RHS. So, an assignment like force A = B; will make A equal to B at the time the force is applied as well as any time B might be updated after. Putting this together with information above (value is static), you arent setting dut1.a to be 1 with your force, but setting it to be value. Once value changes with your next call to your task, dut1.a also changes to match it.

Now, unfortunately, you cant just make the task automatic or just make value automatic to solve the problem since force requires a static expression (ie, an expression of only static variables or constants) to work. One solution is to create a static placeholder for the values you want that disconnects your force from your task input value; you can do that with an array:

task force1(bit sel, int value);
  static int values[1 << $bits(sel)]; // <- Make sure no matter the width of sel, there are enough places in the array, could just be values[2]
  values[sel] = value;
  if(sel == 0) begin
    $display("[%0t]:forcing a to %0d", $stime, value);
    force dut1.a = values[0];
  end
  else begin
    $display("[%0t]:forcing b to %0d", $stime, value);
    force dut1.b = values[1];
  end
endtask

Upvotes: 2

Related Questions