
这是一篇由Espen Tallaksen撰写的客座文章,我(Jonas)在挪威担任FPGA开发人员期间认识了他。Espen是EmLogic的首席执行官,这是一家嵌入系统和FPGA设计公司。Espen还通过开发和维护UVVM为VHDL社区做出了巨大贡献,本文正是关于UVVM的。这不是付费内容。
作者:Espen Tallaksen,EmLogic首席执行官
根据Wilson Research的数据,FPGA的开发时间中约有一半花在了验证上。我认为只需稍作调整且不增加额外成本,就有可能大幅缩短这一时间。
更糟糕的是,几乎一半的验证时间花在了调试上。这包括对DUT(被测设计)和测试平台本身的调试,但在我看来,这在总开发时间中所占的比例实在太大了。
对于FPGA设计,我们都知道架构——从顶层到微架构——对FPGA质量和开发时间都至关重要。显然,这同样适用于测试平台。通用VHDL验证方法学(UVVM)正是为解决这一问题而开发的,它将显著缩短验证时间,同时提升FPGA质量。
UVVM 是一个免费开源的 VHDL 验证库和方法学,提供了尽可能最佳的 VHDL 测试平台方案。凭借其简洁而强大的架构,设计人员能够以前所未有的速度构建自己的测试框架和测试用例。同样重要的是各层级的高效复用。UVVM 拥有独特的复用结构,使其成为高效 FPGA 开发和测试平台复用领域的变革者。
这使得 UVVM 在 FPGA 社区中被迅速广泛采用。目前,全球超过 27% 的 FPGA 设计人员使用 UVVM,若仅统计 VHDL 设计人员,这一比例则更高。有趣的是,UVVM 也是 ASIC 设计人员中最受欢迎的 VHDL 验证方法学。
自 2017 年以来,我们与 ESA(欧洲空间局)保持着紧密合作,共同改进和扩展功能,现在我们刚刚完成了第三个 ESA UVVM 项目,提供了更多验证和调试功能。本文将向您介绍 UVVM,展示它有多么简单易懂、易于上手,同时展示 UVVM 如何帮助您构建更好的 VHDL 测试平台,并显著提升 FPGA 质量和验证效率。
赋能效率与质量
大多数设计师都知道,对于FPGA设计而言,效率与质量同以下设计特性之间存在强相关性:概览性、可读性、可修改性、可维护性和可扩展性。当然,这些特性对于测试平台和验证同样重要。此外,可调试性也至关重要,因为这几乎占用了FPGA开发时间的25%。最后,从一个项目到另一个项目的可复用性始终很重要,但对于验证而言,单个项目内模块测试平台(TB)之间、以及从模块TB到顶层TB之间也存在巨大的改进潜力。
改进架构与简化性
为了实现这些改进,你需要一个真正优秀的测试平台架构,不仅要在高层级上做到,还要一直深入到测试平台的微架构层面。然而,要实现良好的效率和质量,只缺少一个关键方面:简洁性。
当然——对于复杂的FPGA而言,验证很少能做到简单,但关键在于“尽可能简单”,或者更准确地说,“对于你花费大部分时间的任务尽可能简单”,而对于验证来说,这就是要制作所有不同的测试用例,即编写各种测试序列。构建测试平台的其它主要方面包括测试夹具以及任何潜在的验证支持过程、进程和实体。UVVM针对所有这些方面进行了设计。
UVVM提供了什么
那么,什么是UVVM?首先,它是一个免费开源的VHDL验证库和方法学,提供以下内容:
UVVM为VHDL用户提供了一套方法学和库,使其测试平台能够针对从简单到中等再到复杂的DUT进行逐步演进,这样用户只在需要时才提升验证复杂度。那么,让我们从入门级别开始——只是为了展示这有多简单,以及它能给你带来多少收益。
开始使用UVVM
使用UVVM的一个良好起点是评估任何优秀测试平台始终需要什么,这与DUT复杂度无关:
我们可以通过查看一个非常简单的模块的最重要测试平台功能来举例说明,比如一个基本的中断控制器,具有N个中断源、一个输出到CPU的中断以及一个用于软件访问的寄存器接口(SBI = 简单总线接口),如图2所示。
在每个测试平台中,我们还需要一个时钟控制器,在UVVM中你可以在几种变体之间选择,最简单的版本如下:
clock_generator(clk, C_CLK_PERIOD); 这只是放入测试平台架构中的一个简单过程调用。当把过程调用直接放在架构中而非进程内部时,它将成为所谓的并发过程,其工作方式与进程完全相同。因此,clock_generator() 的功能与完整的时钟进程完全一致。UVVM 中提供了大量时钟生成器变体。随后你可以在测试进程中编写测试序列器,如下所示:
log("Check Interrupt trigger and clear mechanism"); check_value(irq2cpu, '0', "irq2cpu default inactive"); check_stable(irq2cpu, now – v_reset_time, "irq2cpu initially stable off"); gen_pulse(irq_source(3), '1', C_CLK_PERIOD, "Set IRQ source for 1T of clk"); await_value(irq2cpu, '1', 0 ns, 2* C_CLK_PERIOD, "Interrupt expected") 这里的全部命令均一目了然,因此易于阅读和修改。作为最后一个参数提供的消息通常是你平时写成注释的内容,但将其包含在过程调用中,可以在出错时将该消息写入转录/日志,或者在你需要时作为正向确认。上述命令产生的输出如下所示。你还可以在此日志输出中包含日志前缀、消息 ID 和作用域:
2000.0 ns 检查中断触发清除机制 ---------------------------------------------------------------------------- 110.0 ns check_value() => OK,std_logic '0'。irq2cpu 默认不活跃 727.5 ns check_stable() => OK。稳定在 0。irq2cpu 初始稳定关闭 1060.0 ns 脉冲至 '1'。设置 IRQ 源为 1T 的 clk 1117.5 ns await_value(std_logic 1, 0 ns, 20 ns) => OK。中断符合预期 以上显示的所有命令均可从 UVVM Utility Library 获取,这是一个测试平台基础设施库,包含大量非常有用的函数和过程。除上述命令外,还有类似的、非常易于使用的函数,用于字符串处理、随机化、等待信号稳定、标志和同步机制、归一化、详细度控制等。
下一个合乎逻辑的步骤是使用总线功能模型(BFM)过程来访问各种 DUT 内部软件可访问寄存器。在下面的示例中,我们首先向中断触发寄存器(ITR)写入一些内容,然后读回中断请求寄存器(IRR)并检查该值是否符合预期:
sbi_write(C_ADDR_ITR, x"A0", "ITR: Set more interrupts"); sbi_check(C_ADDR_IRR, x"A5", "IRR: Check updated value"); 结果将如下所示:
2020.0 ns SBI write(A:x"2", x"A0") completed. ITR: Set more interrupts 2040.0 ns SBI check(A:x"0", x"A5") ==> OK, IRR: Check updated value 然后,在测试序列器中,您可以使用所有这些过程以及许多其他过程来检查模块内的各种功能,最后写出警报摘要。然后,您可以将此摘要或提供的状态摘要共享变量用作回归测试工具的输入。
您可以观看我们为Siemens、Aldec等公司提供的免费网络研讨会之一,以获得更全面的介绍。
BFM过程的局限性
BFM过程非常适合访问接口,因为您只需要调用一个过程。所有协议细节、信号摆动、采样等都会为您处理,您甚至不必了解接口或协议。此外,它允许更改协议和接口,而无需更改BFM过程或来自序列器的调用。
然而,BFM有一个主要限制:它们是阻塞式的。这意味着在执行BFM时,执行该BFM的进程内无法做其他任何事情。因此,当在测试序列器中执行BFM时,测试序列器在接口访问完成之前无法做其他任何事情。例如,一个UART测试序列器无法在向DUT的RX输入发送数据的同时,通过CPU接口读取先前接收到的字节。由于这是一个非常典型的易错场景,测试平台绝对应该测试所有通道上的同时活动。
意识到这一点的设计人员通常从三个不同的测试进程来处理三个独立的UART接口(RX、TX和CPU接口)。这种方法的问题在于,为了在此类场景中找到极易出错的周期相关边界情况,你需要仔细控制这些接口上的交互。
处理这个问题的常规方法是在这些进程之间应用各种同步机制,通常是通过来回发送触发信号或信号量。这看起来像是一种结构化的方法,但你很快就会失去全局观。这意味着你可以忘记可读性、可维护性、可调试性和可复用性。从一个单一的大脑——在这种情况下是一个单一的序列器——来控制一切要容易得多,前提是你有正确的测试平台架构。在这方面,UVVM是向前迈出的一大步。
多接口的简单控制
UVVM的VVC(VHDL验证组件)系统通过将BFM过程的执行在零时间内分发到各VVC,以非常有条理且简单的方式实现对多个接口上同时活动的控制。UVVM甚至允许在任意BFM执行之前或之后插入延迟。这意味着测试序列器对完整验证环境拥有完全控制权,你只需查看单个进程中的测试序列(而非多个进程),就能随时轻松了解测试平台中将发生什么。
UVVM还允许从多个测试控制器控制VVC,但除非确实需要,我 certainly 不建议这样做——这种情况非常少见。这里的一个不错特性是,对于这些特殊场景,UVVM实际上甚至允许单个VVC由多个序列器控制。
从BFM切换到VVC
从测试序列器的角度来看,从直接使用BFM切换到使用VVC相当简单。你只需使用一组略有不同的过程,其中最重要的区别是增加了目标参数。这些目标参数指明哪个验证组件将负责BFM的实际执行,因此实际上,VVC命令只是将BFM命令以非耗时方式分发给指定的VVC。而这种非耗时分发意味着测试序列器不会被阻塞,而是可以同时向多个接口分发命令,然后甚至可以并行地自行执行其他操作。
图3右侧展示了一个基于BFM的测试平台(TB),其中测试序列器可以直接访问DUT的各个接口,并使用BFM逐一访问这些接口。左侧展示了一个基于VVC的测试平台。在这里,VVC直接(端口映射)连接到DUT的各种接口,测试序列器向各个VVC发送非耗时命令。需要注意的是,VVC随后会立即开始向DUT执行相应的耗时BFM过程。
因此,测试序列器完全掌控DUT接口上发生的一切,并可使用await_completion()和insert_delay()命令与任何VVC的BFM执行进行同步。await_completion()将使测试序列器暂停,直到指定的VVC完成执行其所有命令或仅完成指定命令。通过这种方式,测试序列器可以全面掌握测试平台的状态,并知道何时向各个VVC发出命令。insert_delay()命令允许测试序列器对各VVC接口处理进行偏移或错位,从而针对与时钟周期相关的边界情况。
概览性、可读性、可维护性、可修改性与可扩展性
如果你的DUT相当简单,可能仅使用BFM即可应对。VVC面向中高复杂度的模块和FPGA(或ASIC),但请注意此处的复杂度是从验证角度而言的。因此,即使是简单的UART也能从使用VVC中获益。当然,这也是一个质量问题。如果你能接受每10,000字节出现一次UART字节错误,那么你可以降低验证级别和工作量。如果不能接受,VVC将极大地帮助你检测此类缺陷。
对于简单的测试平台,使用 UVVM Utility Library 和 BFM 就足够了;如果不够,至少也是一个非常好的起点。你可能认为简单测试平台的改进潜力不大,但即使是小项目,也很容易节省 50-300 小时(约占总项目时间的 10-30% 或更多),同时还能提升质量。对于更复杂的模块或 FPGA,节省潜力可能更高,甚至按百分比计算也是如此。
顺便提一下,UVVM 拥有迄今为止数量最多的免费开源 VHDL BFM 和 VVC(见图 4)。
AXI4-lite AXI4 Full APB AXI-Stream 发送与接收 UART 发送与接收 SBI SPI 发送与接收 I2C 发送与接收 GPIO Avalon MM Avalon Stream 发送与接收 RGMII 发送与接收 GMII 发送与接收 Ethernet 发送与接收 Wishbone 时钟发生器 错误注入器 图 4:UVVM 中可用的免费 BFM 和 VVC
AXI stream VVC 示例
在本文中同时展示一个 AXI stream 示例可能是有意义的,因为 AXI stream 接口如今被用于许多 FPGA 项目中。在这里我们还可以展示 UVVM 中一个非常有趣的附加特性。
但首先,在为具有一个或多个AXI stream接口的DUT制作测试平台时,您可以同时使用BFM和VVC方法,其优缺点如上所述。对于图5所示的DUT,使用VVC方法比BFM方法能更简单地检测出数据流和接口中更多的潜在问题。
该图以一个非常简单的示例说明了测试序列器如何向测试夹具发出两条命令:发往主VVC的axistream_transmit()和发往从VVC的axistream_expect()。这两条命令由测试序列器同时(仅相差delta周期)发往各VVC。随后,主VVC立即(同时)开始向DUT发送数据,而从VVC则等待DUT输出数据到达,然后将实际接收到的数据与预期值进行比对。协议由此也自然得到了确认。
本页摘要由 AI 辅助整理,经编辑审核后发布;AI 仅用于提炼与分类,原文均附来源链接。