怎么做单元仿真

本文转载自: FPGA的现今未微信公众号

注:本文由作者授权转发,如需转载请联系作者本人

无论是搞FPGA还是ASIC的工程师,都知道代码完成了要搞单元仿真(UT),但是怎么搞?每个人,每个公司都有不同的想法或者规定。这里就笔者做过的UT做一个简单的总结,当然里面的方法并不一定是非常的好,仅供参考。

为什么需要UT
我们的RTL代码完成以后,为了保证代码的正确性,往往需要对代码做一个单元仿真(当然也有很多不做,直接上板测试,这里不太推荐),因为大家都知道,UT是解决问题最简单,最经济的方式。提前发现问题的代价也是最小的。

谁来做UT
通用的方案有2种,一种就是配对编码,即A完成编码的模块由B来做UT,B完成编码的模块由A来做UT;第二种就是个人写的模块自己完成UT。这2种方案各有利弊。

什么时候做UT
这个问题,也有2个答案,一个是完成一个模块,就UT一个模块。另一个是编码完成所有的模块后,再开始UT。笔者之类推荐第二种方案。原因之一是方案制定后,代码的编写一气呵成从效率和质量来看是最优的;原因之二就是代码全部编写完成后再UT的话,可以并行完成综合告警清零等他其他重要的工作,提升效率。

怎么做UT
重点来了,到底如何做UT呢?有人直接拿ST的平台当成UT平台来做UT,也有人做一个非常简单的“UT平台”,简单的发几个激励即可。那一个合适的UT平台有哪些标准?

1、简单
UT平台相比ST平台要简单、搭建方便,下图所示是一个UT平台的架构图。整个平台由testcase和testbench2个大的部分组成。testcase描述具体的用例,testbench描述时序接口以及高层次抽象到底层时序接口的转换,都是用task或者function来完成。当然还可以引入更高级的语法应用,比如类等等。这种平台搭建的重点就是task的描述,在task里不断的调用task或者function,来实现高层抽象到底层时序的转换。

2、固定
一个好的平台,要能发送任一固定的激励,这个是最基本的。比如发送72byte长度的报文,比如能遍历某种私有格式头部所有字段可能的取值。尤其是一些边界用例,也需要准确地打点。

3、随机
仅仅有固定的激励是远远不够的,还有很多组合场景往往是我们想不到的,这个时候就需要随机测试。比如一个100M的网口模块,如下图所示,在对它做UT随机测试的时候,通过远端还回的方式,在激励测随机报文的长度,帧间隔长度等。

随机和固定测试是一对兄弟,缺一不可,只有固定用例,那就会出现测试不全,只有随机用例,最容易出问题的边界场景往往难以覆盖,甚至一些基本的用例都难以覆盖。

4、连续
所有的单个用例都测试完成后,还有一个非常重要的事情,就是需要把所有的用例连续执行。这里的连续执行不是用脚本把每个用例都执行一次,而是要在一次执行中,把所有的用例都运行,或者说所有的用例都要出现在一个波形中。作者通过这种方式经常会发现前面用例有一些依赖关系的bug,否则这类问题只能在上板测试的时候发现。

task的设计
一个简答的task,我们用verilog就可以完成,但是要满足上面的4个要求,必须把System Verilog的一些常见用法掌握好。
1、文件的操作,文件的创建、打开、读写等等;
2、数组的使用;
3、队列的使用;

掌握上述三个语法的应用后,基本可以满足UT所有的操作,即所有task的设计,都可以围绕这3个语法进行。具体的语法应用可以参考官方语法说明或者《SystemVerilog验证测试平台编写指南》这本书。

UT要做到什么程度
我们知道,随着UT用例的增加,总能发现一些问题,但是发现问题的数量会越来越少,难度也会越来越大。UT到底要做到什么程度才算结束。主要标准就2个。
1、所有的功能点都已经覆盖,这个标准比较主观,最好的检验方式就是通过团队评审所有的测试用例,看看需求的功能点是否都已经覆盖,即用团队的力量来弥补个人主观的缺陷。
2、覆盖率分析,完成所有代码的覆盖率分析,能覆盖的必须覆盖,不能覆盖的要说明为什么不能覆盖,尤其是不能覆盖的代码要做好团队的评审和代码检视。
当上述2个标准得到团队的认可后,那么UT可以暂时结束,进入下一个阶段,当团队的开发工具没有能力支持覆盖率分析的时候,做好第一个标准就尤其重要了。

在UT方面你有什么好的经验?欢迎补充交流。