第七篇官方示例工程详解

本篇逐章解析 JasperGold 安装目录中 example_jaspergold_apps/ 的所有官方示例工程, 覆盖每个示例的验证目标、RTL 设计结构、Tcl 脚本逐行解读、完整验证流程(Setup → 约束 → 引擎选择 → 证明 → 结果分析)、运行命令和 GUI 操作指引。

如何使用本章

本章详解每个官方示例的验证思路,而不仅是 Tcl 命令的翻译。阅读时重点关注:

建议学习方法:读每个示例时先自己想"如果是我来验证这个设计,我会怎么做",再对比示例的方法,思考差异和原因。

0. 示例总览与 Designs 目录

JasperGold 安装目录中提供了一套完整的官方示例工程(example_jaspergold_apps/),覆盖所有 App 的典型使用场景。本章对每个示例进行逐行 Tcl 解读和完整验证流程讲解,帮助读者从"能跑"到"理解为什么这么跑"。

Designs 目录结构

所有示例共享 designs/ 目录下的 RTL 资源:

通用运行格式

jg -<app> <script.tcl> -proj <project_dir>

JasperGold 启动后会在 -proj 指定的目录中创建 jgproject/ 数据库目录,包含编译信息、证明结果和波形数据库。不指定 -proj 时默认在当前目录创建。

所有示例的 Tcl 脚本都假设从 example_jaspergold_apps/<APP>/ 目录下运行,RTL 路径使用 ../designs/ 相对路径。

1. FPV 形式属性验证示例

1.1 示例概述

FPV(Formal Property Verification)是 JasperGold 最核心的 App,用于验证设计是否满足 SVA/PSL 断言描述的属性。官方提供 4 个脚本,分别演示 Verilog+SVA、VHDL+SVA、VHDL+PSL 和混合语言四种启动方式,核心验证逻辑相同。

验证目标:验证 SoC 互联结构中仲裁器(arbiter)、桥接器(bridge)、输入端口(ingress)、输出端口(egress)和端口选择器(port_select)的协议正确性。

RTL 模块组成(reference_design/verilog_sva/source/design/)

  • arbiter.v — 4 路请求仲裁器,使用 one-hot 授权
  • port_select.v — 端口选择逻辑
  • bridge.v — FIFO 桥接模块,含读写指针
  • ingress.v — 4 个输入端口(ing0-ing3)
  • egress.v — 输出端口模块
  • top.v — 顶层集成模块

1.2 Tcl 脚本逐行解读

FPV_verilog_sva_example.tcl 为例:

# 设置路径变量
set ROOT_PATH ../designs/reference_design/verilog_sva
set RTL_PATH ${ROOT_PATH}/source/design
set PROP_PATH ${ROOT_PATH}/source/properties

# 分析 RTL 设计文件(Verilog 格式)
analyze -verilog \
  ${RTL_PATH}/arbiter.v \
  ${RTL_PATH}/port_select.v \
  ${RTL_PATH}/bridge.v \
  ${RTL_PATH}/egress.v \
  ${RTL_PATH}/ingress.v \
  ${RTL_PATH}/top.v

# 分析 SVA 属性文件
analyze -sva \
  ${PROP_PATH}/bindings.sva \
  ${PROP_PATH}/v_arbiter.sva \
  ${PROP_PATH}/v_bridge.sva \
  ${PROP_PATH}/v_ingress.sva \
  ${PROP_PATH}/v_egress.sva \
  ${PROP_PATH}/v_port_select.sva

# Elaborate:展开设计层次、连接属性、建立形式模型
elaborate -top top

# 声明时钟和复位
clock clk
reset ~rstN

# 获取设计复杂度信息(状态空间、信号数量等)
get_design_info

# ---- 第一轮证明:快速浅层验证 ----
set_max_trace_length 10
prove -all

# ---- 第二轮证明:深度证明 ----
set_max_trace_length 50
set_prove_per_property_time_limit 30s
set_engine_mode {K I N}
prove -all

# 报告结果
report

1.3 验证流程详解

1Setup 阶段 — 分析与建模

analyze -verilog 编译 RTL 源文件,analyze -sva 编译 SVA 属性文件。elaborate -top top 展开设计层次、实例化 bind 指令(将 SVA 绑定到 RTL 模块实例上)、建立形式验证模型。clock clkreset ~rstN 告诉工具主时钟和低有效复位信号。

2约束策略 — SVA 断言作为约束和检查器

bindings.sva 使用 SVA 的 bind 指令将各模块的属性文件绑定到对应的 RTL 实例上。断言类型包括:

  • $onehot0(gnt) — 授权信号最多只有一位为 1(互斥)
  • 授权保持 — 请求撤掉之前授权不能改变
  • cover — 覆盖所有请求/授权组合场景
3引擎选择 — 两轮策略

第一轮:不指定引擎,使用默认引擎模式,set_max_trace_length 10 限制最大追踪长度为 10 个周期。这是快速验证阶段,可以在短时间内发现浅层 bug(深度 ≤ 10 的反例)。

第二轮:设置 set_engine_mode {K I N} 即 K-Induction(K 归纳)、Interpolation(插值)、BMC(有界模型检测)三种引擎组合。追踪长度增加到 50,每个属性最多 30 秒。这是深度证明阶段,用于证明属性的正确性或找到深层反例。

4证明阶段 — prove -all

prove -all 对所有已加载的断言属性进行证明。第一轮快速筛掉浅层问题,第二轮针对剩余属性使用更强的引擎组合深度证明。

5结果分析

所有断言预期结果为 proven,cover 属性全部被击中。如果有失败的断言,在 GUI Property Table 中查看状态,双击打开 Visualize 波形查看反例。

1.4 运行命令

cd example_jaspergold_apps/FPV && jg -fpv FPV_verilog_sva_example.tcl -proj ~/jgproject

其他三种语言版本:

jg -fpv FPV_vhdl_sva_example.tcl -proj ~/jgproject # VHDL + SVA\njg -fpv FPV_vhdl_psl_example.tcl -proj ~/jgproject # VHDL + PSL\njg -fpv FPV_mixed_language_example.tcl -proj ~/jgproject # 混合语言

关键断言解读

FPV 示例中的 SVA 断言展示了形式验证的基本思路:

// 断言1:授权信号始终是 one-hot 或全零(互斥授权)
property grant_is_onehot0;
  @(posedge clk) $onehot0(gnt);
endproperty
a_grant_is_onehot0: assert property (grant_is_onehot0);

// 断言2:授权只持续一个周期
property grant_is_one_cycle;
  @(posedge clk) (gnt!=4'b0) |=> (gnt==4'b0);
endproperty
a_grant_is_one_cycle: assert property (grant_is_one_cycle);

// Cover 点:每个请求端口和授权端口都被覆盖
c_req0: cover property (@(posedge clk) (req[0]));
c_gnt0: cover property (@(posedge clk) (gnt[0]));
注意断言和覆盖点的分工assert 检查"不能发生的事",cover 确认"应该能发生的事"。两者结合确保验证环境既正确又完整。

验证策略解释

两轮证明策略不是随意的,而是经验总结:

常见问题

Q:第一轮就有很多 failed 怎么办?
先修浅层 bug 不要急着跑第二轮。浅层 bug 往往导致大量相关属性 fail,修一个可能解决一片。

Q:cover 属性都不击中怎么办?
说明约束过强,合法的输入场景被挡住了。放松约束或检查约束逻辑。

扩展练习

  1. 去掉第二轮(set_engine_mode {K I N}),只用默认引擎跑,对比结果差异
  2. 在 bridge.v 中故意加入 bug(FIFO 指针溢出不保护),看断言能否捕获
  3. 注释掉 cover 属性,体会约束过强时无法发现的问题

