在IC设计以及FPGA应用为基础的设计中,验证工作是非常重要的一个环节,一般情况下设计工程师都要参与部分验证工作,好的工程师都会在提供设计代码的基础上提供好的文档,说明设计思路和过程,同时也提供好的仿真程序以验证设计代码的正确性。但是不是说只要懂得部分验证,能提供仿真程序就完成验证工作呢?答案是否定的,因为有如下因素决定设计者提供的仿真和验证代码不能替代标准系统验证。
(1)确定的顺序性
设计提供的仿真代码往往从设计者的角度设计仿真流程,具有明确的顺序性。按照预定的顺序,仿真输出结果往往是正确的,但如果顺序改变后,由于没有系统验证的适应性,往往验证不全。
(2)局限性
设计者提供的仿真代码没有从系统的角度考虑问题,因此仿真代码具有较强局限性。我们知道,一般在设计一种算法时,往往经过了大量简化,抓住了主要问题,同时忽略大量的次要问题,特别是一个从实际场景抽象出来的问题,首先进行分析,简化(抓住主要问题,忽略次要问题),之后进行数学建模并提供算法,最后设计出RTL代码。虽然RTL代码具有代表性,但此时的RTL代码已经相对于实际场景相去甚远。而设计者往往只关心算法与RTL之间的验证,而系统的、用户层面等全面的验证,设计工程师往往并不具备全面的知识,因此不可能提供系统层次或用户角度等全方位的验证。
(3)没有评价系统
从设计者角度看,只要按照一定顺序完成验证就算完成验证工作,对于系统验证工作没有全面的评价,也就说系统验证的覆盖性(coverage)、良好性等验证效果没要较好的评价。术业有专攻,这些工作都交给设计者去做不仅不经济,也几乎是不可能。
(4)非标准性
不同设计者的验证代码风格不同、结构不同,随意性很强,不仅可读性较差,不易维护。验证工作是一个非常严格的学科,因此结构化,标准化的验证流程非常重要。
1. 标准验证方法
虽然设计者提供的验证程序可以一定范围内验证设计代码的可靠性,但众多设计者的设计风格迥异,因此结构化相对较差,大多数情况下代码的重用性较差。当到系统验证阶段时,这些代码几乎不能重用。鉴于以上问题,系统化、标准化的、全面化的验证显得越来越重要,因此对于良好的验证应具有如下需求或特点:
- 开放性,
- 通用性,
- 结构化验证代码,
- 验证随机性,
- 验证约束性,
- 覆盖性,
- 自动性,
- 完善的评价系统。
对于通用的验证方法,目前主要流行有OVM和UVM两种。OVM是Open Verification Methodology(开放性验证方法)的缩写,UVM是Universal Verification Methodology(通用验证方法)的缩写,这两种方法目前都很流行,它们都是基于面向对象的验证过程,底层的验证语言是System Verilog, 因此如果相做好验证工作,除了要理解系统验证方法外,System Verilog 也是基础中的基础。在学习系统验证前,验证平台(test bench)的编写以及仿真验证工具的熟练使用,如modelsim, Questa,Xsim等工具的使用也是必须掌握的。由于OVM的基本机构与UVM基本相同,而且UVM具有更多的特性,应用也更广泛,因此后续文中主要以UVM作为主要介绍对象。下面就OVM和UVM的验证方法的结构做简单介绍。
2. OVM/UVM的基本结构
UVM是通用验证方法(Universal Verification Mothodology)的代表,是面向对象的验证方法。UVM具有如下特性,
-
OVM/UVM是公用的仿真平台
UVM是公用的仿真平台(Common Testbench), 或者说UVM是公用框架仿真平台(Common Skeleton Testbench)。也就是说不同的验证系统,采用UVM系统验证,其验证框架都是相同的。这就带来了代码重用性、调试的便利性以及平台设计的快速性等许多优良的特点。UVM仿真平台如图1所示。
图1 UVM仿真平台
从图1的结构可以看出,UVM包含如下几个模块:
-
- 被测设备DUT (Device under test):可以认为是一台被测设备,在ASIC或VLSI的测试中一般认为是被测设设计模块或系统 。
- 接口(Interface):一般DUT含有输入、输出接口,测试程序也应有相应的接口,Interface主要用来对接被测模块和测试程序之间的接口,具有较强的适应性。
- 引擎(agent) : 引擎包含主要测试程序和模块,以及需要的类(class)和库(libary)等组成,主要模块由3部分组成,分别为监视(monitor)模块,序列模块(sequencer)以及驱动模块(driver)。
- 序列(Sequencer)模块:产生测试序列,
- 驱动(Driver)模块: 将序列模块产生的测试序列加以驱动,通过接口(Interface)与被测模块进行连接,
- 监视(monitor)模块:主要监视DUT的输出以及感兴趣的内部变量和状态。
引擎的序列(sequence)经过驱动(Driver)后可能在一个或多个时钟(clock)的驱动下运行,也可能受复位(reset)信号的控制,监视器(monitor)主要在时钟的控制下捕获DUT的输出或状态,将感兴趣的问题送得分板(Scoreboard)。
-
- 得分板(Scoreboard):得分板接受来自监视器的信号,并最终对被测设备(DUT)进行评价,并分类给出相应的分数值。
3. OVM/UVM 类
上面从整体架构上探讨了UVM的基本结构,而结构中的各个组成部分又都是由类构成。下面从类的角度探讨UVM的组成。UVM有两个主要的类(class),分别是UVM组件类(UVM component classes)和UVM 数据类(UVM Data class)。
- 基本的组件类(Essential component classes):基本组件类由以下主要类组成,这些类之间有特定的层次关系。
- 测试类(test class)
- 环境类(environment class)
- 引擎类(agent class)
- 监视类(monitor class)
- 序列器类(Sequencer class)
- 驱动类(Driver class)
- 测试类(test class)
- 基本数据类(Essential Data classes)
- 交易类(transaction class–sequence_item)
- 序列类 (sequence class)
- 自定义类
在验证时都要创建特定的类用于测试DUT, 但多数类都是从上面基本类扩展得到的。可以看出OVM/UVM充分利用类的内聚与封装的特点,同时又充分利用类的继承性,使设计及简化又具有较好的结构化的特点。