try ai
科普
编辑
分享
反馈
  • 待测器件 (DUT):验证、表征与去嵌

待测器件 (DUT):验证、表征与去嵌

SciencePedia玻尔百科
核心要点
  • 数字测试平台通过生成激励、使用 reg 和 wire 变量进行连接以及控制仿真时间,为测试待测器件 (DUT) 创建了一个虚拟环境。
  • 高级验证使用自校验测试平台,它利用参考模型或记分板 (scoreboard) 来自动比较 DUT 的实际输出与预期结果。
  • 可以使用 JTAG/边界扫描对 PCB 上的 DUT 进行物理测试,该技术通过创建一个虚拟测试链来隔离和控制器件的引脚。
  • 表征模拟和高频 DUT 需要使用开路-短路 (Open-Short)、TRL 或时域门控等去嵌技术,以在数学上消除测试夹具 (test fixture) 带来的寄生效应。

引言

待测器件 (DUT) 的概念几乎是所有科学和工程领域的基础。它是我们试图理解、验证或表征其行为的特定组件、电路或系统。然而,在这一追求中出现了一个重大且普遍的挑战:我们永远无法在完美隔离的环境中观察 DUT。每一次测量都会受到所用工具的影响,从而形成器件及其测试环境的复合视图。因此,测试的艺术,就是将器件本身的行为与其观测过程产生的人为现象区分开来的艺术。

本文探讨了工程师为克服这一根本问题而开发的各种复杂方法,其路径从数字仿真的虚拟世界延伸到高频模拟电路的物理现实。通过理解这些技术,您将深入了解我们如何确信一个器件能按预期工作,无论它是一段代码还是一块硅片。接下来的章节将引导您完成这一旅程。“原理与机制”一章将通过剖析数字测试平台的架构、仿真时间的复杂性以及自动验证的逻辑来奠定基础。随后,“应用与跨学科联系”一章将把视野扩展到物理硬件,探索使用 JTAG 进行的板级测试、模拟噪声测量的挑战,以及优雅的去嵌数学艺术——它让我们能够透过测试夹具的“幽灵”看到 DUT 的真实面目。

原理与机制

想象一下,您想了解一台新设计的汽车引擎是如何工作的。您不会只盯着蓝图看,而是想亲眼看它运转。您会搭建一个测试台,接上燃油管,连接传感器,然后让它经历各种工况——怠速、加速、负载运行。引擎本身是主角,但整个测试台——燃油、传感器、测功机——才是使有意义的测试成为可能的原因。

在数字逻辑的世界里,同样的原理也适用。我们想要验证的芯片或电路就是我们的“引擎”,我们称之为​​待测器件 (DUT)​​。但要测试它,我们必须围绕它构建一个虚拟世界。这个世界本身就是一段复杂的代码,称为​​测试平台 (testbench)​​。它集我们的实验室、测试台和试验场于一体。测试平台的根本目的,是创建一个受控的、可重复的环境,以便我们能驱动 DUT 并观察其行为。

舞台与演员:盒子里的宇宙

验证的第一步是将我们的 DUT,即“演员”,放置到测试平台的“舞台”上。在像 Verilog 这样的硬件描述语言 (HDL) 中,这个过程称为​​实例化 (instantiation)​​。实际上,我们是在将 DUT 设计的一个实例召唤到测试平台的仿真现实中。测试平台通常是一个“顶层”模块;它是一个自包含的宇宙,不需要外部输入或输出,因为它在内部生成一切。

但这个宇宙如何与 DUT 互动?我们如何向它发送信号,又如何监听它的响应?这需要两种不同类型的连接,这是一种反映信息流动的优美二元性。

首先,要向 DUT 发送信号,我们需要一种可以保持值并根据我们的命令进行改变的东西。可以把它想象成一组我们的测试脚本可以拨动的开关或按钮。在 Verilog 中,这是一种 ​​reg​​ (寄存器) 类型。我们在测试平台中声明 reg 变量,并将它们连接到 DUT 的输入端口。因为 reg 可以存储一个值,所以我们可以随时间程序化地为其赋值,从而创建驱动 DUT 的动态激励。

