这篇文章带来ECE111第十二节课的Slides以及自己的一些补充。
该课程的网站如下:
https://link.zhihu.com/?target=http%3A//cwcserv.ucsd.edu/~billlin/classes/ECE111/index.php
这门课到这里就结束了,不知道这一系列文章有没有给大家提供一些帮助。除了老师上课讲的Slides,最后我再补充一下SHA256 Project的讲解,就正式完结撒花了。希望能对大家入行数字IC做一点微小的贡献。后面我可能会讲解EE290这门课,此外带来一些论文精读,主要集中在特定算法的高效硬件实现(微架构领域),对于IP开发工作而言,这是非常重要的。这也是区别RTL民工和优秀的IC设计工程师重要的一方面。
回归正题,开始讲解最后一节课的Slides。
在实际的验证工作中,基本都是基于UVM的验证方法学。基于单纯的Testbench而言的验证方法,在公司级别的开发中已经没有了,但是对于个人做小项目,掌握基本的Testbench的编写还是非常重要的。
什么是Testbench?它也是一个模块,但是它是用于测试别的模块(你的设计)的模块。Testbench一般是不可综合的,写法相对比较简单。其实本质上就是提供一系列的测试向量,检查输出是否符合预期。
- 提供输入,检查输出是否符合预期
延迟,一般是用于模拟更真实的情况。让输入到输出之间存在一个时间差。
我们可以看到,在assign的后面直接加上#1。会导致输入和输出之间存在时间差,本质是延迟1个时间单位,再执行assign这条语句。又由于是阻塞赋值,因此如果有数据依赖关系的话,需要进一步的等待。并且需要注意,两条assign语句之间,是并行执行的!
- 对于{ab,bb,cb}这三个信号而言,在t=0时刻感知到会发生变化,因此会阻塞一个时钟周期,在t=1时刻的时候,获得相应的赋值(此时对应的是t=1时刻的a,b,c取反)
- 对于n2和n3而言,在t=0时刻感知到会发生变化,因此阻塞两个时钟周期,t=2的时候获得相应的赋值。(t=1的时候bb和cb发生变化),这两个assign语句是察觉不到的,因为已经被#2阻塞住了。
- 对于n1而言,t=1时刻感知到会发生变化,因此阻塞三个时钟周期,t=3的时候获得相应的赋值
- 对于y而言,t=3时刻感知到会发生变化(t=2的时候n2,n3会改变,但是不影响y的值,因此不会进入这个assign语句),所以阻塞4个时钟周期,t=7的时候发生变化。符合我们的预期
还有一点需要注意的是,阻塞几个周期以后进行赋值,赋的是现在的值而不是几个周期之前的值!下面的波形对应的语句为assign #4 y=a|b|c。可以看到仿真器在察觉到到a从0变成1,此时y需要发生变化,但是四个周期以后,a|b|c为0。所以y一直为0,而不是“当时算出的1”。
这些其实是一些比较偏的知识点,大家能理解最好,不能理解的话尽量避免这么写即可。(关于这部分如果有不懂的可以跟我进行沟通,我也是经过大量的仿真才理解#的机制),大家还可以参考我之前写的文章:
最简单的tb如上所示,就是写一些测试向量,然后通过肉眼去看波形。这些测试向量如果有严格的先后顺序,一般是放在initial语句里面,通过时间延迟delay分隔开。
同时我们还可以在tb里面增加检查机制,这样可以方便比对,而不用看波形。
测试向量包括输入和期待的输出。一般测试步骤如下:
- 产生时钟信号
- 定义相关的数组
- 指定输入,预期的输出
- 比较实际输出和预期的输出是否一致
其实这些测试方法是非常直观的。相信大家也很容易理解