第五篇:进阶篇(下)------ 基于时钟的时序提取
系列:《VCDSTIL 实战:从仿真波形到 ATE 测试向量》第 5 篇(共 5 篇)
前言
前四篇覆盖了 VCDSTIL 的核心工作流:自动提取、手动强制、条件选择。本篇介绍系列中最"聪明"的一种时序模式------基于时钟的时序提取(Clock-Based Timing)。
注意 :Clock-Based Timing 目前仅在 GUI 模式下可用,CLI 暂不支持。
为什么需要 Clock-Based Timing?
先回顾一下自动提取的本质:VCDSTIL 记录 VCD 中信号实际发生跳变的时刻,并将这些时刻翻译为 STIL 波形。
这对时钟信号本身是合适的------时钟本来就是事件驱动的,它在特定时刻跳变。
但对于被时钟采样的数据信号,情况不同。以一个同步设计为例:
CLK ___↑‾‾‾↑___↑‾‾‾↑___↑‾‾‾
D ─────[ DATA_A ]─────[DATA_B]──
在真实电路中,D 在时钟上升沿之前就必须稳定(满足建立时间 tsu)。在 VCD 中,D 的跳变时刻是精确的仿真时刻,可能是 10.3ns、410.7ns......每个周期的偏移量都略有不同。
自动提取会为这些不同的偏移量分别生成波形,结果可能是几十个"大同小异"的波形。而实际上,从测试工程的角度来看,我们只关心一件事:在时钟边沿附近,数据是否稳定正确。
Clock-Based Timing 正是基于这一思路:以时钟边沿为基准,定义所有同步信号的驱动和采样时间点,而不是从 VCD 中逐字翻译。
两种时序方法对比
| 维度 | 自动提取 | Clock-Based Timing |
|---|---|---|
| 时序基准 | VCD 中信号的实际跳变时刻 | 指定时钟的边沿 |
| 波形数量 | 可能很多(异步情况下尤为明显) | 每个信号每个方向仅一个 |
| 与 VCD 的关系 | 严格反映 VCD | 从 VCD 读取数据值,但忽略时刻 |
| 正确性保证 | 工具自动验证 | 用户负责定义正确的采样点 |
| 结果整洁度 | 视 VCD 而定 | 极为整洁,工程师友好 |
| 适用信号 | 所有信号 | 同步信号(时钟和异步信号仍用自动提取) |
核心权衡 :Clock-Based Timing 生成的 STIL 更整洁、更符合工程直觉,但用户需要自己保证采样点定义正确------工具不会验证定义的时序是否与实际 VCD 波形相符。
关键概念:tcyc
在 Clock-Based Timing 中,你会频繁看到 tcyc 这个变量。它代表测试周期宽度 (即 cycle_width),在本例中为 400ns。
使用 tcyc 而非硬编码具体数值,可以让时序定义具有可移植性 ------如果以后测试速率改变,只需修改 cycle_width,所有相对时序自动更新。
常见的 tcyc 表达式:
| 表达式 | 含义(基于 400ns 周期) |
|---|---|
0*tcyc |
周期起点,0 ns |
0.9*tcyc |
周期的 90% 处,360 ns |
0.5*tcyc |
半周期,200 ns |
配置 Clocks.csv
在 GUI 的 CONFIGURE 界面,加载 setup_clock.py 后,点击 Import Timing ,在导入对话框中勾选 Enable Clock Based Timing Generation ,然后点击 Edit 编辑 Clocks.csv。
Clocks.csv 结构
Clocks.csv 的列定义如下:
| 列名 | 说明 |
|---|---|
| Pin Name | 信号名(或特殊关键字 <*DESCRIPTI ON*>) |
| Clock Name | 该信号所属的时钟域(使用哪个时钟的边沿来定义时序) |
| Input Sampling Edge | 用于确定输入(驱动)时序的时钟边沿(Rising / Falling) |
| Output Sampling Edge | 用于确定输出(采样)时序的时钟边沿(Rising / Falling,可加偏移) |
| ATE Input Timing | 在 STIL 中,信号驱动(Drive)的时间点 |
| ATE Output Timing | 在 STIL 中,信号采样(Compare)的时间点 |
配置示例
基于以下设计意图:
- 所有同步信号(A0、A1、CS_、D0、D1......WR_)以 CLK0 为时钟
- 驱动时机:CLK0 上升沿之后 10 ns (
ATE Input Timing = 10ns) - 采样时机:CLK0 下降沿之后 50 ns (
Output Sampling Edge = Falling+50ns,ATE Output Timing = 0.9*tcyc)
填写后的 Clocks.csv 如下:
| Pin Name | Clock Name | Input Sampling Edge | Output Sampling Edge | ATE Input Timing | ATE Output Timing |
|---|---|---|---|---|---|
| A0 | CLK0 | Rising | Falling+50ns | 10ns | 0.9*tcyc |
| A1 | CLK0 | Rising | Falling+50ns | 10ns | 0.9*tcyc |
| CS_ | CLK0 | Rising | Falling+50ns | 10ns | 0.9*tcyc |
| D0 | CLK0 | Rising | Falling+50ns | 10ns | 0.9*tcyc |
| D1 | CLK0 | Rising | Falling+50ns | 10ns | 0.9*tcyc |
| ... | CLK0 | Rising | Falling+50ns | 10ns | 0.9*tcyc |
| WR_ | CLK0 | Rising | Falling+50ns | 10ns | 0.9*tcyc |
时钟信号本身(CLK0、CLK1、CLK2)和异步信号不在 Clocks.csv 中定义,它们会通过自动提取处理。
特殊示例行
Clocks.csv 中还有一个示例行,演示高级用法:
| Pin Name | Clock Name | Input Sampling Edge | Output Sampling Edge | ATE Input Timing | ATE Output Timing |
|---|---|---|---|---|---|
| > SIG1 | CLK1 | Rising | Falling+2ns | 10ns | 15ns |
这行展示了如果某个信号属于不同时钟域(CLK1 而非 CLK0),可以单独为它指定不同的时钟和时序参数。
理解生成的 timing.csv
点击 Import 导入后,可以通过 Edit 查看生成的 timing.csv。对 CLK0 和 D0 的部分如下:
| Pin | WFC | Waveform | Condition |
|---|---|---|---|
| CLK0 | D | 0ns:D; 150ns:U |
waveform |
| D0 | 10ns:F(pos@CLK0) |
true | |
| D0 | 0*tcyc:Z; 0.9*tcyc:R(neg@CLK0+50ns) |
true | |
| D0 | 10ns:F |
true | |
| D0 | 0*tcyc:Z; 0.9*tcyc:R |
true | |
| D0 | 0*tcyc:Z; 0.9*tcyc:X |
true |
关键点解读:
CLK0 本身 :使用自动提取(Condition = waveform),忠实反映 VCD 中的时钟跳变时刻。
D0 的输入波形:
10ns:F(pos@CLK0)
表示"在 CLK0 上升沿(pos@CLK0)确认后,于 10ns 时驱动 D0 的值"。括号内的时钟边沿引用是工具内部的同步参考,确保驱动时序与时钟边沿正确对齐。
D0 的输出波形:
0*tcyc:Z; 0.9*tcyc:R(neg@CLK0+50ns)
分解为两个事件:
0*tcyc:Z:周期起点(0 ns),D0 进入高阻态 Z(关闭驱动,准备采样)0.9*tcyc:R(neg@CLK0+50ns):在0.9×400ns = 360 ns处采样(以 CLK0 下降沿后 50 ns 为同步参考)
降级波形(fallback):
不含时钟边沿引用的行(如 10ns:F 和 0*tcyc:Z; 0.9*tcyc:R)是当信号不在当前仿真周期内发生跳变时的降级处理,确保每种情况都有对应波形。
生成 STIL
编辑完 Clocks.csv 并导入后,进入 CONVERT 界面,点击 Run 生成 STIL。
生成的 STIL 波形
stil
"CLK0" {
D { '0ns' D; '150ns' U; } ← 自动提取,与 VCD 一致
}
"D0" {
X { '0*400ns' Z; '0.9*400ns' X; } ← 不关心(周期起点高阻,0.9处X)
D { '10ns' D; } ← 驱动低,10ns 有效
U { '10ns' U; } ← 驱动高,10ns 有效
T { '0*400ns' Z; '0.9*400ns' T; } ← 采样,周期起点高阻,0.9处比较
L { '0*400ns' Z; '0.9*400ns' L; } ← 采样低
H { '0*400ns' Z; '0.9*400ns' H; } ← 采样高
}
与自动提取的结果对比:
| 方面 | 自动提取 | Clock-Based |
|---|---|---|
| D0 的波形数量 | 可能 10+ 个 | 固定 6 个 |
| 驱动时间点 | 各周期不同 | 统一 10 ns |
| 采样时间点 | 各周期不同 | 统一 0.9×tcyc = 360 ns |
| 对 VCD 时序的依赖 | 强 | 仅依赖逻辑值,不依赖时刻 |
使用注意事项
1. 仅 GUI 可用
Clock-Based Timing 目前不支持通过 CLI 直接配置,需要使用 GUI 的导入对话框启用。如需在 CLI 中使用,可以先通过 GUI 生成 timing.csv,再在 CLI 流程中使用该文件。
2. 时钟信号和异步信号不能使用 Clock-Based Timing
时钟信号本身的时序必须通过自动提取来处理(它们就是时序的基准);纯异步信号的跳变时刻与时钟无关,也必须用自动提取。只有同步信号适合 Clock-Based Timing。
3. 用户负责保证采样点正确性
工具不会检查你定义的 ATE Input/Output Timing 是否满足 DUT 的建立/保持时间要求。用户需要结合 DUT 规格书和仿真波形,确认所选的驱动和采样时间点在工程上是合理的。
4. tcyc 表达式的计算
运行时,tcyc 会被实际的 cycle_width 值替换:
0*tcyc → 0 × 400ns = 0 ns
0.9*tcyc → 0.9 × 400ns = 360 ns
整个系列的知识体系回顾
至此,整个 VCDSTIL 系列教程已完整介绍。以下是全系列知识点的结构图:
VCDSTIL 知识体系
│
├── 基础概念
│ ├── VCD(事件驱动)vs STIL(周期驱动)
│ ├── 三种工作模式:gen_pins / gen_timing / 默认
│ └── 关键参数:cycle_width、start_time
│
├── 操作方式
│ ├── GUI 模式(直观,适合探索)
│ └── CLI 模式(可脚本化,适合自动化)
│
└── 时序定义方式(从简单到灵活)
│
├── 自动提取(Condition = waveform)
│ └── 从 VCD 事件逐字翻译,严格一致
│
├── 强制波形(Condition = true)
│ ├── 特殊符号:F(输入占位)、R(输出占位)、S(通用)
│ └── 统一替换某信号的所有周期波形
│
├── 条件波形(Condition = 信号==值@时间)
│ ├── 语法:信号=='值'@(t0) / AND / OR
│ └── 按周期动态选择波形
│
└── Clock-Based Timing(仅 GUI)
├── 以时钟边沿为基准定义驱动/采样时机
├── 配置文件:Clocks.csv
├── 关键变量:tcyc(周期宽度)
└── 结果:每个信号每个方向仅一个波形,极为整洁
小结
Clock-Based Timing 是 VCDSTIL 中最接近"工程意图"的时序定义方式。它不问"VCD 中信号在什么时刻跳变",而是问"这个信号应该在时钟的哪个边沿被驱动/采样"。
何时选用 Clock-Based Timing:
- DUT 是同步设计,数据信号由时钟采样
- 仿真是异步事件驱动的,自动提取会产生大量波形
- 需要生成整洁、标准的 STIL 供团队共享或存档
何时不适用:
- 信号本身是时钟或异步信号
- 无法确定正确的采样点(风险由用户承担)
- 需要 CLI 自动化(目前仅 GUI 支持)
至此,《VCDSTIL 实战:从仿真波形到 ATE 测试向量》系列全部完结。希望这五篇文章能帮助你系统掌握 VCDSTIL 的使用,从基础的 VCD 转换到高级的时序控制,覆盖实际工程中遇到的各种场景。
上一篇 :[第四篇:进阶篇(上)------ 用户自定义波形与条件波形](#第四篇:进阶篇(上)—— 用户自定义波形与条件波形)
系列完结《VCDSTIL 实战:从仿真波形到 ATE 测试向量》共 5 篇