购买
下载掌阅APP,畅读海量书库
立即打开
畅读海量书库
扫码下载掌阅APP

第八回
严测试片外编程 如何编写测试程序

本来很犹豫是否还要写这一讲的内容,按理说每个讲FPGA或者数字逻辑设计的材料中都会不遗余力地对测试程序(Test Bench)进行介绍。而且,如何对于测试向量进行编程,也是数字逻辑设计者的基本功。更重要的是,这部分内容比较乏味,绝对会减少某家很多观众(这是私利,不能明说的)。

在看了一些有关别处的资料之后,我发现很多材料还是就设计说设计。这样不能说错,但还是有偏颇。所以,我决定从系统角度和大家掰扯掰扯这个测试向量的问题。

在不考虑电源输入的前提下,在我们系统/板子上,能够不依靠其他外界输入而产生输出信号的器件有木有呢?当然有,而且必须有,那就是大名鼎鼎的晶振了,用来产生我们说过的、对于系统极其重要的系统时钟信号。

除此之外呢,不说什么电容、电阻和电源模块之类的和我们数字逻辑设计无关的玩意。不依靠其他外界输入而产生输出信号的器件还真没有。下面这位开始抬杠了:这个可以有啊,比如我做一个导航用的发射机,配置什么的都固定,发射信号也固定,不是不要输入了?大哥,你忘了?这个不也要时钟输入吗?要不,不就成模拟发射机了?这小子想叫各位数字逻辑设计的工程师都失业啊,给我往死里打,打的他妈妈都不认得他!

(插句话,我们一般工程师作为一个工作单元,其输入就是薪水。为什么老板总觉得员工懒呢?其原因是激励不足啊。)

接着设问(苏格拉底式教学):测试向量是从哪里来的?是从天上掉下来的吗?当然不是。测试向量,也包括可能的外部器件,可能来源有三种,待小子细细表来。

来,来,来!我们来给自己的芯片安装起搏器,叫设计转起来。在做测试程序的时候,可以忘掉可综合性的限制。喜欢“fork”就用“fork”,中意“initial”也没问题,百无禁忌。南无阿弥陀佛,正所谓“海阔凭鱼跃,天高任鸟飞”。所有的Verilog的关键字都在候选范围内,爽吧?

1.简单模块靠逻辑

俗话说:“好汉不提当年勇”。那么我所说的当年的段子,估计不会影响我的光辉形象吧?想当年,我也是以能做出一个计数器什么的单元而沾沾自喜的。套用刘若英的《后来》歌词:“…复位信号,用时延,我总是那么的编写;‘时钟',我自然想,用forever,信号自然出现;那个永恒的日子,工作才一年,我首次测试的那个日子;让我往后的时光,每当有感叹,总想起,当天的程序;那时候的测试,总是那么的简单……”。这里说的就是测试向量的第一个来源:当设计的单元简单、输入输出关系明确的时候,可以由设计者直接设计测试向量完成验证。这也是大多数资料里面介绍的方法,其中内容不必详述。比如,你做一个计数器,然后你做一下reset和clock信号,于是在reset不生效之后,输出就是 1-2-3…了,OK,恭喜啊,你得设计正确。再如,你设计一个加法器,你就需要做不同的加数和被加数的组合,如果得到0+1=1,1+1=2,1+2=3…那么就可以交货了。领会精神!不想找打,就不要抬杠,我们有前车之鉴!

噗通,噗通,听到了吗?系统心跳的声音,这就是时钟。一般,老夫的时钟是这样写的:

对于不是50%占空比的时钟,需要另一个参数,例如高电平的时钟周期。然后,低电平的时钟周期由时钟整体周期和高电平时钟周期计算获得。在“forever”块的内部,需要两条语句分别拉高和拉低时钟。

还有复位信号也采用这种手段:

其他信号也来如法炮制?您老先请,我不陪着,不带这样累傻孩子的。我做一个两输入8比特位宽的加法器,难道要写65536条语句?标准答案来了:在仿真里面也用时钟触发的模块来完成。例如上面说的加法器,就用两个计数器实现。第一个计数器以系统时钟为节拍变化;另一个计数器,当第一个计数器变化一轮之后,执行一次加一操作。他们的时序图,如图1.41所示,代码不难,就不浪费纸张了。

图1.41 加法器验证程序的时序图

2.外部芯片红线牵

