在systemverilog中使用约束时经常会遇到如下的问题以下列出进行辨析QArand类型的变量可以通过rand_mode(0)关闭随机属性非rand类型的变量可以通过rand_mode(1)开启随机属性吗1. rand 类型变量通过 rand_mode(0) 设置有效这是非常常见的用法。它可以将原本参与随机化的变量在仿真运行期间“冻结”使其从随机变量变为固定值。2. 非 rand 类型变量通过 rand_mode(1) 设置无效且无意义在 SystemVerilog 标准IEEE 1800中rand_mode() 这个函数只有在变量声明时带有 rand 或 randc 关键字时才起作用。如果变量未声明为 rand编译器在类定义时就已经将其排除在“随机化列表”之外。即使你在仿真过程中调用 my_non_rand_var.rand_mode(1)SystemVerilog 也会忽略该操作。该变量依然是普通的类成员randomize() 调用永远不会尝试修改它也不会将其视为待求解对象。QAconstraint什么时候才会生效具体来说约束生效需要满足以下 三个核心条件1. 触发动作调用 randomize() 函数这是约束生效的唯一直接触发点。当你执行 object.randomize() 时仿真器的约束求解器Solver会启动。求解器会扫描类中所有标记为 rand 的变量并根据当前的 constraint 规则计算出一组合法的值。如果不调用 randomize()你直接给变量赋值如 p.data 500;即使这个值违反了约束比如约束要求 data 100仿真器也不会报错约束此时处于“休眠”状态。2. 状态开关constraint_mode 必须为 1 默认为1每个约束块都有一个隐藏的开关。默认情况下它是开启的1。如果你执行了 obj.c_limit.constraint_mode(0);那么名为 c_limit 的约束块就会失效。即使随后调用 randomize()求解器也会完全无视这个约束块里的规则。3. 逻辑前提满足 if 或 solve...before 的前置条件如果约束写在 if...else 或 implication (-) 语句中它只有在条件成立时才会生效。示例 constraint c_xy { (mode 1) - (x y); }如果 mode 被随机化为 0那么 x y 这个约束不生效。QA: constraint中可以写非随机变量吗可以1. 非随机变量在约束中的表现当约束求解器Solver遇到非随机变量时它会遵循以下规则只读属性求解器只能读取该变量当前的值绝对不会修改它。作为常量在随机化过程中非随机变量被视为一个“常数”。所有的随机变量rand必须根据这个“常数”的值来计算自己的合法范围。约束无法改变非随机变量的值。如果一个随机变量被设置为rand_mode(0)那么它在约束中和上述非随机变量的行为等同。class Generator; int max_val 100; // 非随机变量 rand int data; // 随机变量 constraint c_range { data inside {[0 : max_val]}; } endclass // 在测试用例中 gen.max_val 50; gen.randomize(); // data 的范围自动变为 0-502. 场景 B作为 if 或 - (推导) 的开关非随机变量常被用来开启或关闭特定的协议特性。class Packet; bit enable_checksum; // 非随机变量 rand bit [7:0] crc; // 随机变量 constraint c_crc { if (enable_checksum 1) { crc 0; } else { crc 0; } } endclass上述两种情况非随机变量都是作为边界或者条件本身并没有被施加约束。但如果非随机变量被施加了约束同样受到约束的检查如果不在约束范围内就会报错。class Packet; rand bit [7:0] addr; constraint c_addr { addr 100; } endclass // --- 在 Test 中 --- Packet p new(); p.addr 200; // 手动给一个非法值 p.addr.rand_mode(0); // 锁定 addr if (!p.randomize()) { $display(随机化失败因为 addr200 违反了 addr 100 的约束); }这里的非随机变量指的是声明时不带rand 关键字的变量声明时带rand关键字的变量但是通过rand_mode(0)关闭了随机属性约束对于随机变量和非随机变量都具有约束作用只不过非随机变量约束只是做检查而无法改变非随机变量的值。