其次,要观察来自 DUT 的信号,我们需要一种不同的工具。我们需要一种像电压表探针一样的东西——它本身不产生信号,但被动地报告它所接触的任何东西的值。这就是 ​​wire​​。我们声明 wire 变量,并将它们连接到 DUT 的输出端口。wire 将持续反映 DUT 输出的状态,让我们能够随时看到我们的“演员”在做什么。

因此,其基本架构是 reg 和 wire 之间的一场双人舞:我们使用 reg 来“对”DUT 说话,使用 wire 来“听”DUT 的声音。这种简单而强大的区别构成了每个测试平台的支柱。

编写剧本:激励的艺术

当 DUT 就位、连接建立后,就该编写脚本了——即我们将要施加的一系列输入,或称​​激励 (stimulus)​​。测试不是一个单一的快照,而是一个在第四维度——时间——中展开的故事。测试平台使用延迟控制来控制仿真时间的流动,通常用 # 后跟一个时间单位数来表示。例如,#10 告诉仿真器在继续之前暂停 10 个单位时间。这使我们能够创建一个精确、定时的事件序列:在时间 t=0t=0t=0 时,将输入设置为一种状态;等待 10 个时间单位;在 t=10t=10t=10 时,改变一个输入;再等待 10 个单位时间;依此类推。

仿真的力量在于自动化。虽然我们可以手动写下每一个输入变化,但更优雅的方法是让测试平台自动生成它们。对于输入数量较少的电路,我们可以使用一个简单的 for 循环来遍历每一种可能的组合。如果一个 DUT 有 4 个输入,一个从 0 到 15 的循环可以系统地施加所有 24=162^4 = 1624=16 种输入向量,仅用几行代码就能确保详尽的覆盖。

有时输入本身需要被构建。想象一下 DUT 需要一个 8 位数,但我们的测试平台逻辑处理的是两个独立的 4 位“半字节 (nibble)”。我们可以使用​​拼接 (concatenation)​​ 运算符来动态组装最终的输入,该运算符就像胶水一样,将较小的向量组合成一个较大的向量。像 {upper_nibble, lower_nibble} 这样的表达式会创建一个 8 位向量,这是测试平台如何在将数据呈现给 DUT 之前对其进行操作的完美示例。

随着测试变得越来越复杂,将这些激励向量直接硬编码到测试平台中会变得很麻烦。一个更强大、更灵活的策略是将测试数据从测试逻辑中移出。我们可以将长序列的输入向量存储在一个外部文本文件中。这样,测试平台的任务就变得更简单:从文件中读取一行,将其应用于 DUT,等待,然后重复。这种​​数据驱动的方法​​将测试场景与测试平台代码解耦,使工程师只需编辑一个文本文件就能编写新的测试,而无需接触验证环境本身。

评论家:构建一个自校验的宇宙

到目前为止,我们的测试平台一直是一个尽职的舞台监督,施加激励并让我们在波形查看器上观察结果。但这是一个手动过程。工程师仍然需要看着输出的 sum 和 carry_out 信号,然后判断:“是的,这是一个加法器的正确行为。” 验证领域的真正革命是创建​​自校验测试平台 (self-checking testbench)​​——一个不仅充当舞台监督,还充当无所不知的评论家的测试平台。

自校验测试平台的核心是​​参考模型​​(有时称为“黄金模型”)。这是测试平台中的一段代码,它独立地计算任何给定输入的预期正确输出。对于一个简单的 2-to-1 多路选择器,参考模型可以是一行优雅的代码:expected_y = (sel == 1) ? b : a。这个表达式完美地模仿了 DUT 的指定行为。

有了参考模型,验证过程就成了一个闭环。测试平台施加一个输入,稍等片刻让 DUT 处理并产生输出,然后将 DUT 的实际输出与参考模型的预期输出进行比较。如果它们不匹配,就会自动标记一个错误。整个仿真可以运行,最终的输出是一个简单、明确的“通过 (PASS)”或“失败 (FAIL)”。

这个强大的思想可以与我们的数据驱动方法相结合。外部文本文件不仅可以包含输入激励,还可以包含每个输入向量的预计算预期输出。然后,测试平台的逻辑对每个测试用例都遵循一个清晰、精确的序列:

  1. 从文件中读取输入向量和预期输出向量。
  2. 将输入向量应用于 DUT。
  3. 等待一个小的、固定的传播延迟,以便 DUT 的逻辑稳定下来。
  4. 将 DUT 的实际输出与从文件中读取的预期输出进行比较。
  5. 如果它们不同,则报告错误。

