在接口任务中使用 force 语句的意外行为
Unexpected behavior with force statement inside interface task
当我在任务中使用强制时,我看到其他不相关信号的副作用受到影响。在下面的示例中,我尝试在模块 "dut" 中强制使用 2 个自变量 "a" 和 "b"。为此,我在界面 'intf' 中使用了辅助任务 "force1"。但是我发现更改 'b' 也会导致 'a' 发生更改,如输出所示。
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.
问题是value
是一个静态变量。当您在 Verilog 中声明一个任务时,除非您将任务指定为 automatic
,否则任务中的所有变量都将是静态的,这意味着对修改变量的任务的每次调用都会对对该任务的所有调用执行此操作(就像在 C 中创建静态局部变量一样。
同样重要的是要注意 force
程序分配不只是解析 RHS 并将 LHS 设置为该值,而是强制将 LHS 设置为 RHS 上的表达式。因此,像 force A = B;
这样的赋值将使 A
等于 B
在应用 force
时以及 B
之后可能更新的任何时间。将其与上面的信息放在一起(value
是静态的),您没有将 dut1.a
设置为 1
而您的 force
,而是将其设置为 value
。一旦 value
随您下一次调用您的任务而变化,dut1.a
也会随之变化以匹配它。
现在,不幸的是,您不能只创建任务 automatic
或只创建 value
automatic
来解决问题,因为 force
需要静态表达式(即,只有静态变量或常量的表达式)才能工作。一种解决方案是为您想要的值创建一个静态占位符,将您的 force
与您的任务输入 value
断开连接;你可以用一个数组来做到这一点:
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
当我在任务中使用强制时,我看到其他不相关信号的副作用受到影响。在下面的示例中,我尝试在模块 "dut" 中强制使用 2 个自变量 "a" 和 "b"。为此,我在界面 'intf' 中使用了辅助任务 "force1"。但是我发现更改 'b' 也会导致 'a' 发生更改,如输出所示。
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.
问题是value
是一个静态变量。当您在 Verilog 中声明一个任务时,除非您将任务指定为 automatic
,否则任务中的所有变量都将是静态的,这意味着对修改变量的任务的每次调用都会对对该任务的所有调用执行此操作(就像在 C 中创建静态局部变量一样。
同样重要的是要注意 force
程序分配不只是解析 RHS 并将 LHS 设置为该值,而是强制将 LHS 设置为 RHS 上的表达式。因此,像 force A = B;
这样的赋值将使 A
等于 B
在应用 force
时以及 B
之后可能更新的任何时间。将其与上面的信息放在一起(value
是静态的),您没有将 dut1.a
设置为 1
而您的 force
,而是将其设置为 value
。一旦 value
随您下一次调用您的任务而变化,dut1.a
也会随之变化以匹配它。
现在,不幸的是,您不能只创建任务 automatic
或只创建 value
automatic
来解决问题,因为 force
需要静态表达式(即,只有静态变量或常量的表达式)才能工作。一种解决方案是为您想要的值创建一个静态占位符,将您的 force
与您的任务输入 value
断开连接;你可以用一个数组来做到这一点:
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