经过前面章节的理论学习,我们对systemverilog中的随机约束,有一定的了解,那么,今天开始,着重讲述一些工作中遇到的困惑。主要通过一些例子,层层递进,举一反三,源于实践,剖析书本中没有提到硬性知识。
案例源代码
我们先看一个例子,例子很简单,但是却暴露了一些问题,百思不得其解。
`timescale 1ns/1ps
`include "uvm_macros.svh"
import uvm_pkg::*;
class my_obj1 extends uvm_test;
`uvm_component_utils(my_obj1)
rand int src=4;
rand int dst=2;
constraint dst_c {
dst inside {[5:9]};
}
rand bit [3:0] crc = 4'b0111;
constraint crc_c {
crc inside {5,6,7,8};
}
function new(string name = "my_obj1" , uvm_component parent = null );
super.new(name, parent);
endfunction // new
extern virtual function print ();
virtual task run_phase(uvm_phase phase);
super.run_phase(phase);
this.print();
endtask
endclass //
function my_obj1::print();
`uvm_info(get_type_name(),$psprintf("%0h,%0h,%0h",src,dst,crc),UVM_LOW)
endfunction
//
module tb();
import uvm_pkg::*;
`include "uvm_macros.svh"
initial begin
run_test("my_obj1");
end
endmodule // tb
//
这里,构造了一个最简单的基于UVM方法学的验证测试平台。其中,我们定义了三个可随机的变量:src, dst,crc。
rand int src=4; // 定义 rand int 类型的src 变量,并且赋值初始化为 4
rand int dst=2; // 定义 rand int 类型的src 变量,并且赋值初始化为2
constraint dst_c { // 声明约束 block: dst_c ,
dst inside {[5:9]}; // 约束dst 可能取值:5,6,7,8,9
}
rand bit [3:0] crc = 4'b0111; // 定义 rand bit 类型的src 变量,并且赋值初始化为 4'b0111
constraint crc_c { // 声明约束 block: crc_c ,
crc inside {5,6,7,8}; // 约束dst 可能取值:5,6,7,8
}
症状1:
尽管多次运行,为什么始终得到如下结果,而不是随机可能数值呢?
运行仿真上述代码,得到如下结果:
另外,如下图标注,随机变量 dst,crc 的初始化赋值,和 约束block 约束取值范围,冲突与否,并不影响仿真。可以理解:在不调用 randomize() 函数的时候,不激活约束block constraint 行为。
分析1:
可见:三个随机变量的取值,均为初始化的被赋值。而并不是随机化的可能取值区间。这是因为,在创建my_obj1 类的时候,并没有显式的调用 my_obj1.randomize() 函数,所以不会去做类内部随机变量的随机行为。
//
症状2:
我们修改上面例子,在类的 new 函数总,调用 randomize(), 看看会有什么效果?
`timescale 1ns/1ps
`include "uvm_macros.svh"
import uvm_pkg::*;
class my_obj1 extends uvm_test;
`uvm_component_utils(my_obj1)
rand int src=4;
rand int dst=2;
constraint dst_c {
dst inside {[5:9]};
}
rand bit [3:0] crc = 4'b0111;
constraint crc_c {
crc inside {5,6,7,8};
}
function new(string name = "my_obj1" , uvm_component parent = null );
super.new(name, parent);
this.randomize(); // 新增 randomize 调用
endfunction // new
extern virtual function print ();
virtual task run_phase(uvm_phase phase);
super.run_phase(phase);
this.print();
endtask
endclass //
function my_obj1::print();
`uvm_info(get_type_name(),$psprintf("%0h,%0h,%0h",src,dst,crc),UVM_LOW)
endfunction
//
module tb();
import uvm_pkg::*;
`include "uvm_macros.svh"
initial begin
run_test("my_obj1");
end
endmodule // tb
分析2:
仿真可见,通过显示调用,随机变量均在显式约束、或者隐式,约束的取值范围取值。
另外:在显式调用randomize()的情况下,对于存在块约束的 随机变量crc,其随机化取值,依然是约束块的取值范围,也就是 :显式调用randomize()的情况下,约束块 比 初始化赋值,具有更高的优先级。