这个“施加-等待-比较”的序列是自动化验证的基本算法。

对于高度复杂的系统,其中事务 (transaction) 可能被乱序处理或涉及多个并发代理 (agent),简单的比较是不够的。在这里,我们引入一个更复杂的组件:​​记分板 (scoreboard)​​。记分板作为事务的中央交换中心。测试平台中的监视器 (monitor) 向记分板报告 DUT 完成的“实际”事务。同时,参考模型报告“预期”事务。记分板的工作是将它们匹配起来。它可以处理乱序到达的事务并跟踪所有内容。在仿真结束时,任何预期但从未出现的事务,或任何实际发生但从未预期的事务,都代表一个错误。记分板确保 DUT 应该做的所有事情都已完成,并且它没有做任何不该做的事情。

深入探讨:时间的隐藏机制

我们经常用像 din = 5; 这样的简单指令来命令我们的测试平台。我们想象这是瞬间发生的。但在一个运行在串行计算机上的仿真中,“瞬间”到底意味着什么?当我们告诉 DUT 在“同一时间”改变其输入并检查其输出时,会发生什么?这个问题揭开了仿真器事件队列的帷幕——这是协调并行硬件执行假象的隐藏机制。

在 Verilog 中,考虑两种类型的命令或赋值:

  • ​​阻塞赋值 (=):​​ 这是一个“立即执行”命令。仿真会暂停并完全执行此赋值,然后才移至下一行代码。它是串行的,就像食谱一样。
  • ​​非阻塞赋值 (=):​​ 这是一个“安排更新”命令。仿真器计算右侧的结果,但不会立即更新左侧的变量。相反,它会安排在当前仿真时间步的最后,在所有其他“立即执行”命令完成后再进行更新。

这种区别至关重要,因为它模仿了真实的硬件。同步电路中的触发器不会在其输入改变的瞬间改变其输出;它们都在时钟边沿采样输入,然后,稍后,所有触发器一致地改变它们的输出。非阻塞赋值是模拟这种并行行为的关键。

现在,想象一个打破此规则的测试平台。它使用阻塞赋值来改变 DUT 的输入,并在由时钟边沿触发的同一个程序块中,立即检查 DUT 的输出。而 DUT 本身,作为一个同步流水线,正确地为其内部寄存器使用非阻塞赋值。于是,​​竞争条件 (race condition)​​ 出现了。如果仿真器碰巧在该时钟边沿处,在 DUT 的代码块之前执行了测试平台的代码块,就会发生一个微妙的错误。测试平台驱动新的输入 (din = 5)。然后 DUT 执行并看到这个新输入。然而,DUT 的输出是基于一个内部寄存器的,该寄存器计划根据前一个周期的值进行更新。当测试平台采样输出时,它看到的是旧的、过时的值,导致一个看起来像是偏差了一个周期的验证失败。

为了解决这些竞争问题,SystemVerilog 引入了​​时钟块 (clocking blocks)​​,它们旨在正式指定测试平台和 DUT 之间围绕时钟边沿的时序关系。它们允许我们说:“在时钟边沿前 1ns 采样输入,并在时钟边沿后 2ns 驱动输出。”但即使是这种强大的抽象也有其微妙之处。如果我们指定一个 output #0ns 的偏斜 (skew),我们的直觉可能会认为驱动发生在时钟边沿“处”。然而,语言标准将其定义为驱动发生在仿真时间步的一个特定阶段,该阶段在 DUT 已经为同一时钟边沿采样其输入之后。结果呢?DUT 仍然捕获旧值,我们的数据被错过了一个周期。

这段旅程,从将 DUT 放置在舞台上的简单行为,到仿真调度深奥的复杂性,揭示了一个深刻的真理。验证不仅仅是编写测试。它是构建完整、自洽的虚拟宇宙。要成功做到这一点,我们不仅必须是优秀的架构师,还必须是这些人工世界的物理学家,理解支配其行为的基本定律,直至最小的仿真时间量子。

应用与跨学科联系

