基于SystemVerilog语言的设计验证技术

时间:2022-09-01 03:29:30

基于SystemVerilog语言的设计验证技术

摘 要:随着集成电路设计规模的不断增大,设计验证工作越来越困难。介绍IEEE新标准SystemVerilog语言中用于验证的随机约束、功能覆盖率、断言技术和利用面向对象思想构建验证平台的一般方法。这些方法能极大提高芯片设计的效率,降低芯片设计的风险,减轻测试工程师的负担。

关键词:SystemVerilog;随机约束;功能覆盖率;断言;面向对象

中图分类号:TN492 文献标识码:B

文章编号:1004-373X(2008)06-008-04

Verification Technology Based on SystemVerilog Language

YAN Mo ZHANG Yuan2

(1.College of Mechanical and Electrical Engineering,Xi′an University of Architecture & Technology,Xi′an,710055,China;

[JZ]2.Graduate Department,Chang′an University,Xi′an,710064,China)

Abstract:With the increasing of IC design scale,the verification becomes more and more difficult.This paper presents an IEEE new standard SystemVerilog language with constrained- random,assertion,functional coverage technologies in verification,and introduces the method of using Object Oriented Programming (OOP) thinking to build verification platform.These technologies promote the efficiency of chip design extremely,reduce the chip design risks and the test engineers′ burdens.

Keywords:SystemVerilog;constrained-random;functional coverage;assertion;OOP

1 引 言

近年来,随着半导体技术的不断发展,集成电路制造工艺技术越来越先进,芯片设计的规模变得越来越大,芯片验证工作成了制约芯片设计水平的关键性因素。对于一款复杂的SoC芯片,设计验证将占到整个设计工作量的70%以上。然而验证技术相对于设计,其发展一直比较缓慢,并且出现相对停滞的现象。这就是所谓的“验证危机”。为了解决这个困境,EDA厂商相继推出一些新的验证手段和概念:随机约束(constrained-random)、断言(assertion)、功能覆盖率(functional coverage)等。所有这些,都是原先使用Verilog语言进行功能验证所不具备的。

毫无疑问,工具和语言是制约验证再次提升的症结所在。IEEE新的标准语言SystemVerilog结合了来自Verilog,VHDL,C++的概念,还有验证平台语言和断言语言,也就是说,他将硬件描述语言(HDL)同现代的高级验证语言(HVL)结合起来。

因此,SystemVerilog拥有验证工程师所需要的全部结构,这其中包括:随机约束(constrained-random)、功能覆盖率(functional coverage)、断言(assertion)、面向对象(OOP)等新技术。

2 SystemVerilog语言中的验证技术

2.1 随机约束(constrained-random)技术

(1) 随机约束的概念

随机约束技术是一种随机的产生测试激励的新技术。相比这种新的随机激励产生技术,往往更加熟悉定向测试激励的产生。传统的定向测试手段是:根据设计规范,工程师通过手工编写测试向量来验证设计规范中的某一项功能。但是,随着芯片设计规模和复杂程度的增加,采用定向测试可能需要成百上千乃至上万的测试向量,验证空间成“几何”增长。这无疑需要大量的人力,同时随着代码行数的增多又会导致出错概率的增加,从而增加验证的难度。另一方面,定向测试只是针对已知测试空间,无法证明设计中不存在潜在的错误。

随机约束技术的引入是解决这一难题的有效手段。利用计算机随机生成函数,设计者可以随机产生任意不同的测试向量,从而使验证程序的代码大幅度减少,提高验证工作的效率。但是,仅通过随机函数产生测试向量还不能够有效地验证设计规范的要求,这项技术最重要的特点是能够约束测试向量的生成。通过对要生成的测试向量施加约束,可以人为地控制向量的生成。工程师可以根据规范中所定义的功能或者根据所关心的边角情况,人为地产生各种测试向量来验证设计的正确性。通过对随机测试向量施加一定的约束,测试向量最终会变成定向测试激励。由此,可以认为,定向测试激励仅是随机约束激励的一个特例,而随机约束激励能够对更广泛的设计空间进行验证。

(2) 随机约束激励的编写方法

为了能够产生随机测试激励,首先需要将激励信号声明为随机变量。以一个数据包的产生为例,如下所示:

rand integer pkt_len;[JY]// 随机产生数据包长度

rand bit [7:0] payload [];[JY]// 随机产生数据包载荷

constraint pkt_c {[JY]// 约束关系

pkt_len >= 3;

pkt_len

payload.size() == pkt_len;

}

在上面这段代码中可以看到,数据包的长度pkt_len和载荷数据payload都被声明成一个随机变量。他们的产生依赖于约束条件。从约束条件中可以看到,数据包的长度pkt_len在3~5之间,载荷payload的长度则由pkt_len决定。

如果要将数据包载荷中的数据取值限定在一定的范围内,则可以使用如下语句进行约束:

foreach (payload[i]) payload[i] inside {[0:16],[64:128]};

这条语句表明,将来生成的载荷数据只能在0~16和64~128之间进行取值。

要想控制数据生成的概率,还可以使用如下语句:

