DFT 中的 On-Chip Clock Controller (OCC) 架构设计
OCC 简介与背景
OCC(On-Chip-Clock Controller)的全称是片上时钟控制器,主要作用是在结构性测试的 At-Speed Delay 测试中管理时钟。在 atspd 测试中,需要精准产生两个 at-speed clock cycles 来完成 Launch 和 Capture 的过程。然而,PLL 产生的时钟是一直运行(Free-Running)的,且 ATE 无法直接提供测试所需的高速时钟。因此,需要一个模块来对测试过程中的时钟进行控制,OCC 就是为了解决这个问题而设计的。
关于 Scan Test 过程的一些补充说明:
- Shift:ATE 提供 Test Clock,shift in 数据的同时对比 shift out 的数据。
- Dummy Cycles:SE 驱动所有寄存器时负载非常大,transition 时间长,且 shift 过程 Toggle 高可能导致芯片电压降低。因此在 AC 测试中,shift 完成后需等待一段时间让芯片电压恢复。
- Force PI & Memory PO:对于 Full Scan 设计,所有 IO PAD 都被当做 Scan in/Scan out(Wrapper Cores),此时不需要此过程,但 ATPG Pattern 默认会有这两个 cycles。
OCC 基本设计与优化
插入 OCC 后,Design 中的时钟结构会发生变化,所有 regs 的时钟都来自 OCC 的输出端口。设计一个 OCC 需要考虑以下几点:
- 正常工作模式:regs 需要一直使用 func clk,因此 OCC 应有一个 Test Mode 端口。当 Test Mode = 0(即正常工作模式),OCC 的 clk out 端口上的时钟和 func clk 完全相同。
- 测试模式切换:在测试模式下,Shift 阶段使用慢速时钟,AC Capture 阶段使用快速时钟。clk 切换的时间是在 scan_en 由高拉低之后,可以利用 scan_en 来控制 clk 的切换过程。
- 延时处理:scan_en 拉低之后,并不是立刻就要用到 fast clock,两者之间有一定的延时,这一点可以用移位寄存器来实现。
基础方案示例
基于 N bits 移位寄存器的 OCC 基本结构中,MUX C 用于选择 Func Clock 或 Test Clock。当 Test Mode = 0 时,芯片工作在 Func Mode,OCC 处于 Bypass Mode,对 Func 模式透明。当 Test Mode = 1 时,芯片进入 DFT 测试模式:
- Shift Enable = 1 时,MUX B 选中 Scan Clock,OCC 输出低速时钟,完成 Shift 过程,同时 0 被保存到移位寄存器中。
- Shift 完成后,Shift Enable = 0,芯片进入 Capture Mode。移位寄存器 Q0 - Qn 开始被 Shift 1。
- 移位寄存器最后三级的输出值经过组合逻辑连接到 ICG 的 E 端口,移位寄存器的长度决定了等待时间。
- 当 At-Speed Mode = 0(DC 测试),MUX A 选中 0,特定条件下 MUX 输出 1,ICG 打开,OCC 输出一个 Capture Clock Pulse。
- 当 At-Speed Mode = 1(AC 测试),MUX A 选中 1,ICG 打开可产生两个 Capture Clock Pulses。
优化方案
基础方案存在风险:Capture Clock Cycles 和 scan_en 之间的时间间隔取决于移位寄存器的级数,设计完成后无法动态调整;scan_en 负载大,切换时间可能超过间隔导致测试失败;scan_en 直接连接移位寄存器可能引入不定态。
优化后的 OCC 在 scan_en 上增加了一级由 slow clock 驱动的 sen_retiming 寄存器。这样虽然 slow clock cycles 和 Launch/Capture Clock Cycles 之间的时间是固定的,但 scan_en 和 slow clock cycles 之前的时间间隔可以通过 ATE 动态调整,进而实现 Launch/Capture Clock Cycles 到来时间的动态调整。分析该 OCC 的工作过程:
- scan_en = 1 时,所有寄存器被 shift 1。
- shift 结束后,slow clock 关闭,CDC 和 sen_sync 等寄存器值不更新,待 scan_en 稳定后给 slow clock cycles,scan_en 的 0 会被 shift 到其他寄存器中。
- 当两级寄存器值为 11 时,launch_en 使能,ICG 打开,提供 Launch Clock Cycles。
- 当两级寄存器值为 01 时,capture_en 使能,ICG 打开,提供 Capture Clock Cycles。
Synopsys OCC 实现
使用 Synopsys 工具实现 Scan 时,OCC 插入前后的电路结构会有所不同。OCC 的基本结构包含 test_se(对应 scan_en)和 ate_clk(对应 slow_clock)。不同工作模式下的时钟通路如下:
- Func Mode:正常功能模式,时钟通路不受干扰。
- Shift Mode:扫描链移位模式。
- Slow Capture Mode:慢速捕获模式。
- Fast Capture Mode:高速捕获模式。test_se = 1 时 Clock Chain 被 shift 1;test_se = 0 时,待 test_en 稳定后给 ate_clk cycles 向 Clock Chain 中 shift 一个 0。Clock Chain 中的值和 PLL cycles counter 的输出共同决定 pll_en 是否有效,因此 capture cycles 出现的时间是动态可调的。
Synopsys 的 OCC 主要分为三部分:
- Clock Chain / Clock Pulse Generator:Clock chain 是 Scan Chain 的一部分,其值可通过 ATPG Pattern 控制。Pulse Generator 对 Clock Chain 进行'翻译',决定输出几个 clock enable 信号或关停 clock。
- Clock Gating Cell:利用 pulse generator 的输出 gating 相应的 clock,去除毛刺和亚稳态。CGC 中的 LAT 是负沿触发,AND2 是正沿触发,半个 clock cycles 的等待足以让信号稳定。
- Scan Enable Sync Cell:避免由 shift 到 fast capture 的切换过程中 clock 产生亚稳态。
基于 Synopsys OCC,Fast Capture Mode 下对应的时序图中,3 Sync Cycles 对应于消除亚稳态的 3 级 Scan Enable Sync Cell。第四个 Cycles 时计数器值为 0,不能产生 Clock Pulse。Count = 1, 2, 3 时需满足 Clock Chain 中的值是 011,这可通过 ATPG Pattern 实现。
OCC 插入规则
OCC 可以直接在 RTL 阶段(前端设计过程中)插入,也可以在 DFT Flow 中插入。OCC 的插入并非随意,需满足以下基本原则:
- External Clock 可以不插 OCC(从 PAD 灌入的 Clock 可从外部控制),Internal Clock 必须要插 OCC。
- OCC 需要放到 Clock Source 和待测寄存器之间。
- OCC 的输入时钟必须是 free-running 的。
- OCC 不能级联。
结合具体实例,看看如何在不同的 Design 中插入 OCC(假设所有 FF 都是 core scan cells,暂不考虑 wrapper cells):
场景一:Free-Running Clock
OCC 的输入时钟必须是 free-running 的。当 design 中 scan cells 的 clock 存在分频的时候,OCC 需要插入到 divider 的后面。如果错误地插入在 divider 前面,驱动 divider 的 clock 已经被 OCC 执行过 chopping 动作,不再是 free-running 的 clock,无法得到预期的 clock。例如 transition 测试需要两个 clock pulse,在 fast-capture mode 下,divider 可以得到两个 clock pulse,但经过 divider 后就只剩下一个,显然不能满足后续 FF 的需求。
场景二:带 Wrapper Cores 的分层设计
Top 层的 design_A 包含 core_A,且 core_A 做了 wrapper chains,能够单独测试。因此,在 core_A 的 internal mode 下,为了测试内部逻辑,core_A 内部需要插 OCC;在其 external mode 下(只考虑做一层 wrapper,此时对顶层是 internal mode),还需要测试顶层逻辑,因此顶层也需要一个 OCC。虽然有两个 OCC,但无论何时只有一个在工作,保证了通路上 OCC 没有级联,且所有 FF 的时钟都由 OCC 控制。
场景三:不带 Wrapper Cores 的分层设计
design_B 与 design_A 类似,区别是内部的 core_B 没有做 wrapper chains。core_B 不需要单独测试,它和 top 一起进行测试,core_B 的内部不需要插入 OCC。测试时无论是顶层的 FF1 还是 core_B 内部的 FF2,其时钟都由顶层的 OCC 来控制。如果 core_B 内部插了 OCC,因为没有做 wrapper,无法与顶层隔离开,FF2 前面将会有两个 OCC,导致 OCC 级联,不符合规则,在 OCC insertion 这一步会有 DRC 报错。
场景四:带 Wrapper Cores 和 Divider 的分层设计
core_C 做了 wrapper chains,并且还有 divider。要实现 Scan 测试,所有的 FF 的时钟都必须由 OCC 进行控制。一般情况下,在 block-level 中,会在每个 clock port 的后面直接插入一个 OCC。但是 core_C 中存在 divider,结合前述示例,core_C 中 OCC 的插入方法需注意:FF2 和 FF4 的 clock 找不到一个公共点来进行 OCC 的插入,此时可以和前端沟通,让他们插入一个定位作用的 Buffer。
Wrapper Cell Driven by Divider
在 Wrapper Core 中,Scan Cell 分为 Regular Cell 和 Wrapper Cell。Regular Cell 在 Internal Mode 工作,Wrapper Cell 在 External Mode 工作。如果 FF3 是 Wrapper Cell,它在 External Mode 下工作,此时顶层的 OCC1 工作,core 内部的 OCC3 不工作。这时 FF3 拿到的 Capture Clock 就会出现问题,因为顶层的 OCC1 工作后会放下来一个 chopping 过的 clock,再经过 divider,AC Capture 的时候两个 Clock Pulse 就变成一个,使得 FF3 无法测试。因此,对于 Core 内有 Divider 的模块,假如 Divider 后面驱动了 Wrapper cell,需要特殊处理,最简单的方法就是这部分逻辑不做 Wrapper Cell。假如工具把 FF3 分析为了 Wrapper Cell,就需要把相对应的 Port Exclude 掉,使得 FF3 变成 Regular Cell 即可。
场景五:不带 Wrapper Cores 但有 Divider 的分层设计
design_D 与 design_C 类似,区别是内部的 core_D 不做 wrapper。对于内部 core 不做 wrapper 的情况,core 内不用插 OCC,但对于 design_D 来说行不通,因为 core 内还有个 Divider。假如 core_D 内部不插入 OCC 并且不做 wrapper,Core 和顶层一起测试,Core 内的 FF 的测试时钟都由 OCC1 来控制。这对于 FF2 和 FF4 没什么问题,但对于 FF3 又会出现 AC Capture Clock 只有一个 Clock Pulse 的情况,导致其无法测试。因此,不管做不做 Wrapper,Core 内部只要有 Divider,Divider 后面就要插 OCC,否则 Divider 后面的逻辑将不可测。解决这个问题的办法是给 Divider 这一路单独做分支,从顶层开始做,并给 core_D 增加个 port(如果这路时钟仅仅只是驱动了 core_D,在顶层没有驱动其他逻辑,也可以不新增 port,把 OCC1 和分支做在 core 内部)。
总结
基于上述示例,对 OCC 的插入位置做一个简单总结:
- 内部时钟必须插 OCC,外部时钟可选。
- OCC 置于 Clock Source 和待测寄存器之间。
- 输入时钟必须是 free-running。
- 严禁 OCC 级联。
- 涉及 Divider 时,需在 Divider 后插入 OCC,注意 Wrapper Cell 的处理以避免 Clock Pulse 丢失。
