传统的测试平台实现只能按顺序设置工作参数,无法动态响应被测设备的要求。因此这种测试方法会遗漏软件和硬件之间的某些复杂时序交互。随着FPGA 功能的逐渐强大,软件和FPGA之间的交互信息量也在不断增加。本文讨论的以消息驱动的测试平台能够模拟FPGA实际运行环境对FPGA进行仿真测试。该方法除了能为测试平台所要求的物理接口模型建模外,还能对控制FPGA的部分软件进行建模。因此允许人们在测试平台和FPGA之间建立动态交互渠道,从而改善FPGA的测试覆盖率。
测试平台应该真实反映FPGA在实际硬件环境中的工作状况。以前也经常出现仿真通过了但在实际在线使用时FPGA出故障的情况。
有时很容易找出故障原因,有时则很难。一旦找到问题的症结我们会扪心自问:“为什么不早点发现这个问题呢?”很多时候这些问题发生在软件和硬件之间的灰色区域。在仿真FPGA时我们应该在何处下手呢?如果我们忽略软件是如果使用FPGA的,那么我们以后肯定能找出问题的原因。因此不受硬件的约束、积极吸收一些软件功能才是明智不举。这样做有以下一些优点:
1. 由于覆盖了一部分硬件与软件之间的灰色区域,测试覆盖率可以得到改善。
2. 能够更好地理解软硬件的交互以前二者之间的交互时序。
3. 能够部分验证FPGA的控制算法。
我们如何设计这种测试平台呢?
在FPGA和处理器系统中,软件设置好FPGA寄存器后就可以与FPGA进行交互通信了。这种测试平台可以同时满足这二种情况。不过后者令人更有兴趣,也更难一些。让我们考虑一下如图1所示的系统,它的FPGA内部有一个处理器接口和二个UART。
FPGA内部的这些模块通过内部总线连接在一起。为了控制UART,外部微处理器需要通过处理器接口和FPGA内部总线访问UART内部的寄存器。波特率、奇偶校验等UART参数必须由软件先行初始化设置。在工作期间,软件在访问数据寄存器之前必须查询UART状态寄存器或等待中断,否则数据寄存器的内容可能是无效的。
测试平台部分由三个测试模块组成,其中有二个测试模块与UART接口,另一个与FPGA处理器接口相接。必须配置好测试模块,以确保UART测试模块的工作参数和UART工作参数相同。
为了仿真通过UART给UART测试模块发送数据的工作过程,需要二次循环。每次循环都要检查UART的状态寄存器,当状态寄存器指示允许写入时再向发送数据寄存器写入数据。这二次循环需要在处理器测试模块中完成,因为只有一个VHDL进程可以驱动FPGA处理器接口信号。
这种方法对简单案例很有效,但随着处理器测试模块中测试模块的增多,这种方法将变得越来越复杂。另外,因为需要比较从FPGA UART发送到UART测试模块的数据,仍然需要在模块之间建立一定的通信机制。
由于已经对硬件和部分软件作了建模,因此可以研究一下软件在系统中是如何工作的,从而帮助我们作出正确的比较结果。
首先我们需要构筑能够匹配FPGA功能的软件,以便我们拥有能够管理每个FPGA模块的软件任务。该软件任务可以作为这种模块的设备驱动器。参考高级操作系统提供的功能,软件任务之间的通信可以通过消息管道和信号机实现。在VHDL中可以使用相同的结构。软件任务类似于VHDL进程。虽然不象C等高级语言那样方便,但还是可以创建消息队列的。利用信号可以很简单地构建信号机,然后依靠接收进程等待这一信号的变化。至此我们就具备了用 VHDL创建软件驱动器的所有条件。
那么这样一种测试平台的结构是怎样的呢?图2是测试平台内部消息流程的一个简单例子。
命令是由命令解析器从脚本文件中读取的。以命令解析器为目的的命令在本地得到处理,而其它消息发送到相应的模块。脚本命令被转换成标准消息格式。这种消息格式一般由一条记录组成,该记录包含消息目的地、消息源、消息类型和数据阵列指针等字段。消息送到目的地后再进行进一步处理。
目标模块不断查询消息队列是否有输入消息。当有消息到达时,它会检查消息类型并决定如何处理该消息。一般用case语句区分不同的命令。在每个case语句中,可以立即执行命令(比如希望用一些数据填充某些RAM的情形),也可以通过激发被某个进程监视的脉冲信号触发并启动这个进程。
值得注意的是我们可以从测试平台中的任何模块向其它任何模块发送消息。因为有这样的反馈路径,因此能够构建查询循环。图3 给出了UART测试模块的结构。
模块被分成三大部分:物理接口、软件接口和本地数据存储模块。
物理接口用来管理与FPGA的连接。在该模块内有二个VHDL进程为测试UART建模。第一个进程收集来自FPGA UART RxD引脚的数据,并把数据存放在本地数据存储器中。第二个进程将来自本地数据存储器的数据通过TxD信号发送给FPGA UART。
软件接口对运行于实际微处理器的软件算法进行建模。在该模块内也有二个进程。第一个进程将本地数据存储器中的数据发送给FPGA UART。这些进程和物理接口进程的区别在于这时的数据交换是通过UART数据寄存器而不是UART TxD和RxD信号完成的。这就要求我们可以从UART测试模块访问FPGA UART寄存器。通过交换UART测试模块和进程接口模块之间的消息队列中的消息实现对FPGA UART寄存器的访问。
控制接口用于启动物理接口内的进程。共享变量和信号用于软件和物理接口模块之间的通信。
例子
下面研究一下可能运行于图1所示的FPGA上的测试。在测试中需要将缓冲数据通过每个UART发送到相应的测试模块。对每个UART来说测试包含以下一些步骤:
..初始化UART
..初始化UART测试模块
..初始化发送数据的缓存
..缓存非空时循环
..比较结果
利用简单的脚本命令如WRITE_REGISTER就可完成UART和UART测试模块的初始化。将要发送的缓存数据存放于UART测试模块中。可以用脚本命令设置该数据。循环相对要复杂些,包括将来自UART测试模块的消息发送给处理器接口模块,并用指令读取UART状态寄存器。一经读取,处理器接口模块就会向UART测试模块回送一条带状态寄存器值的消息。然后由UART测试模块决定是否发送数据。
UART测试模块的其它部分收集来自FPGA TxD引脚的数据。待收集完所有数据后,就可以比对接收数据和期望数据了。
处理器接口模块相对简单些,它在输入队列和处理器上接收消息。通常这些消息要么是写寄存器命令,要么是读寄存器命令。如果是写寄存器命令,来源于消息的数据和地址就被写入FPGA处理器接口,其写入方式与实际处理器向FPGA写入的方式相同。如果是读寄存器命令,则地址来自消息。FPGA处理器接口完成读周期,读到的数据放在消息中再发送回请求读的模块。
其它测试模块以相同的方式写入UART测试模块。大多数测试模块具有相同的结构,而由消息驱动测试平台建立的架构能使新测试模块的插入非常容易。
本文小结
FPGA加上微处理器构成了典型系统的基础。FPGA和微处理器之间的交互常常很难预测和查错。消息驱动测试平台则有助于仿真这些交互,从而减少硬件测试期间可能会遇到的问题。
作者:Robert Schenk
Array Electronics公司
Email: jrschenk@t-online.de