foreach (payload[i]) payload[i] dist {[0:16]:=80,[64:128]:=20};

上面这条语句对数据的取值概率进行了约束。payload将在0~16和64~128范围内按照80~20的概率进行取值。

如果继续修改约束条件,例如对数据包使用pkt_len==5;进行约束;数据载荷使用foreach (payload[i]) payload[i] == i;进行约束。这样,可以清楚地知道所生成的payload是按照{1,2,3,4,5}进行取值。这时,随机约束产生的测试激励实际上已经转化为定向测试激励。

在定义了上面的这些约束条件后,应当把他们放在一个自定义的类(Class)中,例如:driver类。这样做的好处是,设计者可以很容易的构建验证平台。接着,可以按照下面的方法产生激励:

driver drv[JY]// 声明为driver类

drv = new;[JY]// 产生driver类对象

if (drv.randomize()==1) begin

for (i = 1;i

$display("@%0d: paypload[%0d]=%0d",time,i,drv.payload[i]);

#20ns;

end

end else

$display("Randomization failed");

这段代码中使用drv.randomize()对driver类对象drv进行随机化,如果成功,就显示出payload数据;否则显示随机化过程失败。

2.2使用功能覆盖率(functional coverage)

功能覆盖率往往是同随机约束一起使用的,当设计者使用了随机约束产生激励时,怎么能够知道设计是否已经达到目标?无论是否使用随机激励或定向激励,设计者都能够通过使用覆盖率来精确估计验证过程。

使用功能覆盖率的一般过程是这样,首先,仿真工具会根据用户定义的覆盖率组将覆盖率数据收集到一个或多个数据库中。测试开始时,覆盖率会随着测试的时间而不断提升,到达一定时候,覆盖率不再增加。这时,如果覆盖率还没有达到100%,设计者可以采用更多的种子生成激励进行测试或通过修改约束的方法生成新的激励,直到整个设计的功能覆盖率达到100%。这时可以认为验证结束。功能覆盖率的使用方法如下:

covergroup memory @ (posedge en);

address : coverpoint addr {

bins low= {0,127};

bins high= {128,255};

}

endgroup

上面这段代码中使用covergroup关键字定义了一个功能覆盖率组并且使用关键字converpoint定义功能覆盖率点。他的意义是:每当en信号上升沿来的时候,仿真工具将采样addr信号,将收集得到的值分别放入low和high两个数据库文件中。当addr小于128时,他的值将被收集到low这个数据库文件中;当addr大于127时,他将被收集到high这个数据库文件中。low和high是采用bins关键字并由用户自己定义的用来收集覆盖点addr数据的二进制文件。

仿真工具会根据收集到的这些数据和用户预先定义好的这些二进制类型的数据库文件进行命中比对,从而计算出相应的功能覆盖率。

2.3断言(assertion)技术

断言技术是SystemVerilog语言为进行芯片验证而增加的新技术。一条断言就指明系统的一个行为,他主要用来验证设计行为。SystemVerilog包含2种类型的断言:即时(immediate)断言和并发(concurrent)断言。

(1) 即时(immediate)断言

即时断言主要跟随在仿真事件之后,同仿真过程一起使用,他的执行类似过程控制块中的语句。他主要是在语句执行的过程中对一个表达式进行判断,也可以使用if语句进行同样的解释。如果表达式的计算结果为:X,Z,0,那么他就被解释成假并且被断言失败。反之,表达式被解释为真并且断言通过。即时断言可以使用下面的语句进行:

assert (req1 || req2) display("assert passed");

else error("assert failed at time %0t",time);

这条语句对表达式req1||req2进行断言,当表达式成立时,断言通过;否则,断言失败。

(2) 并发(concurrent)断言

并发断言基于时钟语义并且使用采样后的变量值,他就像带有时钟的always块。并发断言描述一种跨越时间的行为。与即时断言不同的是,他的计算模型是基于时钟的,断言仅在时钟标记发生时进行计算。一个并发断言的构成一般由以下几个部分组成:布尔(Boolean)表达式、序列(Sequences)、属性(Property)、属性断言指令。

在并发断言中,序列表达式表示的是时间序列上的一组事件。为了精确的描述时序行为,SystemVerilog定义了基本的序列运算符:拼接(concatenation)、重复(repetition)、跳转重复(goto repetition)、非连续重复(non-consecutive repetition)、贯穿(throughout)、蕴涵within)、交集(intersect)、与(and)、或(or)[2]。其意义如下:

拼接运算 如a##2 b表示在当前时钟标记时刻a事件为“真”,在随后2个时钟标记时刻b事件应当为“真”。a##[0:3] b表示b跟随在a之后的0~3个时钟标记期间。

重复运算 如a##1 b[*3]##1 c表示a##1 b##1 b##1 b##1 c,b被重复了3次。如果使用b[*2:3],则表示b被重复2~3次。

跳转重复运算 如a##1 b[->2:10]##1 c表示在第1个时钟标记a为“真”,在最后一个时钟标记c为“真”,在倒数第2个时钟标记b为“真”,在a之后c之前包含倒数第2个b之间b为“真”应当为2~10次。这个表达式等价于:a##1 ((!b[*0:]##1 b)[*2:10])##1 c。这里表示时钟标记数不固定。

