这门课到这里就结束了,不知道这一系列文章有没有给大家提供一些帮助。除了老师上课讲的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”。 这些其实是一些比较偏的知识点,大家能理解最好,不能理解的话尽量避免这么写即可。(关于这部分如果有不懂的可以跟我进行沟通,我也是经过大量的仿真才理解#的机制),大家还可以参考我之前写的文章: lawliet:一个实例带你理解阻塞赋值与非阻塞赋值14 赞同 · 2 评论文章 最简单的tb如上所示,就是写一些测试向量,然后通过肉眼去看波形。这些测试向量如果有严格的先后顺序,一般是放在initial语句里面,通过时间延迟delay分隔开。 同时我们还可以在tb里面增加检查机制,这样可以方便比对,而不用看波形。 测试向量包括输入和期待的输出。一般测试步骤如下: · 产生时钟信号 · 定义相关的数组 · 指定输入,预期的输出 · 比较实际输出和预期的输出是否一致 其实这些测试方法是非常直观的。相信大家也很容易理解 通常我们在时钟的上升沿让输入发生变化(D触发器的基本机制),在时钟的下降沿进行比较,这个时候数据是最稳定的。 上面是输入与预期的输出。准备工作做好以后,就可以进行TB的编写了。 首先例化好相应的模块,产生对应的时钟信号。定义一个大的数组用于读取我们的测试向量。 然后使用readmem函数将之前准备好的文本吃到testvectors这个值中。 每个时钟周期的上升沿,将预期的结果赋值到中间变量中。 然后在适中的下降沿进行比对即可。 当然对应的行数也要增加。大家写的时候要注意数据是一一对应的,别错开就行。 接下来简单讲一下VHDL,实际上VHDL大部分公司都是不适用的。但是存在有些IP库还有部分代码是VHDL写的,所以需要大概能看懂,掌握到这个程度就足够了。 我们看一下这两个例子对比,左边的SV代码我就不讲解了,之前有说过,直接看VHDL代码。 · 首先需要导入IEEE的库,这个有点像C语言导入标准库,是个固定的写法 · 然后用entity gates来说明所要实现的电路为逻辑门,制定输入输出。 · 再通过architecture说明其对应的逻辑。 再看这个例子,用entity mux2说明要实现的是一个二选一的mux,然后用architecture说明其对应的逻辑。 再看一个例子,要实现一个全加器。也是先说明,然后再定义基本逻辑。 可以看到VHDL逻辑非常严谨,可控性很强。需要使用什么就先声明,再使用。代码和硬件的对应关系较强,因此更不容易出错。但是高层次设计(算法层面的代码编写)较为困难,代码量大。因此被SV/Verilog所慢慢替代。但欧洲一些国家的公司还有我国的一些军工企业,还是有使用VHDL的,大家能根据代码大概知道写的是什么就够了,不用自己去写。 然后介绍了一些运算符、位操作的东西。 再看一下模块例化,这个4选1的MUX是由三个2选1的MUX组成的,我们看代码如何编写: · library,entity正常编写 · 用architecture struct of说明是由模块例化组成的 · component说明基本组成部件 · 下面的begin end进行模块的例化,左边的是"lowmux"等是实例化的名字,这个方向与SV相反。 再看一个8位的2选1逻辑。需要两个4位的2选一逻辑组成。代码写法也是基本一致 · library entity · architecture struct说明由模块实例化组成 · begin end里面进行模块例化,实例名:组件名 port map里面说明端口对应关系 寄存器写法如上所示,较为简单就不进行额外说明了,需要注意使用process说明是过程赋值,类似于always块 上面这个例子说明process也可以用在组合逻辑当中。 还有诸如case语句,状态机写法请大家参考课程官方的课件,相信大家都能通过对比看懂,如果有不懂的可以问我。我这里就不一一讲了。 最后再说明一下,如果你是要找一份工作的话,不需要会写VHDL(有些读者是学生,上某门课必须要用VHDL,这种情况就没办法了,老老实实写吧,或者劝你的老师换成Verilog/SV),但是你如果能看懂对于找工作而言肯定是加分项。所以做到能看懂即可! 到这里所有课件讲解结束了,还差SHA256的Project代码讲解文章就正式完结撒花了。大家对什么感兴趣欢迎留言, |