1.5 GUI 操作指引

下图展示了 FPV App 启动后的主界面,左侧为 Design Hierarchy 面板,右侧为 Property Table(属性表),底部为 Console:

FPV App 主界面:Design Hierarchy(左)、Property Table(右)、Console(底)

证明完成后 Property Table 会显示每个属性的状态(绿色 ✓ proven、红色 ✗ failed),底部 Proof Progress 条显示证明进度:

FPV Property Table:绿色勾表示 proven,红色 X 表示 failed,底部为证明进度条

来源文件

  • FPV/FPV_verilog_sva_example.tcl
  • designs/reference_design/verilog_sva/

2. CDC 时钟域交叉验证示例

2.1 示例概述

CDC(Clock Domain Crossing)App 自动识别设计中的跨时钟域路径,验证同步器结构正确性、协议合规性,并通过亚稳态注入(MSI)验证同步器的容错能力。

验证目标:在含 4 个时钟域的多时钟设计中,识别所有跨域路径、验证同步器方案正确、通过结构检查+协议检查+MSI 三级验证确保不存在 CDC 违规。

RTL 模块(cdc_design/,共 20 个文件)

  • ndff_sync.v/ndff.v — 双触发器同步器
  • mux_sync.v — 多路选择器同步器
  • pulse_sync.v — 脉冲同步器
  • handshake.v — 握手同步器
  • afifo.v/fifo1.v — 异步 FIFO
  • fsm.v/sender_fsm.v/receiver_fsm.v — 发送/接收状态机
  • reset_sync.v — 复位同步器
  • interruption_manager.v — 中断管理器
  • counter.v/car.v/control.v — 计数器和控制模块
  • top_level.v — 顶层模块(含 modreg_bank 寄存器堆需黑盒)

2.2 Tcl 脚本关键步骤解读

# 黑盒化寄存器堆(不需要验证其内部)
elaborate -bbox_m modreg_bank

# 声明 4 个时钟域
clock clock_control1
clock clock_control2
clock clock_fsm
clock clock_fsm clock_fsm_aux 2 1  # 分频时钟(2:1)

# 用 clock -rate 将输入端口关联到对应时钟域
clock -rate {en_control clock_control_sel ...} clock_control1
clock -rate {en_fsm proc_int_code ...} clock_fsm
clock -rate counter_en clock_fsm_aux

# 声明复位(3个异步复位,低有效)
reset ~reset_n_control1 ~reset_n_control2 ~reset_n_fsm

# 信号配置:将使能信号设为常量 1
check_cdc -signal_config -add_constant {{en_fsm 1'b1} {en_control 1'b1} ...}
check_cdc -signal_config -add_static {{conv_br1_reg}}

# 设置规则严重级别
check_cdc -check -severity {fatal {no_scheme}}
check_cdc -check -severity {error {cdc_pair_logic sync_chain_logic}}

# 核心 CDC 流程
check_cdc -clock_domain -find          # 查找时钟域
check_cdc -clock_domain -join jg_clock_fsm_aux -into jg_clock_fsm  # 合并分频域
check_cdc -pair -find                  # 查找 CDC 对(跨域路径)
check_cdc -scheme -find                # 查找同步器方案

# 添加用户定义的 FIFO 同步器方案
check_cdc -scheme -add FIFO -map {...}

# 添加豁免(waiver)
check_cdc -waiver -add -filter [...] -comment {Input to be synchronized externally}

# 查找收敛点
check_cdc -group -find

# 验证豁免条件
check_cdc -waiver -generate
check_cdc -waiver -prove

# 协议检查(验证同步器功能正确性)
check_cdc -protocol_check -generate
check_cdc -protocol_check -prove

# 亚稳态注入(MSI)
check_cdc -metastability -inject
check_cdc -metastability -prove

# 生成报告
check_cdc -report pairs -file .../pairs.csv
check_cdc -report violations -file .../violations.csv
check_cdc -report signoff -file .../signoff.csv

2.3 验证流程详解

1Setup — 多时钟域声明

设计包含 4 个时钟域:clock_control1clock_control2clock_fsmclock_fsm_aux(clock_fsm 的 2 分频)。使用 clock -rate 将每个输入端口关联到正确的时钟域,这是 CDC 分析的基础——工具需要知道每个信号属于哪个域才能识别跨域路径。-bbox_m modreg_bank 将寄存器堆黑盒化,因为验证重点是跨域逻辑而非内部寄存器。

2约束 — 信号配置与豁免

check_cdc -signal_config -add_constant 将使能信号约束为常量 1,表示这些使能始终有效,避免工具报告使能信号本身导致的跨域问题。豁免(waiver)机制用于标记已知安全的跨域路径(如在外部已同步的输入信号),条件豁免还可以通过 SVA 表达式描述安全条件。

3引擎选择 — 默认 CDC 引擎

CDC App 内部管理引擎选择。结构检查使用静态分析(无需证明引擎),协议检查和 MSI 使用 BMC + K-Induction 组合。check_cdc -check -severity 设置不同违规类型的严重级别:no_scheme(无同步方案)为 fatal 级别。

4三级证明流程

第一级:Structural(结构检查)— 识别所有跨域路径和同步器结构,报告无同步方案的路径。

第二级:Protocol(协议检查)— 对已识别的同步器生成断言,验证其功能正确性(如双 FF 同步器输出稳定)。

第三级:MSI(Metastability Injection)— 在同步器的第一级 FF 注入亚稳态(X 值),验证亚稳态不会传播到设计其他部分。

5结果分析

检查 violations.csvsignoff.csv 报告。已正确同步的路径无违规,未同步路径报告 violation。在 GUI Violation Tree 中查看违规详情,Schematic+Graph 视图显示跨域路径和同步器位置。

2.4 层级化 CDC(Hierarchical)

CDC/Hierarchical/ 目录包含 bottom-up 层级化验证示例:先用 run_block 验证各个模块级 CDC,' 导出数据库后用 run_hier 在 SoC 级集成验证,避免在扁平化设计上一次性运行 CDC 的性能问题。

为什么 CDC 需要三级验证

Structural → Protocol → MSI 三级不是冗余,是逐层深入:

新手常犯错误:只跑 Structural 就认为 CDC 验证做完了。没有 MSI,你无法确认同步器在亚稳态条件下真的能工作。

CDC App 运行后,Review Violations 面板按严重级别分类显示违规项,Analyze Violations 面板显示详细信息(源/目的时钟域、同步器类型等):

CDC Violation 视图:按类别分组显示 Missing Synchronizer 等违规,右侧显示违规详细信息

CDC Phases 面板显示各阶段(Structural/Functional/Metastability)的检查结果,绿色勾表示通过,红色 X 表示违规,橙色圈表示警告:

CDC Phases 面板:显示 Pairs/Schemes/Convergence/Functional/Metastability 各阶段状态

来源文件

  • CDC/CDC_verilog_example.tcl
  • CDC/Hierarchical/
  • designs/cdc_design/

3. SEC 时序等价检查示例

3.1 示例概述

SEC(Sequential Equivalence Checking)用于证明两个设计(specification 和 implementation)在时序上等价,' 常用于验证 RTL 修改前后行为一致、RTL-to-netlist 等价等场景。

验证目标:验证 UART 16550 兼容核的原始 RTL(spec)与修改后 RTL(imp)时序等价。

