现在,让我们看看在约束块中编写约束表达式的一些常见方法。
请注意,表达式中只能有一个关系运算符< <= > >=。
class MyClass;
rand bit [7:0] min, typ, max;
// Valid expression
constraint my_range { 0 < min;
typ < max; typ > min;
max < 128; }
// Use of multiple operators in a single expression is not allowed
constraint my_error { 0 < min < typ < max < 128; } // This will set min to 16 and randomize all others constraint my_min { min == 16; } // This will set max to a random value greater than or equal to 64 constraint my_max { max >= 64; }
endclass
不能在约束块内进行指定,因为它只包含表达式。相反,您必须使用等价运算符==如上面示例中名为my_min的约束所示,其中min将获得16的值,所有其他变量都将随机化。这是一种将特定值固定到变量的方法,即使解算器尝试将其随机化。
constraint my_min { min == temp.low * 9/5 + 32; }
您还可以使用更复杂的表达式,如上面所示,其中min表示存储华氏温度的变量,low是类对象temp中的一个变量,该变量保存摄氏温度。
class myClass;
rand bit [3:0] min, typ, max;
rand bit [3:0] fixed;
constraint my_range { 3 < min;
typ < max; typ > min;
max < 14; }
constraint c_fixed { fixed == 5; }
function string display ();
return $sformatf ("min=%0d typ=%0d max=%0d fixed=%d", min, typ, max, fixed);
endfunction
endclass
module tb;
initial begin
for (int i = 0; i < 10; i++) begin
myClass cls = new ();
cls.randomize();
$display ("itr=%0d %s", i, cls.display());
end
end
endmodule
请注意,fixed 变量固定为值5,而其他变量已随机化为满足所有约束的值。
# KERNEL: itr=0 min=7 typ=9 max=12 fixed= 5
# KERNEL: itr=1 min=4 typ=9 max=12 fixed= 5
# KERNEL: itr=2 min=7 typ=10 max=13 fixed= 5
# KERNEL: itr=3 min=4 typ=6 max=11 fixed= 5
# KERNEL: itr=4 min=8 typ=12 max=13 fixed= 5
# KERNEL: itr=5 min=5 typ=6 max=13 fixed= 5
# KERNEL: itr=6 min=6 typ=9 max=13 fixed= 5
# KERNEL: itr=7 min=10 typ=12 max=13 fixed= 5
# KERNEL: itr=8 min=5 typ=11 max=13 fixed= 5
# KERNEL: itr=9 min=6 typ=9 max=11 fixed= 5
可以使用inside 运算符指定下限和上限,以替代下面显示的表达式。
constraint my_range { typ > 32;
typ < 256; } // typ >= 32 and typ <= 256
constraint new_range { typ inside {[32:256]}; }
// Choose from the following values
constraint spec_range { type inside {32, 64, 128}; }
请注意,内部构造包括下限和上限。SystemVerilog收集所有值,并以相等的概率在值之间进行选择,除非变量有其他约束。
如果需要特定范围之外的任何值,则可以按如下方式编写反向约束。这将产生一个从0到31的随机值,因为typ是一个8位变量,并且上限已经覆盖了它可以保持的最大值。
rand bit [2:0] typ;
constraint inv_range { ! (typ inside {[3:6]}); }
注意,重复随机化给出了除落在范围3至6内的值之外的所有值。
# KERNEL: itr=0 typ=7
# KERNEL: itr=1 typ=0
# KERNEL: itr=2 typ=7
# KERNEL: itr=3 typ=0
# KERNEL: itr=4 typ=0
# KERNEL: itr=5 typ=0
# KERNEL: itr=6 typ=7
# KERNEL: itr=7 typ=1
# KERNEL: itr=8 typ=1
# KERNEL: itr=9 typ=7
dist运算符允许您创建加权分布,以便选择某些值的频率高于其他值。:=运算符指定范围内的每个指定值的权重相同,而 /= 运算符指定权重在所有值之间等分。
:= operatorrand bit [2:0] typ;
constraint dist1 { typ dist { 0:=20, [1:5]:=50, 6:=40, 7:=10}; }
在dist1中,0的权重为20,6为40,7为10,而1到5为50,总共为320。因此,选择0的概率为20/320,选择1到5之间的值的概率为50/320。让我们来看一个简单的示例。
class myClass;
rand bit [2:0] typ;
constraint dist1 { typ dist { 0:=20, [1:5]:=50, 6:=40, 7:=10}; }
endclass
module tb;
initial begin
for (int i = 0; i < 10; i++) begin
myClass cls = new ();
cls.randomize();
$display ("itr=%0d typ=%0d", i, cls.typ);
end
end
endmodule
在下面显示的日志中,请注意,1到5出现的次数超过0、6或7,因为它们的权重更高,选择频率更高。
# KERNEL: itr=0 typ=5
# KERNEL: itr=1 typ=1
# KERNEL: itr=2 typ=6
# KERNEL: itr=3 typ=3
# KERNEL: itr=4 typ=2
# KERNEL: itr=5 typ=3
# KERNEL: itr=6 typ=0
# KERNEL: itr=7 typ=5
# KERNEL: itr=8 typ=1
# KERNEL: itr=9 typ=4
/= operatorrand bit [2:0] typ;
constraint dist2 { typ dist { 0:/20, [1:5]:/50, 6:/10, 7:/20}; }
在dist2中,0的权重为20,6为10,7为20,而1到5的总权重为50,因此各有10。因此,选择0的概率是20/100,选择1和5之间的值的概率是10/100。
class myClass;
rand bit [2:0] typ;
constraint dist2 { typ dist { 0:/20, [1:5]:/50, 6:/40, 7:/10}; }
endclass
module tb;
initial begin
for (int i = 0; i < 10; i++) begin
myClass cls = new ();
cls.randomize();
$display ("itr=%0d typ=%0d", i, cls.typ);
end
end
endmodule
在下面显示的日志中,请注意,6出现的次数比其他的多,因为它的权重最高。
# KERNEL: itr=0 typ=5
# KERNEL: itr=1 typ=6
# KERNEL: itr=2 typ=4
# KERNEL: itr=3 typ=6
# KERNEL: itr=4 typ=6
# KERNEL: itr=5 typ=4
# KERNEL: itr=6 typ=2
# KERNEL: itr=7 typ=3
# KERNEL: itr=8 typ=4
# KERNEL: itr=9 typ=6
约束块不像过程代码那样从上到下执行,而是同时处于活动状态。让我们用另一个例子来看。
class myClass;
rand bit [3:0] val;
constraint c1 { val > 3;
val < 12; } constraint c2 {val >= 10; }
endclass
module tb;
initial begin
for (int i = 0; i < 10; i++) begin
myClass cls = new ();
cls.randomize();
$display ("itr=%0d typ=%0d", i, cls.val);
end
end
endmodule
注意,约束c1和c2将值限制为10和11。
# KERNEL: itr=0 typ=11
# KERNEL: itr=1 typ=11
# KERNEL: itr=2 typ=11
# KERNEL: itr=3 typ=10
# KERNEL: itr=4 typ=11
# KERNEL: itr=5 typ=10
# KERNEL: itr=6 typ=10
# KERNEL: itr=7 typ=10
# KERNEL: itr=8 typ=10
# KERNEL: itr=9 typ=10