非连续重复运算 如a##1 b[=2:10]##1 c等价于:a##1((!b[*0:]##1 b)[*2:10])##1 !b[*0:]##1 c。

贯穿运算 如a throughout (b[->1])表示a必须一直保持有效直到b也有效。

蕴涵运算 如a within b表示从b开始到结束期间,若a至少发生1次,则该表达式匹配。

交集运算 如a intersect b表示a与b从开始到结束都应当匹配。

与运算 如a and b表示a和b在开始时应当匹配,结束时可以不同。

或运算 如a or b表示a和b中只要有一个匹配,表达式就匹配。

序列的定义可以使用sequence和endsequence进行定义,如:

sequence s1;

a and b;

endsequence

属性是由基本的序列组成,描述了一个复杂的硬件时序行为。假设已经定义了req1和req2序列,属性可以描述如下:

property a1;

@ (posedge clk)

disable iff (reset)

req1 |-> req2;

endproperty

上面代码表示定义了一个断言属性a1,每次在时钟上升沿的时候断言进行计算。|->符号表示req1匹配时就有req2匹配。disable iff (reset)语句表明断言在reset有效时不进行计算,即不在复位时刻进行断言。

当定义完属性后,就可以用断言指令,对属性进行断言,例如:

a1_assert : assert property (a1);

3验证平台的建立与面向对象思想

要能够有效地使用上述的验证技术,验证工程师需要搭建合理的验证环境。一般的验证平台结构如图1所示:

从图1中,可以看出整个验证平台从底至上被分成信号层、命令层、功能层、场景层以及测试层。这其中包括了:生成器、、驱动器、监视器、检查器、记分板以及断言。

信号层为DUT(被测设计)提供信号级的连接。命令层在信号层之上,一般包括驱动器(Driver)、监视器(Monitor)和断言(Assertion)。驱动器主要用来向DUT提供激励数据。监视器用来报告观测到的时序和数据。功能层位于命令层之上,是高层次操作的抽象。这一层主要包括(Agent)、检查器(Checker)和记分板(Scoreboard)。的作用是接收上层传来的高层事务,如DMA的读写等,并且将这些高层事务转换成单独的命令向驱动器提供。驱动器在接收到发出的命令后,就会生成相应的激励数据。检查器根据监视器报告的时序和数据进行相应的判断。SystemVerilog语言在验证中使用记分板技术实现自检查结构。记分板的作用就是根据层送来的命令和检查器所报告的命令进行比较,用来确定是否某一高层事务被遗漏,同时进行记录。场景(Scenario)层在功能层之上,主要是用来生成高层事务。最上层是测试层,他被用来配置不同的测试案例,定义不同的约束条件。在整个测试工程中,功能覆盖率由仿真工具自动生成,测试者将根据功能覆盖率来调整测试平台,修改测试案例直到覆盖率达到100%,便可以认为测试过程结束。

为了使验证平台的分层结构更容易实现,各验证模块之间更容易地进行数据通信,SystemVerilog引入了面向对象(OOP)的思想建立验证平台。一般情况下,将驱动器、监视器、检查器、记分板、事务生成器使用关键字class定义为类。一旦定义了一个类之后,就可以将与之相关的数据和操作统一放在这个类里面。从而使整个验证平台的结构变得清晰并且更容易维护。

4结语

随机约束、功能覆盖、断言已经成为现代芯片验证中的关键技术。这些技术能够大幅度地提高工作效率,降低芯片设计风险,节约成本。在使用这些技术进行芯片验证工作时,应当合理地运用面向对象的思想按照前面提到的分层结构建立相应的验证平台。这样做不仅可以加快验证环境的建立、有效地使用验证技术而且还可以降低验证平台的维护成本、增强程序可读性。

参考文献

[1]刘杰,徐伟俊,夏宇闻,等.设计验证中的随机约束\[J\].中国集成电路,2006(11):28-31,44.

[2]Janick Bergeron,Eduard Cerny,et al.Andrew Nightingale.SystemVerilog验证方法学\[M\].夏宇闻,杨雷,陈先勇,等,译.北京:北京航空航天大学出版社,2007.

[3]Rindert Schutten.基于ESL并采用SystemC和SystemVerilog的设计流程\[J\].电子设计技术,2006(4):142-149.

[4]Chris Spear.SystemVerilog for Verification\[M\].Springer,2006.

[5]SystemVerilog 3.1a Language Reference Manual.Accellera′s Extensions to Verilog.Accellera,Napa,California,2004.

[6]李暾,郭阳,李思昆.基于断言的模拟矢量自动生成方法\[J\].软件学报,2004,15(10):1 441-1 450.

作者简介 闫 沫 男,1980年出生,陕西西安人,西安建筑科技大学机电工程学院,硕士研究生,助教。主要研究方向为集成电路设计。

上一篇:嵌入式Linux通用GPS接口的设计与实现 下一篇:300MW机组计量给煤机控制系统的PID控制