设计结构

  • uart_design/verilog_sva/source/design/ — 原始 UART RTL(spec)
  • uart_design/verilog_sva/source/imp_design/ — 修改后的 RTL(imp,含 bug)
  • uart_design/verilog_sva/source/imp_fixed_design/ — 修复后的 RTL(imp_fixed)
  • uart_tfifo — 发送 FIFO 模块,在验证中黑盒化

3.2 Tcl 脚本关键解读

# SEC 设置:指定 spec 和 imp 的顶层、分析选项、展开选项
check_sec -setup -spec_top uart_top \
            -imp_top uart_top \
            -spec_analyze "-sv -f ${SPEC_RTL_PATH}/sec_spec.vfile" \
            -imp_analyze  "-sv -f ${IMP_RTL_PATH}/sec_imp.vfile" \
            -spec_elaborate_opts "-bbox_m uart_tfifo" \
            -imp_elaborate_opts "-bbox_m uart_tfifo"

# 时钟声明
clock wb_clk_i
clock -rate wb_cyc_i wb_clk_i   # 将 Wishbone 接口信号关联到时钟域
clock -rate wb_stb_i wb_clk_i
# ... 其他接口信号

# 复位
reset wb_rst_i

# 自动映射未初始化寄存器的 X 值
check_sec -auto_map_reset_x_values on

# 接口检查:报告 spec 和 imp 之间端口不匹配
check_sec -interface

# 手动映射自动映射未覆盖的地址端口
check_sec -map -spec {wb_adr_i[4:0]} -imp {uart_top_imp.wb_address_i[4:0]} \
  -respect_connections_during_reset -global

# 生成等价性验证环境(创建映射点对和等价检查属性)
check_sec -gen

# 证明
set_prove_time_limit 30s
check_sec -prove

# Signoff
check_sec -signoff

3.3 验证流程详解

1Setup — Spec/Imp 双设计加载

check_sec -setup 是 SEC 特有的设置命令,分别指定 spec 和 imp 的 RTL 文件列表、顶层模块名和展开选项。-bbox_m uart_tfifo 将发送 FIFO 黑盒化(FIFO 内部状态不影响接口等价性验证)。SEC 会将两个设计展开后建立点对点的映射关系。

2约束 — 信号映射

SEC 自动根据名称匹配映射 spec 和 imp 的信号。check_sec -interface 报告无法自动映射的端口。本例中 wb_adr_i[4:0] 在 imp 中被重命名为 wb_address_i[4:0],需要手动 check_sec -mapcheck_sec -auto_map_reset_x_values on 让工具自动处理未初始化寄存器的 X 值差异。

3引擎 — Basic vs Bug-Hunting

默认使用 Basic 策略(标准等价检查引擎组合)。SEC 也提供 Bug-Hunting 策略,专注于快速找到不等价的反例而非全面证明。Proof Cache 机制缓存已证明的等价点,加速后续重跑。

4证明 — check_sec -prove

check_sec -gen 生成等价性验证环境后,check_sec -prove 证明所有映射点对的等价性。30 秒时间限制用于快速演示,实际项目中可能需要更长时间。

5结果对比:原始版 vs 修复版

SEC_verilog_example.tcl(imp 含 bug):预期结果为 failed,在 Property Table 中可查看反例波形,定位导致不等价的 bug。

SEC_verilog_fixed.tcl(imp_fixed 已修复):预期结果为 proven,signoff 时使用 -waive_category x_signals_and_undrivens 豁免 X 值和未驱动信号。

SEC App 的 Signal Browser 面板并排显示 Spec(左)和 Imp(右)的设计层次和信号,Signal Mapping 面板显示自动映射结果:

SEC Signal Mapping 界面:左侧 Spec Design 层次、右侧 Imp Design 层次,右下 Signal Mapping 表显示信号映射对和等价性证明结果

来源文件

  • SEC/SEC_verilog_example.tcl
  • SEC/SEC_verilog_fixed.tcl
  • designs/uart_design/

4. LPV 低功耗验证示例

4.1 示例概述

LPV(Low Power Verification)App 加载 UPF(Unified Power Format)电源意图文件,自动生成电源感知 RTL 和断言,' 验证隔离单元(isolation)、保持寄存器(retention)、电源开关(power switch)连接和功能正确性。

验证目标:验证带 UPF 电源域的设计中,隔离单元/保持寄存器/电源开关的结构连接和电源状态转换行为正确。

4.2 Tcl 脚本解读

# setup 过程在 elaborate 后调用
proc setup {} {
    clock clk
    reset reset
    assert -disable *::*         # 禁用所有自动断言
    cover -disable *::*
    assert -enable "<embedded>::top.efficiency"  # 只使能 efficiency 相关
    assume -env { vdd_net } -name vdd_net_always_on  # vdd 电源常开
}

clear -all
set PATH "../designs/lpv_design"
set_engine_mode {Ht Hp B N}        # 多引擎组合
set_prove_time_limit 100s          # 较长时间限制

