一种自动编写UVM testbench的方法

本文转自:http://www.eetop.cn/blog/html/28/1561828-437619.html

SystemVerilog UVM 是一个以SystemVerilog类库为主体的验证平台开发框架,验证工程师可以利用其可重用组件构建具有标准化层次结构和接口的功能验证环境。UVM方法的强大是毋庸置疑的,但同时UVM却也不是那么容易掌握的。对于没有UVM经验的工程师,直接使用UVM方法还是比较困难的。

但是幸运的是,你可以在网上找到一些UVM模板和UVM生成器。它们都是一些基于UVM库的UVM框架。使用这些模板或者生成器的好处在于,在一开始你并不需要知道关于UVM的所有细节,当然,在此之前还是需要懂得SystemVerilog知识和UVM基本验证环境。所以,本文面向的是没有UVM验证经验的工程师。着重介绍了一个简单的模板和生成器,经过一些简单的修改,只需要在一个工作日内,一个新的基于UVM的testbench就建立并且能够正常运行起来了。

下图是一个理想的生成器

 

模板当然不是完全自动化的,根据你的特定需求,你需要在其中描述定义你的transaction、总线、driver和monitor的连接等。你必须要设计你的测试用例的产生方法,比如怎样测试多个接口等,可能还需要编写“golden model”。这些工作都会要求你在生成器所产生的样板文件中修改完成。虽然不需要懂UVM的细节,但是SystemVerilog还是必不可少。

基本的UVM Testbench

最基本的UVM testbench包含有 DUT、用于接口的agent、把所有agents收集到一起的environment和一个顶层的test。DUT和基于类的testbench间是使用virtual interface连接的。下图是一个有三个接口的简单DUT模型(其中一个并没有连接)。下面的UVM模板也是基于这个DUT模型展开的。

 

模板

模板并不是唯一的,不同的模板有不同的特性,没有正确的模板,只有合适的模板。模板系统本身是可独立运行的,即该模板可以被独立编译、仿真。对于一个可编译可仿真的系统,创建的模板bug较少。这篇文章介绍的模板简单普通,包含了共计500行代码的20个文件。生成器的脚本如下所示。

 

上面使用了tar命令为agent创建一个层级,然后处理新层级里的所有文件内容,使用sed把一般的模板名转换为特定的名字(即体现在我们自己具体设计中的名字),例如下面的这个sequencer模板

 

会被转化为下面的sequencer类

 

Transaction

Transaction用于描述你要与DUT之间进行怎样的交互联系。一个工程了里会有很多Transaction,诸如读写事务、寄存器事务和总线事务等。下面是一个包含有地址和数据的读写事务。

 

总线

各种信号都要经过总线,这里主要讲的是总线的接口。所有生成的agent都会连接virtual interface,用于采集信号。使用如下方式定义

 

除了上面的这种接口,这种模板还有一种接口,就是带有驱动和监视总线功能的BFM(Bus Function Model总线功能模型)。定义方式如下:

 

Agent

Agent是包含了driver, monitor 和sequencer的容器,其目的是连接这些组件。把所有的组件放在一起,使用一个接口驱动和监视总线事务。下图是一个ABC agent的结构。

 

Driver

Driver只负责驱动transaction,transaction是在sequence中产生的,所以driver 要向sequence提出请求,并通过总线发送请求。每一个driver 都有特定的协议。下面是driver的模板代码。

 

Monitor 

Monitor 用于监视总线上的活动,每当识别出一个事务,就会实例化一个transaction对象,并且通过分析端口送出,分析端口一般连接了一个scoreboard 。scoreboard 会查看处理transaction的正确性或者将其保存下来。下面是monitor 的模板代码。

 

 Sequence

UVM sequence 是一块简单的软件代码,用于生成供driver 执行的transaction,例如下图中的名为boby的task产生的transaction,先调用了start_item()语句(旨在获取在driver里运行的权限,就像调用wait_for_grant()一样),然后随机化名为tx的transaction,最后执行finish_item语句(实际用于通知driver开始驱动transaction)。所以基本的步骤应该是包括:创建、等待许可、随机化、执行。

 

再比如下面的sequence代码,用于在两个地址间产生10000个读写transaction。

 

另外为了创建不同的地址,我们还要创建一个新的sequence,我们可以直接从上面的sequence类派生,加上新的约束(这里的约束是保证地址都是偶数),就得到了新的sequence类。

 

Environment

Environment也是一个容器,有点像agent,不过一般environment是包含了agent的。environment用于创建agent,以及设置连接到DUT的virtual interface。下面是一个环境的配置。

 

Test

Test即测试用例。Test本身也是一种组件,我们是在测试用例代码里实例化的environment,并且在测试用例中开启sequence。不同的测试用例会开启不同的squence,例如在一个有三个接口的DUT中,test就会启动3种不同的sequence。在不同的接口上,测试DUT不同的行为。在一个test上,我们只需要实例化好environment并开启sequence,test就可以自行开启测试仿真。

 

 其余的部分

在一个UVM testbench中,还可能有许多其他组件,例如“analysis components”。analysis components就是诸如predictor、scoreboard、checkers 之类的组件。每一个对应的组件就有相应特定的工作。我们这里所用的简单模板,只用到了简单的scoreboard。

DUT必须要连接到testbench上。top模块上实例化了接口和DUT封装。DUT封装实例化了DUT和连接到DUT管脚上的SystemVerilog接口信号。Test top中实例化BFM,并开启UVM test,具体可见以下代码。

下面这个简单的Top模块实例化了总线(信号都要连接到DUT上)和DUT封装,并且设置了时钟信号。

 

DUT封装把接口映射到管脚上

 

Test_top的功能比较简单,在这个模块实例化了BFM interface。driver 和monitor会使用BFM interface发送或接收总线数据。test_top模块把BFM interface储存在全局数据库中,可以根据名字进行搜索调用。最后test top模块调用run_test()开始UVM test。

 

结论:

使用UVM方法会使验证效率会得到巨大提升。但是短时间全面学习UVM是比较费劲的。寻求其他外界资源的帮助费时费钱,使用模板系统就简单便捷多了。但是模板也不是万能的,你至少还是要熟悉SystemVerilog代码,能根据特殊的协议和DUT的功能自己修改编写一些代码。

好的模板要短而精,产生器要简单易懂,我们这个模板就是,只用了共计约500行代码的20个文件,产生器用了不到50行代码。如果你在不精通UVM的情况下需要完成验证工作,就从类似的模板开始吧!

©️2020 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页