3. 简单约束:范围约束、集合约束、权重分布约束
各位同学,咱们今天聊聊约束里最基础、也最常用的三种类型。说白了,就是告诉验证平台:「你生成的数据,得在我划定的圈子里玩。」
我个人习惯把约束分成两类:一类是「硬约束」,比如地址必须对齐;另一类是「软约束」,比如权重分布。今天讲的这三种,都属于日常手边的工具。
3.1 范围约束:给数据划个圈
范围约束,就是限定一个变量的取值范围。比如你写一个总线事务,地址不能超过 1MB,数据长度必须是 4 的倍数。
在 SystemVerilog 里,写法很简单:
class MyTransaction;
rand bit [31:0] addr;
rand int data_len;
constraint addr_range {
addr inside {[0:1023]}; // 地址在 0~1023 之间
}
constraint len_aligned {
data_len % 4 == 0;
data_len inside {[16:256]};
}
endclass
嗯,这里要注意一个细节:inside 后面的范围是闭区间,包含边界值。我在项目中遇到过有人写成 addr inside {[0:1024]},结果地址跑到 1024 去了,总线直接挂掉。你想想看,这种 bug 查起来多头疼。
核心要点:范围约束的边界值一定要确认清楚。特别是地址、长度这类敏感字段,建议用参数宏定义,别写死数字。
3.2 集合约束:从一堆里挑一个
集合约束比范围约束更灵活。它允许你指定一组离散的值,随机化时从里面选一个。比如操作码、状态机状态、或者某些特殊地址。
举个例子:
class Command;
rand opcode_t op;
rand bit [7:0] special_addr;
constraint op_set {
op inside {READ, WRITE, ERASE}; // 只允许这三种操作
}
constraint addr_set {
special_addr inside {8'h00, 8'h55, 8'hAA, 8'hFF};
}
endclass
我曾经犯过一个低级错误:集合里写了个重复值,比如 {READ, WRITE, READ}。仿真器不会报错,但权重会变。你想想看,READ 出现的概率是 50%,WRITE 是 50%,这跟你的预期完全不一样。
小技巧:集合约束可以和范围约束混用。比如 addr inside {[0:15], 32'hFF00, 32'hFF01},既包含连续范围,又包含离散值。这种写法在验证地址映射表时特别有用。
3.3 权重分布约束:让随机更「聪明」
权重分布约束,说白了就是让某些值出现的概率更高。比如你测试一个 FIFO,希望大部分时间写操作占 70%,读操作占 30%。
SystemVerilog 提供了 dist 操作符:
class TrafficGen;
rand operation_t op;
constraint op_weight {
op dist {
WRITE := 70, // := 表示精确权重
READ := 30
};
}
endclass
这里有个坑::= 和 :/ 的区别。我刚开始用的时候也搞混过。
:=:每个值独立分配权重。比如WRITE := 70,WRITE 的权重就是 70。:/:权重在所有值之间均分。比如WRITE :/ 70,如果 WRITE 是一个范围,那这个范围内的每个值共享这 70 的权重。
举个例子:
constraint example {
addr dist {
[0:3] := 80, // 每个地址权重 80,总共 320
[4:7] :/ 20 // 四个地址共享 20,每个 5
};
}
这种情况下,地址 0~3 出现的概率远高于 4~7。我在项目中用这种分布来模拟「热点地址」的场景,效果很好。
注意:权重分布约束不能保证精确比例,它只是概率上的倾向。如果你需要精确的序列控制,得用 randsequence 或者手动构造序列。
3.4 三种约束的对比
为了方便你记忆,我整理了一张表:
| 约束类型 | 适用场景 | 常用语法 | 注意事项 |
|---|---|---|---|
| 范围约束 | 地址、长度、时间等连续值 | inside {[min:max]} |
边界值测试要单独覆盖 |
| 集合约束 | 操作码、状态、特殊值 | inside {val1, val2, ...} |
避免重复值,注意权重变化 |
| 权重分布约束 | 概率控制、热点场景 | dist {val := weight} |
:= 和 :/ 的区别 |
3.5 知识体系总览
下面这张图,帮你把今天的内容串起来:
这张图把三种约束的关系和子知识点都列出来了。你可以把它当作一个速查表,写约束的时候瞄一眼,思路就清晰了。
总结一下:范围约束管连续区间,集合约束管离散值,权重分布约束管概率。三者结合,基本能覆盖 90% 的随机化场景。剩下的 10%,咱们后面讲更高级的约束时再聊。
可可精品资料库