隔离的艺术:看清待测器件

在科学的宏伟冒险中,我们的探索目标通常是理解一个特定的事物。它可能是一个晶体管、一个生物细胞或一颗遥远的恒星。这个我们好奇的对象,用工程师的语言来说,就是​​待测器件 (Device Under Test)​​ 或 DUT。但在这里我们面临一个根本性的困境,一种宇宙级的玩笑:我们永远无法真正看到事物本身,至少不能直接看到。当我们试图测量它、触碰它、用光照射它时,我们看到的就不再仅仅是那个器件了。我们看到的是器件和我们的测量设备。我们是通过望远镜看到恒星,在显微镜下看到细胞,连接到导线和仪表来看到晶体管。

DUT 的故事就是应对这一挑战的故事。它是将我们想要研究的事物从我们用来研究它的工具中解脱出来的艺术。这是一段充满深刻创造力的旅程,将我们从简单的数字逻辑带到量子噪声的幽灵世界和矩阵代数的优雅抽象。它证明了我们有能力剥开观察的层层外衣,以尽可能近地一窥器件本身的真实本质。

数字木偶戏:让 DUT 起舞

让我们从清晰、明确的数字电子世界开始。想象我们的 DUT 是一个小逻辑电路,一个被设计用来表演特定舞蹈的木偶。作为验证工程师,我们的工作就是成为木偶师。“测试平台”是我们的舞台和剧本。我们必须在正确的时间拉动正确的线,看看木偶是否按照其设计者的意图行事。

我们的剧本可能非常简单:在时间零点,将输入设置为 0000;然后在主时钟的第一个节拍,将其更改为 0101;第二个节拍,1010,以此类推。我们编写这个与时钟同步的激励序列,以引导 DUT 完成其动作。这是最基本的交互形式:我们命令,DUT(希望如此)服从。

但一个好的木偶师不仅仅是拉线;他们会密切关注表演。如果我们忘记测试舞蹈的关键部分怎么办?假设我们的 DUT 是一个寄存器,当“加载使能”信号关闭时,它应该保持其值。在我们的测试序列中,我们可能正确地测试了它会复位到零,以及在使能时会加载新值。但如果我们从未检查当它应该保持值时,是否正确地忽略了新的输入数据,我们可能就会错过一个关键的错误。我们的测试存在盲点;我们的“测试覆盖率”不完整,一个有缺陷的器件可能会溜进最终产品中。

木偶本身也可以变得越来越复杂。现代数字设计通常不是固定的,而是可配置的。想象一个移位寄存器,它可以是 8 位、12 位或任意位数 N。DUT 不是一个特定的器件,而是一个蓝图。我们的测试平台就必须足够智能,能够实例化并测试一个特定的配置,比如 N=12 的版本,应用一长串复杂的复位、并行加载和串行移位序列,以确保这个特定实例完美工作。

有时,表演不是独白,而是对话。考虑一个需要通过共享总线通信的 DUT。它不能随心所欲地喊出它的数据;它必须遵循一个协议。它可能会升起一个“请求”(req) 标志,然后必须耐心等待另一个设备——由我们的测试平台扮演——以“确认”(ack) 信号响应,然后才被允许将数据放到总线上。如果 DUT 不耐烦,在收到确认信号之前就将数据放到总线上,它就违反了协议。我们的测试平台,作为这个数字握手中的警惕伙伴,必须被设计成能捕捉到这种违规行为。

全视之眼:电路的 X 射线视觉

通过实例进行测试功能强大,但它有一个根本的弱点:我们无法测试所有可能的事件序列。一个复杂 DUT 的状态数量可能是天文数字。有没有更好的方法?我们能否证明 DUT 在所有可能的条件下都是正确的?

这就把我们带到了​​形式验证 (formal verification)​​ 的美妙世界。我们不再为木偶编写剧本,而是为它的宇宙编写物理定律。使用像 SystemVerilog Assertions 这样的语言,我们可以陈述必须始终成立的永恒属性。对于一个半加器,我们可以断言这个属性:“在每一个时钟上升沿,carry 输出必须等于 a 和 b 输入的逻辑与。” 这不是针对某个特定输入的测试,而是一条普适定律。

