SystemVerilog为我们提供了两种声明条件关系的结构-implication和if_else.
以下代码片段显示了两种样式:
// implication运算符“->”告诉您,当mode等于2时len应该大于10
constraint c_mode { mode == 2 -> len > 10; }
// Same thing can be achieved with "if-else" construct
constraint c_mode { if (mode == 2)
len > 10;
}
注意,对于所有大于10的len值,mode不必为2。但是,如果mode是2,则约束条件是len应该大于10。
Example
class ABC;
rand bit [2:0] mode;
rand bit [3:0] len;
constraint c_mode { mode == 2 -> len > 10; }
endclass
module tb;
initial begin
ABC abc = new;
for(int i = 0; i < 10; i++) begin
abc.randomize();
$display ("mode=%0d len=%0d", abc.mode, abc.len);
end
end
endmodule
Simulation Log
ncsim> run
mode=1 len=11
mode=6 len=3
mode=3 len=9
mode=7 len=11
mode=3 len=15
mode=2 len=12
mode=3 len=6
mode=2 len=12
mode=4 len=9
mode=7 len=13
ncsim: *W,RNQUIE: Simulation is complete.
仿真结果表明,当len大于10时,模式不必取值为2。
implication运算符
implication运算符->可以在约束表达式中使用,以显示两个变量之间的条件关系。
如果->运算符的LHS上的表达式为true,则将满足RHS上的约束表达式。 如果LHS不为真,则不考虑RHS约束表达式。
(LHS和RHS含义是赋值操作的左侧与右侧。)
Example
class ABC;
rand bit [3:0] mode;
rand bit mod_en;
// If 5 <= mode <= 11, mod_en should be 1
constraint c_mode { mode inside {[4'h5:4'hB]} -> mod_en == 1; }
endclass
module tb;
initial begin
ABC abc = new;
for (int i = 0; i < 10; i++) begin
abc.randomize();
$display ("mode=0x%0h mod_en=0x%0h", abc.mode, abc.mod_en);
end
end
endmodule
Simulation Log
ncsim> run
mode=0xf mod_en=0x1
mode=0x9 mod_en=0x1
mode=0x3 mod_en=0x1
mode=0xe mod_en=0x1
mode=0x1 mod_en=0x1
mode=0x0 mod_en=0x0
mode=0x1 mod_en=0x0
mode=0xe mod_en=0x0
mode=0x5 mod_en=0x1
mode=0x0 mod_en=0x0
ncsim: *W,RNQUIE: Simulation is complete.
请注意,每当mode的LHS表达式在4’h5和4’hB内部时,mod_en为1。但是,如果LHS评估为false,则可以将mod_en随机化为任何值。
if-else约束
if-else约束提供了一个选项,用于指定条件表达式的else部分。 如果条件表达式为真,则应满足第一个约束中指定的所有约束。 否则,将满足可选else部分中的所有约束。
允许嵌套的if-else块,并且多个约束语句要求将它们括在花括号{}中。 这类似于在程序块(如initial和always)中使用的begin-end。 但是,约束被归类为声明性代码,因此需要大括号。
Example
在下面显示的代码中,第一个if块检查mode是否在5和11内。如果此条件为true,则应将mod_en约束为1,如果为false,则执行else部分。 else部分中还有另一个if-else块,该块检查mode是否为1并尝试满足相应部分中提到的约束。
class ABC;
rand bit [3:0] mode;
rand bit mod_en;
constraint c_mode {
// If 5 <= mode <= 11, then constrain mod_en to 1
// This part only has 1 statement and hence do not
// require curly braces {}
if (mode inside {[4'h5:4'hB]})
mod_en == 1;
// If the above condition is false, then do the following
else {
// If mode is constrained to be 1, then mod_en should be 1
if ( mode == 4'h1) {
mod_en == 1;
// If mode is any other value than 1 and not within
// 5:11, then mod_en should be constrained to 0
} else {
mod_en == 0;
}
}
}
endclass
module tb;
initial begin
ABC abc = new;
for (int i = 0; i < 10; i++) begin
abc.randomize();
$display ("mode=0x%0h mod_en=0x%0h", abc.mode, abc.mod_en);
end
end
endmodule
Simulation Log
ncsim> run
mode=0xb mod_en=0x1
mode=0x1 mod_en=0x1
mode=0x6 mod_en=0x1
mode=0x7 mod_en=0x1
mode=0x2 mod_en=0x0
mode=0x2 mod_en=0x0
mode=0x2 mod_en=0x0
mode=0x9 mod_en=0x1
mode=0x7 mod_en=0x1
mode=0x8 mod_en=0x1
ncsim: *W,RNQUIE: Simulation is complete.
参考文献:
【1】https://www.chipverify.com/systemverilog/systemverilog-implication-constraint