第二类情况是这样的,你设计了一个对于复杂芯片的接口或者控制器,你就需要外部芯片的行为模型配合你的测试了。举个例子,你需要设计一个SDRAM的控制器,用来控制大容量的SDRAM来存储数据。首先,你会得到一个对应RAM的datasheet(数据手册),里面会有芯片的电气特征啊什么的数字逻辑设计不感兴趣的内容。大家需要注意的就是读写的时序,还有SDRAM的刷新要求(不懂这个?没关系了,就是一个例子。等到你做的时候,自然就了解了。如果还是不懂,那么等着丢数据吧,别抱怨我没说过)。这个控制器基本就是一个状态机。在设计完之后,需要进行验证的时候,问题来了:“如何测试这种系统呢?”。竖起耳朵听着,找供货商要对应芯片的行为模型,这个可以有的。

事实上,在选择芯片的时候,有没有这种模型是很重要的一个指标,必须向采购要求。叫甲方们在吃回扣之余,一定要选择有行为模型的芯片。要不然,逻辑设计的工作量就是加倍了。而且即使我们按照自己的理解设计了外部芯片的行为,还不能保证我们做的模型是完全正确的。这就陷入了验证—再验证的死循环了,命苦啊。

这种验证最简单,除了时钟、复位什么的以外,就需要构建几个线型变量,把我们的设计和片外芯片勾搭在一起就好了。大伙儿就是月老的角色,积德的。

3.复杂处理读文件

最后一种验证可以帮助大家复习一下第一讲。子曾经曰过:温故而知新,可以为师矣。这次有给我们输入文档的算法工程师一起来联合工作。可惜,这类工程师里面也缺乏美女/帅哥,很难达到“男女搭配,干活不累”的要求。这种情况一般发生在我们设计信号处理类系统的时候,例如:通信里面的发射机、接收机等。和我们一样辛劳的算法工程师们,需要给我们提供测试向量。这种向量一般是以文件形式提供的,里面有输入和输出数据,一般是十六进制的几列。大家需要利用文件读写函数(Verilog 里面就是$readmemh之流),读取输入(可能也要输出)数据,输入需要验证的系统,来考察设计是否正确。

给一个大概的样子:

这样,就从文件中读出了一组数据,存储到了数组in_vec里面。然后,和上面计数器类似,一个时钟或者约定的周期,输出一个in_vec里面的数据。如此,系统就开始工作了。

说到这里,又可以显示一下我的卑鄙了(有诗云:卑鄙是卑鄙者的通行证。这样我可以畅通无阻了。贫僧特别卑鄙,该发特别通行证了)。我做算法工程师的时候,给设计工程师用来单元验证的测试向量,与给测试工程师用来集成和系统测试的测试向量,向来是不同的两组。这样可以防止设计工程师作弊。设计的哭了:“本是同根生,相煎何太急”。于是乎,当年联调的时候,我就可以搬个椅子睡觉了,告诉别的单元的人:“有问题叫醒我”。我从来是睡到自然醒的。

最后还有点时间,和大伙儿简单地唠唠复杂系统自动测试的事情。

首先,仿真器提供一个编程语言接口PLI(Program Language Interface)。PLI把C程序嵌入到HDL设计中,用户可以用C写扩展的系统任务和函数,扩充了HDL语言的功能。有了PLI,C和HDL之间就可以直接通信,去掉了文件交互的环节,大大提高了效率和方便性。然后,C还可以嵌入Matlab和ADS等,牛的一腿。

其次,如果采用上面说的第三种验证方法。可以通用比较器来验证设计,例如用相等比较器,相同输出为“1”。如果见到了“0”,恭喜了,子曰:闻过则喜。这种方法里面需要注意的是时延问题。我们的所有设计,在输入和对应输出之间,总是存在时延的。这个时延,就是我们以前提到过的建立时延。在有效输出建立之前,会存在若干无效的过渡性数据,这些数据需要被删除。具体的时延是多少,圣上在设计的时候应该确定的。我就不在这里“皇帝不急太监急”了。

同样给一个样子,假设输出是一个8比特位宽的数据,处理时延为3个时钟周期。

这正是:“系统设计已完毕,仿真验证待做起;时钟复位写延时,其他部分靠逻辑。外部芯片厂家提,代码中间把线系;信号处理赖文件,读出输入芯片里。” M0Gu6NiF2GQQ6CM3F0FJYiCe4lY/PKejKxSaycwKhI7tfHiJC8OaJyyqS1zzkHku

点击中间区域
呼出菜单
上一章
目录
下一章
×