现在,想象一个微妙的错误潜入了我们的 DUT:进位逻辑有一个意外的一周期延迟。时间 ttt 的 carry 输出实际上反映了时间 t−1t-1t−1 的输入。一个标准的测试可能会错过这一点。但是一个形式验证工具,有了我们的普适定律,将会在数学上探索状态空间并找到一个反例。它会报告:“我发现了一个案例!如果 a 和 b 在上一个周期是 0,而在这个周期是 1,那么你的属性 (a b) == carry 就失败了,因为 1 1 是 1,但进位输出仍然是 0。” 该工具以数学的确定性检测到了这个错误。

这种对 DUT 拥有深刻、穿透性洞察力的想法,从抽象的设计世界延伸到了具体的物理硬件世界。一块现代印刷电路板 (PCB) 是一个繁忙的芯片之城。当我们的 DUT 被焊接在上面,周围环绕着几十个其他芯片时,我们如何测试这一个特定的芯片?

答案是一项名为 ​​JTAG/边界扫描 (Boundary Scan)​​ 标准的工程奇迹。它就像在每个芯片内部构建了一个秘密的地铁系统。芯片的每个引脚都配备了一个微小的“扫描单元”,这些单元可以被电子方式连接成一个长链,即“扫描链”。我们可以将测试数据一位一位地移入这个链条,直到我们的 DUT 的输入被设置为我们想要的任何值。我们让 DUT 执行一个时钟周期的功能,将其输出捕获到扫描单元中,然后将整个链条的内容移出以读取结果。我们实际上创建了一套虚拟探针,可以将我们的 DUT 与其邻居隔离开来。

为了使这个过程高效,该标准包含了一些巧妙的指令。如果我们有一个很长的芯片链,但只想测试其中一个,我们可以告诉所有其他芯片进入 BYPASS 模式。在这种模式下,它们对扫描链的贡献从数百位缩短到仅一位。我们的测试路径总长度急剧缩短,从大约 LDUT+(N−1)LotherL_{DUT}+(N-1)L_{other}LDUT​+(N−1)Lother​ 减少到仅 LDUT+N−1L_{DUT}+N-1LDUT​+N−1,从而大大减少了测试时间和成本。这个测试系统的设计本身就是一段优美的逻辑,一个有限状态机,其结构经过巧妙设计,使得将一个引脚保持高电平五个时钟周期,就能以数学的确定性重置链中每个芯片的测试逻辑,无论它之前处于什么状态。这为任何测试提供了一个有保证的、可靠的起点。

耳语与轰鸣:表征模拟世界

现在让我们离开 1 和 0 的二进制世界,进入连续、嘈杂的模拟电子领域。在这里,我们的 DUT 可能是一个 MOSFET 晶体管,我们的目标不是检查其逻辑,而是测量其一个微妙的物理特性,比如其固有的​​闪烁噪声 (flicker noise)​​。这种噪声就像是流经器件的载流子的量子力学运动所产生的微弱、随机的“耳语”。

要听到这种耳语,我们需要一个非常灵敏的麦克风——一个低噪声前置放大器。但问题在于:前置放大器本身也是一个电子电路,它也有自己的噪声。它也在耳语!我们链末端的频谱分析仪听到的是两种耳语的总和:Stotal(f)=SDUT(f)+Spreamp(f)S_{total}(f) = S_{DUT}(f) + S_{preamp}(f)Stotal​(f)=SDUT​(f)+Spreamp​(f)。如果我们的前置放大器太吵,它将完全淹没我们 DUT 的信号。我们的测量就变成了对我们工具的测量,而不是对器件的测量。

因此,模拟测量的艺术在于设计一个测试环境,使其自身的不完美之处与我们希望测量的效应相比可以忽略不计。例如,我们可能规定,在我们的目标频率 20 Hz20 \text{ Hz}20 Hz 下,我们前置放大器的噪声功率不得超过 DUT 噪声功率的 4%。这个约束对我们前置放大器可接受的闪烁噪声系数施加了严格的上限,迫使我们构建一个足够安静的测量系统,以听到 DUT 的耳语。

机器中的幽灵:去嵌的艺术