analyze -sv {*}[glob $PATH/*.v]
elaborate -clear
elaborate -top top

# 加载 UPF 电源意图
check_lpv -load_upf top.upf

# 自动生成电源感知 RTL
check_lpv -generate_power_design

setup

# ---- 结构检查(10项)----
check_lpv -verify check_iso_clk_all          # 隔离单元时钟
check_lpv -verify check_iso_inputs           # 隔离输入
check_lpv -verify check_iso_outputs          # 隔离输出
check_lpv -verify check_iso_ctrl_rst         # 隔离控制/复位
check_lpv -verify check_iso_connections      # 隔离连接
check_lpv -verify check_ret_connections      # 保持寄存器连接
check_lpv -verify check_iso_default_value    # 隔离默认值
check_lpv -verify check_ret_ctrl_rst         # 保持控制/复位
check_lpv -verify check_power_switch_connections  # 电源开关连接
check_lpv -verify check_power_switch_ctrl_rst     # 电源开关控制/复位

# ---- 功能检查(12项)----
check_lpv -create assert_iso_up_before       # 电源开启前隔离
check_lpv -create assert_iso_supply          # 隔离供电
check_lpv -create assert_iso_up_after        # 电源开启后隔离
check_lpv -create assert_ret_supply_on_save  # save 时保持供电
check_lpv -create assert_ret_supply_on_restore  # restore 时保持供电
check_lpv -create cover_power_switch_ctrl    # 电源开关控制覆盖
# ... 更多功能检查

prove -property <LowPower>::lpv::*

# 查看隔离输出的反例波形
visualize -violation -property <LowPower>::lpv::iso_up_after_iso_output__PD_MEM -new_window

4.3 验证流程

1Setup — UPF 加载与电源感知 RTL 生成

check_lpv -load_upf top.upf 加载 UPF 文件,LPV 解析电源域、隔离规则、保持策略。check_lpv -generate_power_design 自动在 RTL 中插入隔离单元、保持寄存器和电源开关的功能模型,生成电源感知的形式验证模型。setup 过程中 assume vdd_net 约束主电源常开。

2约束 — 选择性使能断言

示例中禁用了所有自动断言后只使能 efficiency 类断言。实际项目中可根据验证需求启用不同类别的自动检查。

3引擎 — {Ht Hp B N} 组合,100s

LPV 检查涉及复杂的电源状态转换,使用 Ht(Heavyweight trace)、Hp(Heavyweight proof)、B(BMC)、N(K-Induction)四引擎组合,100 秒时间限制。

4证明 — 结构+功能两类检查

check_lpv -verify 执行静态结构检查(无需证明引擎,纯结构分析)。check_lpv -create 创建功能断言后,prove -property <LowPower>::lpv::* 证明所有 LPV 属性。

5结果分析

大部分结构检查预期 proven。功能断言如果失败,使用 visualize -violation 查看隔离输出在电源状态转换时的反例波形。

LPV Power Properties Viewer 显示电源域结构和自动生成的电源属性证明结果,绿色勾表示结构检查通过,红色 X 表示功能检查发现反例:

LPV GUI:Power Domain Info(左中)显示电源域层次,Power Properties Viewer(右)显示各 LPV 自动属性的证明结果

来源文件

  • LPV/LPV_verilog_example.tcl
  • LPV/top.upf
  • designs/lpv_design/

5. X-Prop 未知态传播验证示例

5.1 示例概述

X-Propagation 检测 RTL 仿真中因 X 值(未知态)传播导致的乐观性问题——RTL 仿真可能忽略 X 值的影响而通过,' 但门级仿真中 X 值会真实传播导致功能错误。XPROP App 通过形式化方法穷举 X 值的传播路径。

5.2 Tcl 脚本解读

clear -all
check_xprop -init_control 1    # 启用 X 初始化控制模式

# 分析 RTL
set RTL_PATH ../designs/reference_design/verilog_sva/source/design
analyze -verilog \
  ${RTL_PATH}/arbiter.v ${RTL_PATH}/port_select.v ${RTL_PATH}/bridge.v \
  ${RTL_PATH}/egress.v ${RTL_PATH}/ingress.v ${RTL_PATH}/top.v

elaborate -top top
clock clk
reset ~rstN
get_design_info

# 创建三类 X-Prop 属性
check_xprop -create -outputs -no_bit_blast         # 检查输出端口的 X 传播
check_xprop -create -control -no_bit_blast          # 检查控制信号的 X
check_xprop -create -clocks_and_resets -no_bit_blast  # 检查时钟/复位的 X

set_max_trace_length 10
check_xprop -prove -no_decompose -all
report

5.3 验证流程

1Setup — X 初始化控制

check_xprop -init_control 1 启用 X 初始化控制模式,在复位时将寄存器初始化为 X 值。

2三类 X-Prop 属性

-outputs:检查输出端口是否会出现 X 值(X 从内部传播到输出)。
-control:检查控制信号(如 mux 选择、使能端)上的 X 是否导致非确定性行为。
-clocks_and_resets:检查时钟和复位信号上的 X。
-no_bit_blast 不展开位向量,加速验证。

3证明 — BMC 模式

set_max_trace_length 10 + check_xprop -prove -no_decompose -all,使用 BMC 在 10 周期深度内穷举 X 传播。

4结果分析

报告哪些信号上的 X 会传播到输出,指示 RTL 仿真可能漏检的 bug。X-Prop 违规通常需要通过复位初始化或安全的 X 处理来修复。

X-Prop Analysis Browser 按实例分组显示 X 传播检查结果,绿色表示该路径无 X 传播问题,红色表示检测到 X 传播:

X-Prop Analysis Browser:按层次显示各实例的 X 传播检查结果,Property Table 显示具体的 X-Prop 属性和状态

来源文件

  • XPROP/XPROP_verilog_example.tcl
  • XPROP/XPROP_vhdl_example.tcl

6. Connectivity 连接性验证示例

6.1 示例概述

Connectivity App 验证模块间信号连接的正确性,支持正向连接验证(从 CSV 加载连接映射)和反向连接验证(自动从 RTL 提取连接关系)。

6.2 三种验证方式

方式一:正向验证(CONN_verilog_example.tcl)

# 配置 Blackbox Assistant 自动优化黑盒
blackbox_assistant -config -connectivity_map conn.csv
elaborate -top top

clock clk
reset ~rstN

# 加载连接映射表(CSV 格式定义了源→目的连接)
check_conn -load conn.csv

# COI 验证:连接的信号在彼此的影响锥内
check_conn -validate

# 翻转检查:翻转源端看目的端是否翻转
check_conn -generate_toggle_checks {}

check_conn -prove
report

方式二:反向验证(CONN_reverse_verilog_example.tcl)

blackbox_assistant -config -max_depth 0
elaborate -top top

clock clk
reset ~rstN

# 自动从 RTL 提取连接关系
# -src 指定源模块列表,工具追踪所有从这些模块出发的连接
check_conn -reverse -src {ing0 ing1 ing2 ing3 eg brdg arb p_sel} -load

check_conn -validate
check_conn -generate_toggle_checks {}
check_conn -prove

6.3 验证流程

1Setup — Blackbox Assistant 配置

blackbox_assistant -config -connectivity_map conn.csv 让 BBA 根据连接映射自动优化黑盒设置,减少证明复杂度。反向验证使用 -max_depth 0 配置。

2证明 — COI + 翻转检查

check_conn -validate 执行 COI(Cone of Influence)验证,确认连接的源和目的在彼此的影响锥内。check_conn -generate_toggle_checks 生成翻转检查属性:翻转源端信号,证明目的端也会翻转(验证连接在功能上是通的)。

Connectivity Viewer 左侧 Worksheet Browser 列出所有连接检查项及其状态(绿色勾通过、红色 X 失败、Toggle/COI 列显示翻转和影响锥验证状态),右侧 Property Table 显示每个连接属性的证明结果:

Connectivity App GUI:Worksheet Browser(左)列出连接对和检查状态,Property Table(右)显示各连接属性的证明引擎和结果

来源文件

  • CONN/CONN_verilog_example.tcl
  • CONN/CONN_reverse_verilog_example.tcl
  • CONN/conn.csv

7. COV 覆盖率验证示例

7.1 示例概述

COV(Coverage)App 度量形式验证的覆盖率,包括代码覆盖率(branch/statement/expression/toggle)和功能覆盖率(functional covergroup)。

7.2 Tcl 脚本解读

# 在 elaboration 之前初始化 COV
check_cov -init -model {branch statement expression toggle functional} \
  -toggle_ports_only -exclude_bind_hierarchies

# analyze + elaborate ...
# clock + reset ...

# 先证明所有属性
set_max_trace_length 9
prove -all

# 生成覆盖率指标
check_cov -measure -no_auto

7.3 验证流程

1Setup — 覆盖率模型选择

check_cov -init 必须在 elaboration 之前调用。-model 指定覆盖模型:branch(分支)、statement(语句)、expression(表达式)、toggle(翻转)、functional(covergroup)。-toggle_ports_only 只对端口做翻转覆盖(减少计算量),-exclude_bind_hierarchies 排除 bind 层级的覆盖率(测试平台代码不统计)。

2证明 — 先 prove 属性再 measure

先用 prove -all 证明属性(max_trace_length 9),然后 check_cov -measure 生成覆盖率。-no_auto 禁用自动证明策略,使用已有的证明结果来计算覆盖率。

3GUI 操作

在 GUI 中打开 Coverage 视图:

  1. 等待引擎完成覆盖率计算
  2. 查看 Stimuli(激励覆盖)/COI(影响锥覆盖)/Proof(证明覆盖)三类指标
  3. 使用 Report Coverage 功能查看 Unreachable(不可达覆盖项)和 Out of COI(COI 外的逻辑)
  4. 源码视图中高亮不可达项(灰色标注)

Coverage Analysis 面板显示 Formal/Stimuli/Checker 三种覆盖率,绿色表示已覆盖,红色表示未覆盖,黄色表示部分覆盖;右侧源码视图高亮显示覆盖状态:

Coverage GUI:Toggle 覆盖率表显示 Formal/Stimuli/Checker 三列覆盖情况,右侧源码高亮绿色(已翻转)和红色(未翻转)

来源文件

  • COV/COV_verilog_sva_example.tcl

8. CSR 寄存器验证示例

8.1 示例概述

CSR App 验证寄存器映射的行为正确性:根据 CSV/IP-XACT 寄存器定义,自动生成断言验证寄存器读写/复位/字段访问行为。

验证目标:验证 UART 设计中寄存器的地址映射、访问类型(RO/RW/W1C 等)、复位值符合 CSV 规格。

8.2 Tcl 脚本解读

set CSR_MAP uart_top_JasperCSR.csv

# 分析 UART RTL
analyze +define+DATA_BUS_WIDTH_8 -sv +incdir+${RTL_PATH} \
       ${RTL_PATH}/uart_top.v ${RTL_PATH}/uart_receiver.v \
       ${RTL_PATH}/uart_regs.v ${RTL_PATH}/uart_tfifo.v \
       ${RTL_PATH}/uart_transmitter.v ${RTL_PATH}/uart_wb.v ...

# 分析 Wishbone 总线约束文件
analyze -sv +incdir+${RTL_PATH} ${PROP_PATH}/wishbone_cons.sv

# 连接 CSR PA 实例
analyze -sv09 jasper_CSR_PA_inst.sv

elaborate -top uart_top

# 加载寄存器映射表
check_csr -load $CSR_MAP -instance i_jasper_csr.jasper_csr_checker0 -auto_hr_info

clock wb_clk_i
reset wb_rst_i -non_resettable_regs 0

# Task 机制:建立总线约束任务并链接到 CSR 任务
task -create IF_CONS -source_task <embedded> -copy_assumes
task -set CSR
task -link IF_CONS

set_engine_mode {Ht N}
set_prove_time_limit 30s

check_csr -prove

8.3 验证流程

1Setup — 寄存器映射加载

CSV 文件定义了每个寄存器的地址、字段、访问类型、复位值。jasper_CSR_PA_inst.sv 实例化 CSR PA,-instance 指定 PA 实例在设计层次中的路径。-auto_hr_info 自动提取头文件信息。

2约束 — 总线接口约束

wishbone_cons.sv 包含 Wishbone 总线协议的约束(assume),确保总线事务合法。使用 task 机制:将 assume 从 embedded task 拷贝到 IF_CONS task,然后链接到 CSR task,使 CSR 验证在总线约束下进行。

3证明

check_csr -prove 使用 {Ht N} 引擎,30 秒时间限制。CSR 自动生成的断言验证:写入指定地址 → 读出预期值、复位后读出复位值、只读字段不可写等寄存器行为。

CSR GUI 加载寄存器映射表后,自动生成的属性在 Property Table 中显示,验证寄存器读写行为是否符合规格:

CSR App 界面:寄存器属性验证结果

来源文件

  • CSR/CSR_verilog_example.tcl
  • CSR/uart_top_JasperCSR.csv
  • designs/uart_design/

9. ARCH 架构建模验证示例

9.1 示例概述

ARCH App 使用 XML 格式的表格化架构模型验证设计是否符合架构规范。示例验证 L1/L2 缓存之间的通信协议。

9.2 Tcl 脚本解读

clear -all
set_visualize_auto_check_props on

# 加载 XML 格式的架构模型
check_arch -load L1L2.xml

set_prove_per_property_time_limit 10s
set_prove_time_limit 30s

check_arch -prove
report

# 查看 L1 比较失败的反例
visualize -violation -property {<embedded>::L1L2.AST_table_L1_CMP_full} -new_window

9.3 验证流程

XML 模型定义了 L1 和 L2 缓存之间的期望行为表格。ARCH 自动生成三类属性:

证明失败时使用 visualize -violation 查看具体哪个表格行的比较失败及反例波形。

ARCH App 加载 XML 架构模型后验证设计行为与表格定义的一致性:

ARCH App 架构建模验证界面

来源文件

  • ARCH/ARCH_example.tcl
  • ARCH/L1L2.xml

10. BPS 行为属性综合示例

10.1 示例概述

BPS(Behavioral Property Synthesis)从仿真波形(VCD)中自动学习设计行为模式,综合出 SVA 属性候选。

验证目标:从 3 个 VCD 波形中学习 reference_design 的行为模式,生成属性候选并导出。

10.2 Tcl 脚本解读

# 分析 RTL + SVA
analyze -verilog ${RTL_PATH}/design/arbiter.v
analyze -verilog ${RTL_PATH}/design/bridge.v
# ... 其他 RTL 和 SVA 文件

elaborate -bbox_a 1024     # 黑盒阈值 1024 门
clock clk
reset {rstN == 1'b0}
waveform -reset rstN==0

# 提取关注点(POI = Points of Interest)
scope -extract all         # 自动提取所有信号
scope -add ready0 ready1 ready2 ready3   # 手动添加 ready 信号
scope -add eg.cur_state eg.read_write brdg.current_read_write  # 添加状态信号

# ---- 第一轮 VCD 扫描 ----
check_bps -scan -trace -vcd ${VCD_PATH}/vcd/e154.vcd
database -set_baseline -bps    # 设置基线

# ---- 第二、三轮扫描 ----
check_bps -scan -trace -vcd ${VCD_PATH}/vcd/e155.vcd
check_bps -scan -trace -vcd ${VCD_PATH}/vcd/e156.vcd

# 导出 cover 类候选到 FPV 证明
check_bps -export -class unclassified -type cover
set_current_gui fpv
prove -task <synthesized> -time_limit 30s

# 导出为多种格式
export -bps -to_sva [get_proj_dir]/example.sva \
    -to_tcl [get_proj_dir]/connect_sva.tcl \
    -type coverage_hole -type exercised_cover \
    -class certified -class unclassified
export -bps -to_html [get_proj_dir]/example.htm \
    -type coverage_hole -type exercised_cover \
    -class certified -class unclassified

10.3 验证流程

1Setup — POI 提取

scope -extract all 自动提取设计中的信号作为观察点。scope -add 手动添加关键控制信号和状态信号。POI 决定了 BPS 学习行为的范围。

2三轮 VCD 扫描学习

每轮 check_bps -scan -trace -vcd 扫描一个 VCD 波形文件,BPS 分析波形中信号间的时序关系,学习重复模式并综合为 SVA 属性。第一轮后 database -set_baseline -bps 设置基线,后续扫描发现新行为。三轮扫描(e154/e155/e156)提供不同的仿真场景,增加学习覆盖度。

3导出与验证

check_bps -export 将综合出的属性导出到 FPV App 中用形式引擎证明。导出格式包括 SVA 文件、Tcl 连接脚本、HTML 报告。属性分类:certified(已在所有波形中验证)、unclassified(未分类,需形式验证确认)。

BPS POI Browser 显示提取的关注点(按 Counters/FIFOs/FSMs 等分类),Property Candidates 面板列出从波形中学习到的属性候选及其状态(covered/unprocessed):

BPS POI Browser(左)和 Property Candidates(右):从 VCD 波形中自动学习并综合出的属性候选列表

来源文件

  • BPS/BPS_verilog_sva_example.tcl

11. FSV 功能安全验证示例

11.1 示例概述

FSV(Functional Safety Verification)面向 ISO 26262 功能安全标准,通过故障注入(SA0/SA1/SEU/SET)分析设计在硬件故障下的安全性,' 评估故障的可激活性(Activability)、可传播性(Propagatability)和可检测性(Detectability)。

验证目标:分析饮料售货机(drink_machine)在硬件故障下的功能安全性,并对比安全版(drink_machine_top_safe)的改进效果。

RTL 模块(fsv_design/)

  • can_counter.v — 易拉罐计数
  • coin_counter.v — 硬币计数
  • drink_machine.sv — 售货机核心逻辑
  • drink_machine_top.v — 非安全版顶层
  • test_drink.v — 测试模块
  • rtl_safe/drink_machine_top_safe.v — 带安全机制的顶层

11.2 Tcl 脚本解读

check_fsv -init
source fsv_utils.tcl             # 加载 fsv_summary 等工具过程

analyze -sv ${RTL_PATH}/rtl/can_counter.v \
            ${RTL_PATH}/rtl/coin_counter.v \
            ${RTL_PATH}/rtl/drink_machine.sv \
            ${RTL_PATH}/rtl/drink_machine_top.v \
            ${RTL_PATH}/rtl/test_drink.v \
            ${RTL_PATH}/rtl_safe/drink_machine_top_safe.v

elaborate
clock -infer                      # 自动推断时钟
reset top.reset

set_fsv_clock_cycle_time 200ns    # 时钟周期 200ns(5MHz)
set_fsv_engine_mode {Bm Ht Hp Tri}
set_fsv_regs_mapping_optimization on
set_fsv_strobe_optimization on

# ---- 故障注入配置 ----
# SA0+SA1(stuck-at-0/1):所有信号
check_fsv -fault -add [get_design_info -instance top -list signal -silent] -type SA0+SA1
# SEU(单粒子翻转):所有 flop,全时段
check_fsv -fault -add [get_design_info -instance top -list flop -silent] -type SEU -time_window 0:$
# SET(单粒子瞬态):所有信号,500ns 建立保持时间
check_fsv -fault -add [get_design_info -instance top -list signal -silent] -type SET -time_window 0:$ -set_hold_time 500ns
# 移除 checker 输出信号(*_failure)不作为故障目标
check_fsv -fault -remove [check_fsv -fault -list -node {.+_failure} -regexp -silent]

# ---- Strobe 配置(观察点)----
check_fsv -strobe -add [get_design_info -instance top -list output -include_hier_path -silent] -functional
check_fsv -strobe -add [check_fsv -strobe -list -node {*_failure} -silent] -checker

# ---- 三阶段分析 ----
check_fsv -structural          # 结构分析:快速排除不可达故障
check_fsv -generate            # 生成形式验证属性
check_fsv -prove -time_limit 1m  # 证明

# ---- 报告 ----
check_fsv -report -class dangerous
check_fsv -report -force -text ~/fsv.rpt
fsv_summary                     # 按 A/P/D 分类汇总

11.3 验证流程

1Setup — 故障类型与注入目标

四种故障模型:

  • SA0/SA1(Stuck-At-0/1):信号固定为 0 或 1
  • SEU(Single Event Upset):触发器值翻转(全时段 0:$)
  • SET(Single Event Transient):信号上出现瞬态脉冲(500ns 宽度)

Strobe(观察点)分为两类:functional(功能输出端口)和 checker(安全检查器输出 *_failure)。

2约束 — 移除 checker 信号

check_fsv -fault -remove 将 *_failure 信号从故障目标中移除,因为这些是检查器的输出而非设计功能信号。

3引擎 — {Bm Ht Hp Tri}

Bm(BMC)、Ht(Heavyweight trace)、Hp(Heavyweight proof)、Tri(Triage engine)组合,1 分钟时间限制。

4三阶段证明

Structural:通过静态结构分析快速排除不可达故障(不在任何观察点 COI 内的故障直接标记为 safe)。
Generate:对剩余故障生成形式验证属性。
Prove:证明每个故障是否可激活、传播到观察点、被安全机制检测到。

5结果分析 — A/P/D 分类

fsv_summary 按 A(Activability 可激活)、P(Propagatability 可传播)、D(Detectability 可检测)分类汇总:

  • Safe:故障不可激活或不可传播到任何输出
  • Dangerous:故障可激活、可传播、且不可被检测到
  • Unknown:工具无法在时限内确定

验证思路:对比实验法

FSV 的核心验证方法是对比实验

  1. 非安全版(drink_machine_top)上跑 FSV → Dangerous 故障数量
  2. 安全版(drink_machine_top_safe)上跑 FSV → 新的 Dangerous 数量
  3. 差异 = 安全机制检测到的危险故障数
  4. 诊断覆盖率 DC = (原始 Dangerous - 安全版 Dangerous) / 原始 Dangerous × 100%

ISO 26262 根据 ASIL 等级要求不同 DC:ASIL B ≥ 90%,ASIL D ≥ 99%。

对比 drink_machine_top 和 drink_machine_top_safe 看安全机制的危险故障覆盖率提升。

FSV Fault Table 列出所有注入的故障及其分类结果(SA0/SA1/SEU/SET),Source Browser 显示 RTL 源码,Instance 树显示各模块故障统计:

FSV Fault Table:显示故障节点、故障类型(SA0/SA1)和分类结果(Unknown/Dangerous/Safe),左侧 Instance 树显示模块级故障统计

来源文件

  • FSV/FSV_example.tcl
  • FSV/fsv_utils.tcl
  • designs/fsv_design/

12. SPV 安全路径验证示例

12.1 示例概述

SPV(Security Path Verification)验证安全信息不会从指定的"源"泄露到"目的"节点,适用于 TrustZone、安全子系统、密钥保护等场景。

验证目标:验证 OTP 密钥(otp_key)和自定义密钥(custom_key)在非安全状态下不会泄露到可读寄存器 s_rdata。

RTL 模块(spv_design/)

  • otp_key — OTP 密钥(安全信息源)
  • custom_key — 自定义密钥(安全信息源)
  • s_secure — 安全状态标志
  • s_rdata — 读数据总线(信息泄露目的端)
  • s_req/s_write/s_ack — 总线访问控制信号

12.2 Tcl 脚本解读

analyze -sv -f $RTL_PATH/hash.f
analyze -sv $RTL_PATH/sva/hash_checker.sv

elaborate -top hash
clock clk
reset ~rst_n

# stopat:将密钥信号设为自由变量(不受设计逻辑驱动)
stopat otp_key custom_key
stopat hash_core.out_hash

# SPV 属性 1:非安全状态下 otp_key 不能流向 s_rdata
check_spv -create \
          -from otp_key \
          -to s_rdata \
          -to_precond {~s_secure}

# SPV 属性 2:非安全读操作时 custom_key 不能流向 s_rdata
check_spv -create \
          -from custom_key \
          -to s_rdata \
          -to_precond {s_req && ~s_write && s_ack && ~s_secure}

check_spv -prove

# 失败时查看泄露路径波形
visualize -violation -property <embedded>::spv_prop:1 -new_window

12.3 验证流程

1Setup — stopat 密钥源

stopat otp_key custom_key 将密钥信号设为不受约束的自由变量——形式引擎会穷举密钥的所有可能值,验证无论密钥是什么值,在非安全状态下信息都不会流到 s_rdata。

2约束 — 前置条件(-to_precond)

-to_precond 指定信息泄露的前提条件:

  • 属性 1:当 ~s_secure(非安全状态)时,otp_key 不能影响 s_rdata
  • 属性 2:当 s_req && ~s_write && s_ack && ~s_secure(非安全读事务)时,custom_key 不能影响 s_rdata
3证明 — 信息不泄露

SPV 使用信息流分析(information flow analysis)证明 -from 和 -to 之间不存在因果路径。如果证明失败,visualize -violation 显示具体的泄露路径波形。

SPV 支持四种典型 Use Model:Slave Access(从设备访问控制)、TrustZone Slave(TrustZone 从设备)、' Secure Subsystem(安全子系统)、Fault Tolerance(容错)。

SPV Analysis Browser 显示安全属性和信息流分析结果,右键菜单可查看 Violation Trace(泄露路径波形)或 Show Graph(信息流图):

SPV GUI:Properties 面板列出安全属性(no_ROM_leak_to_CPU 等),右键菜单提供 View Violation Trace、Show Graph 等调试操作

来源文件

  • SPV/SPV_verilog_example.tcl
  • designs/spv_design/

13. RTLD RTL 开发阶段验证示例

13.1 示例概述

RTLD(RTL Development)支持在 RTL 编写过程中增量验证,通过两步流程(start→continue)对比 RTL 修改前后的结构和行为变化。

13.2 两步验证流程

第一步:RTLD_start — 初始设计分析

# 自动设置分析(从目录结构推断 RTL 文件和顶层)
auto_setup -sv -path ../designs/reference_design/verilog_sva \
  -top_file ../designs/reference_design/verilog_sva/source/design/top.v

# 结构分析并设为基线
database -structural_analysis -batch
database -structural_analysis -set_baseline

# 可视化源码行行为
visualize {arb.shift="1000"}
visualize -save_recipe {Visualizing arbiter shift} -task <embedded> ...

# 捕获传输开始事件作为 Behavior
cover -name Transfer_Start {(arb.trans_started == 0) ##1 (arb.trans_started == 1)} ...

# 探索 FSM
visualize -explore eg.cur_state
visualize -save_recipe "Exploring main FSM" ...

# 行为分析并设为基线,保存数据库
database -behavioral_analysis -set_baseline
save -jdb [get_proj_dir]/example.jdb -capture_setup

第二步:RTLD_continue — 修改后对比

# 恢复数据库
restore -jdb [get_proj_dir]/example.jdb

# 结构分析 → 导出结构差异报告
database -structural_analysis -batch
database -export_report "Structural Differences" [get_proj_dir]/sa.csv

# 行为分析 → 导出行为差异报告
database -behavioral_analysis -include_behaviors -batch
database -export_report "Behavioral Differences" [get_proj_dir]/ba.csv

# 对比行为变化(replot)
visualize -property {<embedded>::behavior:0}
visualize -replot
visualize -save_recipe {Another recipe} ...

13.3 验证流程

RTLD 体现了 RTL 开发中"修改→对比→验证"的迭代工作流:

  1. 设基线:初始版本完成结构和行为分析后设置基线
  2. 修改 RTL:工程师修改 RTL 代码
  3. 结构对比structural_analysis 报告层次结构、端口、实例的变化
  4. 行为对比behavioral_analysis 报告已索引行为的波形变化
  5. Replot:可视化同一 Behavior 在修改前后的波形差异

RTLD 基于 Visualize 波形引擎进行行为分析,下图展示了 Visualize 波形窗口中右键菜单提供的调试功能(Why 分析、Relevant Logic 高亮、波形比较等),RTLD 的 behavioral_analysis 即利用此功能对比修改前后波形:

Visualize 波形窗口:RTLD 利用波形可视化和右键调试功能进行行为对比分析,支持 Why、Relevant Logic、Highlight Relevant Difference 等操作

来源文件

  • RTLD/RTLD_start_verilog_example.tcl
  • RTLD/RTLD_continue_verilog_example.tcl

14. Superlint 静态检查示例

14.1 示例概述

Superlint 将传统 Lint(静态语法/结构检查)与形式验证结合,不仅能发现代码风格问题,还能通过形式引擎证明 bug 的可达性。' AUTO_FORMAL/ 目录包含 9 类带 bug 的 RTL 示例,每类展示 Superlint 如何使用形式验证发现真实 bug。

14.2 主脚本解读(Superlint_verilog_example.tcl)

check_superlint -init

# 分析 RTL
analyze -verilog ${RTL_PATH}/arbiter.v ${RTL_PATH}/bridge.v ...
elaborate -bbox_a 1024

clock clk
reset {rstN == 1'b0}

# 提取检查项(Lint + Auto Formal)
check_superlint -extract

# 添加设计约束(FIFO 指针范围约束)
assume {brdg.wr_ptr < 4'b1111}
assume {brdg.rd_ptr < 4'b1111}

# Task 机制:将约束链接到 Superlint 任务
task -create design_assumptions -copy_assumes -copy_related_covers -source_task <embedded>
task -link design_assumptions -to <SL_AUTO_FORMAL_ARITHMETIC_OVERFLOW>

set_max_trace_length 50
check_superlint -prove -task {<SL_*}

14.3 AUTO_FORMAL 9 类 Bug 示例

Superlint/AUTO_FORMAL/ 中每个子目录包含带特定 bug 的 RTL 和对应的 slint.tcl

类别规则Bug 描述
ARITHMETIC_OVERFLOWEXP_IS_OVFL算术运算溢出(加法/乘法结果超出位宽),形式验证证明溢出可达
BUSBUS_IS_CONT/BUS_IS_FLOT总线连续驱动(多驱动)/ 总线浮空(无驱动)
CASECAS_IS_DFRC/CAS_NO_PRIO/CAS_NO_UNIQcase 不全(default 缺失)/ 无优先级 / case 项不唯一
COMBO_LOOPMOD_IS_FCMB组合逻辑环路(无寄存器打断的反馈路径)
DEAD_CODEBLK_NO_RCHB不可达代码块(形式验证证明该路径永远不可达)
FSMFSM_IS_DLCK/FSM_IS_LLCK/FSM_NO_MTRN/FSM_NO_RCHB/FSM_NO_TRRN死锁 / 活锁 / 无转移 / 不可达状态 / 无转移(到达后无法离开)
OUT_OF_BOUND_INDEXINGARY_IS_OOBI数组越界索引(索引值可能超出数组范围)
SIGNALSSIG_IS_DLCK/SIG_IS_STCK/SIG_NO_TGFL/SIG_NO_TGRS信号死锁 / stuck(恒定值)/ 0→1 无翻转 / 1→0 无翻转
X_ASSIGNMENTASG_IS_XRCHX 赋值可达(将 X 值赋给信号的路径可被激活)

14.4 LINT 规则类别

除 AUTO_FORMAL 外,Superlint/LINT/ 包含 9 类纯 Lint 规则:

每个子目录包含 Verilog/VHDL 示例和 slint.tcl,可独立运行:

cd Superlint/AUTO_FORMAL/AUTO_FORMAL_ARITHMETIC_OVERFLOW && jg -superlint slint.tcl

Superlint 主界面的 Task Tree 显示各检查类别(AUTO_FORMAL_ARITHMETIC_OVERFLOW、DEAD_CODE、FSM 等)的证明结果,Automatic Formal Properties 面板列出具体属性和状态,Analysis Browser 显示违规源码位置:

Superlint 界面:Task Tree(左)显示各检查类别结果,Automatic Formal Properties(中)列出属性和状态,Analysis Browser(右)高亮源码中的违规位置

来源文件

  • Superlint/Superlint_verilog_example.tcl
  • Superlint/AUTO_FORMAL/
  • Superlint/LINT/

15. Proof Accelerator 教程示例

15.1 tutorial_scoreboard_priority — FIFO 数据完整性

使用 jasper_scoreboard_priority PA 验证 8 深度 FIFO 的数据按序传输完整性。提供两个脚本:含 bug 的 test.tcl 和修复后的 test_ok.tcl

test.tcl — 发现 Bug

analyze -verilog {./design/fifo.v}
analyze -verilog -req ./jasper_req/FIFO_datapath.v

elaborate -bbox_a 512

# 连接 PA 端口到 DUT
connect FIFO_datapath req \
  -connect clk       clk \
  -connect rstN      hresetn \
  -connect valid_in  fifo_write \
  -connect valid_out fifo_read \
  -connect data_in   fifo_datain \
  -connect data_out  fifo_dataout

clock clk
reset {~hresetn}
assume -env {~fifo_reset}

task -set {<req.dp_PACKET_SANITY>}
assume {(~fifo_empty_s && ~fifo_read) == 1'b0}

set_engine_mode engineG
prove -all

此脚本未约束 overflow/underflow,证明结果为 failed:' 当 FIFO 满时写入或空时读出导致数据乱序,scoreboard 检测到 data integrity 违规。

test_ok.tcl — 完整证明

# ... 同上 ...

# 防止 overflow 和 underflow 条件
assume -env {(fifo_empty && fifo_read) == 1'b0}
assume -env {(fifo_full && fifo_write) == 1'b0}

set_engine_mode engineG
prove -all

添加 overflow/underflow 约束后,所有断言预期 proven

15.2 tutorial_scoreboard_2 — 串并转换接收器

使用 jasper_scoreboard_2 验证 Universal Asynchronous Receiver 的数据传输正确性。

test.tcl — 发现两个 Bug

analyze -verilog {./design/universal_asynchronous_receiver.v}
analyze -verilog -req {./jasper_req/datapath.v}

elaborate -bbox false -top {uar}

connect datapath dp \
  -connect {clk}       {clk}  \
  -connect {rstN}      {~gl_reset}  \
  -connect {tx_error}  {dError}  \
  -connect {valid_in}  {count8}  \
  -connect {data_in}   {dIn}  \
  -connect {valid_out} {dReady}  \
  -connect {data_out}  {dOut}

clock {clk}
reset {gl_reset}

assert -disable <dp.dp_PACKET_INTEGRITY>::sanity_reset_activated
assert -disable <dp.dp_PACKET_INTEGRITY>::sanity_reset_toggle_once

set_engine_mode engineG
prove -all

证明 failed,发现两个 bug:

  1. Bug 1dReady(data ready 信号)未通过全局复位正确初始化,导致无数据时也输出有效
  2. Bug 2dReady 置位后未拉低,导致同一数据重复输出

test_fix.tcl — 修复后证明

将 DUT 文件替换为 universal_asynchronous_receiver_fix.v,其余不变,所有断言预期 proven

两组教程均提供 Verilog 和 VHDL 双版本。

从示例中学到什么

这两个 PA 教程展示了形式验证的重要模式:先找到 bug,再理解约束,再证明正确性

PA(Proof Accelerator)预构建了常用检查逻辑(scoreboard、datapath 等),不需要自己写复杂 SVA。

扩展练习

  1. FIFO 示例只加 overflow 约束不加 underflow,观察哪些断言 fail
  2. Receiver 示例只修复初始化 bug,观察还有什么 fail

下图展示了 Proof Accelerator 中 scoreboard PA 的架构示意图,支持 FULL_BUS、RANDOM_BIT、BIT_BLAST、SELECTED_BITS 四种位宽选择模式,分别对应数据完整性检查的不同精度和性能权衡:

Scoreboard PA 架构:四种位宽选择模式(FULL_BUS/RANDOM_BIT/BIT_BLAST/SELECTED_BITS)下的数据完整性断言结构

来源文件

  • proof_accelerators/tutorial_scoreboard_priority/verilog/test.tcl
  • proof_accelerators/tutorial_scoreboard_priority/verilog/test_ok.tcl
  • proof_accelerators/tutorial_scoreboard_2/verilog/test.tcl
  • proof_accelerators/tutorial_scoreboard_2/verilog/test_fix.tcl

16. IP-XACT 驱动验证示例

16.1 示例概述

IP-XACT 是 IEEE 标准的 IP 元数据描述格式。JasperGold 可以直接加载 IP-XACT 描述来驱动连接性验证和 CSR 验证,无需手动编写连接映射或寄存器 CSV。

16.2 IP-XACT 一致性+连接性验证

# 加载 IP-XACT 并自动设置设计
ipxact -load ipxact/top.xml -lib ipxact -setup design

# 检查 IP-XACT 声明与 RTL 的一致性(端口/参数/实例)
ipxact -check_rtl_consistency

# 从 IP-XACT 生成连接映射表
ipxact -generate_connectivity_map [get_proj_dir]/conn.csv orpsoc_top
check_conn -load [get_proj_dir]/conn.csv

clock -analyze
reset -analyze
clock clk_pad_i
reset ~rst_n_pad_i

check_conn -prove

16.3 IP-XACT CSR 验证

analyze -sv jasper_bind_csr.sv
ipxact -load ipxact/or1k.xml -lib ipxact -setup design

# 直接从 IP-XACT 加载 CSR 定义
check_csr -load_ipxact -instance jasper_csr_checker0

clock clk_i
reset rst_i
check_csr -prove

IP-XACT 驱动的连接性验证复用 Connectivity App GUI,从 IP-XACT XML 自动生成的连接映射在 Worksheet Browser 中列出并验证:

IP-XACT 驱动的连接性验证界面:IP-XACT 描述自动生成连接映射表后,使用 Connectivity App 的验证流程证明连接正确性

来源文件

  • IPXACT/IPXACT_consistency_connectivity_example.tcl
  • IPXACT/IPXACT_csr_example.tcl

17. UNR 覆盖不可达性分析示例

17.1 示例概述

UNR(Coverage Unreachability)结合仿真覆盖率数据库,证明仿真未覆盖的项确实不可达(dead code),帮助排除伪漏盖。

17.2 验证流程

# jg.tcl — JasperGold 端形式验证
check_unr -setup
clock -none
reset -none

check_unr -prove -prove_opts { -verbosity 4}
check_unr -list -type unreachable    # 列出不可达覆盖项
database -export_unicov              # 导出 unicov 格式

report -summary
run
exit

UNR 示例采用仿真+形式联合流程:

  1. 运行仿真生成覆盖率数据库(coverage.ucdb 等格式)
  2. 在 JasperGold 中 read_coverage_db -sim <coverage.ucdb> 读取仿真覆盖数据
  3. check_unr 对未覆盖项做不可达证明:如果形式引擎证明该覆盖点不可达,则为 dead code;如果可达则说明仿真激励不足
  4. database -export_unicov 导出结果回覆盖率数据库

VerificationKit 库支持多种方法学:SV Class Library、e over SC TLM、UVM e 等。

UNR Items Table 列出从仿真覆盖率数据库中导入的未覆盖项,红色禁止图标表示形式引擎证明该项不可达(dead code),绿色勾表示可达但仿真未覆盖(需要补充激励):

UNR GUI:UNR Items Table 显示各覆盖项的不可达性证明结果,红色图标表示不可达(dead code),绿色勾表示可达(激励不足)

来源文件

  • UNR/tcl/jg.tcl
  • UNR/tcl/run_sim.tcl

来源文件

  • example_jaspergold_apps/FPV/
  • example_jaspergold_apps/CDC/
  • example_jaspergold_apps/SEC/
  • example_jaspergold_apps/LPV/
  • example_jaspergold_apps/XPROP/
  • example_jaspergold_apps/CONN/
  • example_jaspergold_apps/COV/
  • example_jaspergold_apps/CSR/
  • example_jaspergold_apps/ARCH/
  • example_jaspergold_apps/BPS/
  • example_jaspergold_apps/FSV/
  • example_jaspergold_apps/SPV/
  • example_jaspergold_apps/RTLD/
  • example_jaspergold_apps/Superlint/
  • example_jaspergold_apps/proof_accelerators/
  • example_jaspergold_apps/IPXACT/
  • example_jaspergold_apps/UNR/
  • example_jaspergold_apps/designs/