SystemVerilog
SystemVerilog是一種在現代積體電路(尤其是超大型積體電路)的设计及验证流程中,由Verilog发展而来的硬體描述、硬件验证统一语言,前一部分基本上是2005年版Verilog的扩展,而后一部分功能验证特性则是一门面向对象程序设计语言。面向对象特性很好地弥补了传统Verilog在芯片验证领域的缺陷,改善了代码可重用性,同时可以让验证工程师在比寄存器传输级更高的抽象级别,以事务而非单个信号作为监测对象,这些都大大提高了验证平台搭建的效率。[1] SystemVerilog已经被采纳为电气电子工程师学会1800-2009标准,并获得了主流电子设计自动化工具供应商的支持。雖無任一個仿真系統能聲稱自己完全支援SystemVerilog语言参考手册(Language Reference Manual, LRM)裡介紹的所有语言结构,要改善测试平台的互操作性相当困难,但推进跨平台兼容性的研究开发工作已在進行中。若干种验证方法学相继出现,以预定义类的形式对测试平台模块进行标准化,如今最新基于SystemVerilog的验证方法学为通用验证方法学。此方法学主要包括开放源代码的类库以及支援可重用测试平台、开发验证IP核的预置格式。许多第三方提供商则开始推出基于SystemVerilog的验证IP核。 发展历史SystemVerilog的历史可以追溯到2002年,当时一个被称为“Superlog”的语言被捐赠给Accellera公司(Verilog的主要支持者)。[2]而Synopsys公司捐赠的OpenVera后来发展成为SystemVerilog中硬件验证语言子集。2005年,SystemVerilog获批成为电气电子工程师学会1800-2005标准。[3]当时Verilog作为电气电子工程师学会1364-2005标准尚独立存在。2009年,SystemVerilog与的Verilog进行了合并,成为了新的电气电子工程师学会1800-2009标准。现在的最新标准是电气电子工程师学会1800-2017标准。[4] 设计特性对于电路设计工程师来说,SystemVerilog中有大部分内容继承自Verilog,但是也提供了一些增强或者改进的特性。下面的章节主要讲述SystemVerilog的这些特性。[5] 新的数据类型逻辑型变量SystemVerilog定义了一种新的逻辑型( logic [31:0] my_var;
在传统的Verilog中,变量主要分为线网型( SystemVerilog增强了寄存器型变量的功能,它可以像Verilog中线网型变量一样由线网(如逻辑门等模块的输出)驱动(这样的线网驱动寄存器的方式在Verilog中是不允许的)。这种增强的变量类型被命名为“逻辑型”,从而避免“寄存器型”在字面上给人带来的误会。在大多数情况中,SystemVerilog中的 多维压缩数组这种结构将Verilog中与寄存器、存储器相关的概念进行了合并和扩展。 在Verilog中,变量名称左边的索引被用来表示二进制变量的位宽,Verilog规定它只能是一维的。而这个数组名称右边的索引用来表示以这种位宽变量组成数组的元素个数,因为数组可以是一维数组、二维数组或者多维数组,因此这个索引可以是任意整数。在SystemVerilog中,如果在变量名称左边指定了由高至低的位宽(如8位信号由 logic [1:0][2:0] my_pack[32];
在上面的例子里,非压缩数组数组 枚举SystemVerilog引入了枚举型变量,它使用一系列有实际字面意义的名称来代表若干变量。如果不进行专门的数据类型转换,一个枚举型变量不能直接赋值给另一个枚举型的变量。过去在Verilog中描述有限状态机常常使用参数(关键字为 typedef enum logic [2:0] {
RED, GREEN, BLUE, CYAN, MAGENTA, YELLOW
} color_t;
color_t my_color = GREEN;
initial $display("The color is %s", my_color.name());
上面的例子使用了typedef来创建了一个新的数据类型名称,从而可以用它来创建一系列枚举数据。枚举类型的数据类型,为位宽为3的逻辑型变量。3位二进制数能够逐一指代六种颜色。使用代码 其他新增的数据类型除了基本的逻辑型变量( 结构体和联合体这两种数据类型和C语言中的结构体和联合体类似。在SystemVerilog中,与这两种数据类型相关的增强特性为压缩属性( typedef struct packed {
bit [10:0] expo;
bit sign;
bit [51:0] mant;
} FP;
FP zero = 64'b0;
条件、选择语句的唯一性和优先性当条件、选择语句的路径分支较为复杂时,设计人员稍不留意就可能造成代码所描述的行为违背设计人员预计的优先级别,或者被判断的表达式同时满足多个分支条件,从而在仿真过程中产生无规律结果。 为此,SystemVerilog增强了条件、选择语句的功能,允许设计人员为这分支流程的执行设置特别的约束。在多级条件、选择语句中使用关键字 过程代码Verilog中的过程代码可以描述时序逻辑电路,也可以描述组合逻辑电路,这一点容易造成概念的混淆,如果代码不严谨,逻辑综合很可能推断出锁存器,从而产生不符合预期的硬件模型。SystemVerilog除了继续支持原来Verilog中的老式过程结构
三种专用的 下面的例子使用 always_comb begin
tmp = b * b - 4 * a * c;
no_root = (tmp < 0);
end
逻辑综合工具会将 always_ff @(posedge clk)
count <= count + 1;
逻辑综合工具还会将 always_latch
if (en) q <= d;
接口对于小型的设计,Verilog设计人员可以使用端口(port)来简洁地描述模块与外部环境的连接情况。不过,在规模较大、抽象层次较多的设计中,处于枢纽地位的模块往往具有大量连线与外界的连通。为此,SystemVerilog引入了接口(interface)的概念,这个概念一方面减少了大量需要声明的端口名称,另一方面,它还方便设计人员将某些相关信号的通道作为一捆相对独立的线网组,这样就使复杂的设计更加简单、明晰。另一个概念是modport,它显示了逻辑连接的方向。例如: interface intf;
logic a;
logic b;
modport in (input a, output b);
modport out (input b, output a);
endinterface
module top;
intf i ();
u_a m1 (.i1(i));
u_b m2 (.i2(i));
endmodule
module u_a (intf.in i1);
endmodule
module u_b (intf.out i2);
endmodule
验证特性随着集成电路集成规模的不断提高,电路的复杂程度也越来越大。在这种情况下,设计验证在整个设计流程中所占用的时间越来越高。SystemVerilog在Verilog基础上增加了许多专门针对验证的特性,使其成为一种杰出的硬件验证语言。下面所提到的验证代码通常是不可综合的,它们的作用主要体现在测试平台的搭建过程中。[5] 新的数据类型SystemVerilog引入了专门的字符串型变量,用关键字 string s1 = "Hello";
string s2 = "world";
string p = ".?!";
string s3 = {s1, ", ", s2, p[2]}; // 字符串的拼接
$display("[%d] %s", s3.len(), s3); // 仿真结果显示为:“[13] Hello, world!”
除了在设计中使用静态数组,SystemVerilog还提供了动态数组、关联数组(associative array)和队列(queues): int cmdline_elements; // # elements for dynamic array
int da[]; // 动态数组
int ai[int]; // 以整数位索引的关联数组
int as[string]; // 以字符串为索引的关联数组
int qa[$]; // 队列
initial begin
cmdline_elements = 16;
da = new[ cmdline_elements ]; // 为da数组分配16个元素
end
动态数组的行为和非压缩数组相似,不过它允许仿真在运行时动态分配元素个数(正如上面例子所示)。压缩数组部分的元素个数(以往称之为“位宽”)必须在编译的时候已知(通过由常数或常数表达式直接确定),而非压缩数组的动态大小则可以在程序运行时,由另一个运行中的程序变量进行初始化,这样就可以在运行中根据所需改变数组的大小。 类SystemVerilog为验证代码的编写提供了面向对象程序设计的模型。 SystemVerilog支持类的单一继承,即不允许一个类继承多个基本类。需要注意的是, 虽然SystemVerilog里提供了与Java中名称相同的“接口”概念,但是二者的实际含义却大有不同,后者的接口能够提供类似多继承的功能。SystemVerilog的类可以自带配置参数,这种类被称为参数化的类,其功能与C++的模板类似,不过SystemVerilog不支持模板特化和函数模板。SystemVerilog的多态性和C++类似,在子类中被覆盖的同名方法在基本类中必须使用关键字 virtual class Memory;
virtual function bit [31:0] read(bit [31:0] addr); endfunction
virtual function void write(bit [31:0] addr, bit [31:0] data); endfunction
endclass
class SRAM #(parameter AWIDTH=10) extends Memory;
bit [31:0] mem [1<<AWIDTH];
virtual function bit [31:0] read(bit [31:0] addr);
return mem[addr];
endfunction
virtual function void write(bit [31:0] addr, bit [31:0] data);
mem[addr] = data;
endfunction
endclass
含约束的随机化可以对定义在类或者其他语句块中的整数型变量进行随机化,从而实现输入激励的随机化,大大降低了验证人员专门定义输入激励的复杂程度。这时使用SystemVerilog构建随机验证平台的重要技术基础。在类数据变量声明前使用 class eth_frame;
rand bit [47:0] dest;
rand bit [47:0] src;
rand bit [15:0] type;
rand byte payload[];
bit [31:0] fcs;
rand bit [31:0] fcs_corrupt;
constraint basic {
payload.size inside {[46:1500]};
}
constraint good_fr {
fcs_corrupt == 0;
}
endclass
在上面这一例子中,数据成员 随机化方法每一个SystemVerilog类都有隐含的三个与随机化有关的方法[註 1],它们是 控制约束条件此外,SystemVerilog还提供了 class eth_frame;
rand bit [47:0] dest;
rand bit [47:0] src;
rand bit [15:0] type;
rand byte payload[];
bit [31:0] fcs;
rand bit corrupted_frame;
constraint basic {
payload.size inside {[46:1500]};
}
constraint one_src_cst {
src == 48'h1f00
}
endclass
.
.
.
eth_frame my_frame;
my_frame.one_src_cst.constraint_mode(0); //关闭one_src_cst约束,之后该变量的随机化将不再受该约束限制
my_frame.type.random_mode(0); // 关闭type变量的约束,之后的随机化将不会给该变量赋予随机数值
my_frame.randomize();
断言与其他属性规约语言类似,SystemVerilog具有断言这一概念。在整个芯片验证流程中,断言检查器会自动检查定义的属性是否得到满足,如果违背,则会给出警告。SystemVerilog断言由序列( sequence S1;
@(posedge clk) req ##1 gnt;
endsequence
这一简单序列的意思是,信号 property req_gnt;
@(posedge clk) req |=> gnt;
endproperty
assert_req_gnt: assert property (req_gnt) else $error("req not followed by gnt.");
上面这个例子显示了蕴含(implication)操作符 功能覆盖在硬件验证中,功能覆盖是指验证过程中对人工定义信号事件的数据采样和收集过程。功能覆盖率在某种程度上反映了被测设计在所给输入激励下,其内部功能正确与否被检测到的百分比。功能覆盖率越高,一般代表测试越完备。注意功能覆盖率和代码覆盖率不同,后者只是测量被测设计的所有代码有多少在仿真过程中被执行过。功能覆盖的目的是确保设计中的所有边界情况都能够被经历。 SystemVerilog覆盖组(coverage group)内可以定义若干个仓(bins)来储存相关变量取值在其范围内的次数。交叉覆盖(Cross-coverage)则可以进一步获取多个变量分别在某一范围内统计数据。通过使用覆盖组的 For example: class eth_frame;
// Definitions as above
covergroup cov;
coverpoint dest {
bins bcast[1] = {48'hFFFFFFFFFFFF};
bins ucast[1] = default;
}
coverpoint type {
bins length[16] = { [0:1535] };
bins typed[16] = { [1536:32767] };
bins other[1] = default;
}
psize: coverpoint payload.size {
bins size[] = { 46, [47:63], 64, [65:511], [512:1023], [1024:1499], 1500 };
}
sz_x_t: cross type, psize;
endgroup
endclass
在这一例子中,验证工程师重点关注广播和单播帧的分布以及负载大小。 同步化一个复杂的测试平台往往是包含多个可重用验证模块的环境,这些模块之间需要互相通信。Verilog的事件( 其他与传统Verilog类似概念的比较除了前面提到的特性,SystemVerilog还在以下方面对传统的Verilog进行了增强:[1]
注释
参考文献引用
来源
外部链接IEEE 标准文献
教程标准开发
语言延伸
参见 |