在高频和精密测量中,DUT 与测试环境之间的界线变得更加模糊。将探针连接到硅片上器件的这一行为本身就引入了寄生效应。金属探针焊盘对下方的衬底有电容,而通向 DUT 的微小走线有电阻和电感。这些都不是 DUT 的一部分,但它们是测量中不可避免的一部分。它们就像机器中的幽灵,“误差盒”或“夹具”,破坏了我们对真实 DUT 的观察。

​​去嵌 (De-embedding)​​ 是一种强大而优雅的艺术,可以在数学上驱除这些幽灵。

一种常见的技术是​​开路-短路 (Open-Short) 法​​。我们首先测量一个缺少 DUT 的伪结构——一个“开路”电路。这个测量主要告诉我们关于并联寄生元件的信息,比如焊盘到地的电容。然后,我们测量第二个伪结构,其中 DUT 被一个近乎完美的“短路”电路取代。这个测量,在我们减去已知的并联效应后,告诉我们关于串联寄生元件的信息,比如走线电阻和电感。在表征了我们夹具的完整电气模型后,我们可以将它们表示为一个矩阵。然后我们可以测量我们实际的 DUT(它被这些相同的夹具包围),并使用矩阵代数从总测量中“除掉”或去级联 (de-cascade) 夹具矩阵,最终得到 DUT 本身的原始矩阵。

这种基于矩阵的方法非常强大。在 ​​Thru-Reflect-Line (TRL)​​ 方法中,我们甚至不需要明确知道夹具的误差矩阵。想象一下,我们 DUT 的测量是一个矩阵乘积 MDUT=EleftNDUTErightM_{DUT} = E_{left} N_{DUT} E_{right}MDUT​=Eleft​NDUT​Eright​,其中 NDUTN_{DUT}NDUT​ 是真实的 DUT 矩阵,而 EleftE_{left}Eleft​ 和 ErightE_{right}Eright​ 是左、右夹具的未知误差矩阵。似乎无法解出 NDUTN_{DUT}NDUT​。但通过对已知的标准进行一些其他巧妙的测量——比如直接的“直通”(Thru) 连接 (NThru=IN_{Thru} = INThru​=I)——我们可以构建一个矩阵,它是真实 DUT 矩阵的相似变换 (例如,S=EleftNDUTEleft−1S = E_{left} N_{DUT} E_{left}^{-1}S=Eleft​NDUT​Eleft−1​)。线性代数的一个基本定理告诉我们,相似矩阵具有相同的特征值。物理器件矩阵的特征值与其最基本的属性(如传播常数)直接相关。通过计算我们构建的矩阵 SSS 的特征值,我们可以推断出真实 DUT NDUTN_{DUT}NDUT​ 的属性,而根本不需要知道误差矩阵 EEE!这些幽灵仿佛魔术般地从方程中消失了。

一种完全不同但同样优美的方法来自信号处理领域。如果我们将一个非常短的电脉冲送入我们的测量装置,我们可以观察其在时间上的反射。首先,我们会看到来自输入连接器的反射。稍后,是来自 DUT 本身的反射。最后,是来自输出连接器的反射。这就是​​时域 (time-domain)​​ 视图。如果这些反射在时间上足够分离,我们可以简单地在 DUT 响应周围的时间里打开一个“门”或窗口,并忽略该窗口之外发生的事情。通过傅里叶变换将这个门控信号转换回频域,我们就能得到 DUT 响应的估计值,而没有夹具效应的干扰。

当然,现实从不那么干净。由于我们仪器的有限带宽,我们的“脉冲”永远不是无限短的,它在时间上的表示有旁瓣,可能导致不同反射之间的泄漏。这迫使我们做出复杂的选择。一个尖锐的矩形时间门能提供良好的时间分辨率,但可能在频域中产生波纹。一个更平滑、锥形的门(如汉宁窗 Hann window)以牺牲时间特征的模糊性为代价来减少波纹。这种权衡是傅里叶变换不确定性原理的直接结果。去嵌的艺术变成了一门加窗和信号处理的艺术,是测量科学与应用数学之间的深刻联系。

从数字木偶戏到傅里叶变换的频谱分析,理解待测器件的旅程本身就是科学探索的一个缩影。它提醒我们,每一次观察都是观察者与被观察者之间的一种关系,而真正的理解需要有将两者区分开来的智慧。