想象你是这座城市的交通管理中心主任。市中心有一个智能十字路口,四组红绿灯由一枚芯片统一调度。你的职责是确保:红灯亮起时,垂直方向的车流必须停下;绿灯亮起时,车辆必须按序通过;绿灯不能与侧向绿灯同时亮起,否则就会撞车。你无法派交警全天候盯着路口,于是你做了两件事:第一,制定一套交通规则并安装摄像头,让违规行为自动浮出水面;第二,画一张监控盲区地图,记录哪些时段、哪些场景还没被拍到证据。前者的技术名字叫“断言”,后者的技术名字叫“覆盖率”。本文要讲的,就是如何用SystemVerilog这门硬件描述语言里的断言(SVA)技术,为芯片行为立下“交规”,再用覆盖率技术量化验证的充分程度,最终在芯片交付前实现“覆盖率闭合”。

岗位关联

对AI从业者的价值:掌握SVA断言与覆盖率,相当于掌握芯片验证的“仪表盘”和“路线图”——你能精确描述行为是否正确、量化验证是否充分,把“我觉得测够了”升级为“数据证明测够了”。

目录
  1. 可视化演示
  2. SVA基础概念
  3. 立即断言
  4. 并发断言
  5. 序列与属性
  6. 操作符用法
  7. 覆盖率度量
  8. 覆盖率闭合
  9. AI 应用场景
  10. Python 演示
  11. 常见误区
  12. 面试题

可视化演示

展示系统处理流水线、实时性能指标曲线及多方案对比分析,包含数据流转、吞吐延迟监控与方案评估。

本节配有交互动效(进入视口后自动加载,约 3KB)。

系统可视化 处理流程:输入→处理→模型→输出 性能监控:实时指标 P=L×T

SVA基础概念

想象城市里刚启用的智能十字路口:四组红绿灯由一颗芯片统一指挥。你最担心的不是灯不亮,而是“变化顺序不对”——南北向还绿着,东西向就抢行。没有交警日夜盯守时,如何让设备自动识别违规?你立下一套“行为准则”并装上监控,让机器自己发现异常。在芯片验证领域,这套“行为准则”的标准化语言就是 SVA(SystemVerilog Assertion)。

验证工程师不再在测试平台里写一段段容易遗漏的 if-else 检查,而是用专门的断言语句把协议规则直接描述出来,仿真工具会在信号变化时自动判断违规并生成报告。SVA 最大的价值是形式化:规则一经写成,就不疲劳、不漏判,还能在回归测试中一遍遍自动执行。

SVA 贯穿芯片验证的不同层次:模块级检查数据通路的内部时序,接口级检查总线握手协议,系统级把多模块的交互作为整体校验。断言本身分为立即断言和并发断言两大类,前者像单张抓拍,后者像连续录像。把“验证完备性”抽象成数学语言,就是所有检查点预期的总和:

回到路口:每一条“行为准则”就是路口的一个检查点,验证完备性则是把路口所有点位的监控探头叠加起来的总覆盖能力。

验证完备性=∑i=1N(设计预期i  ⟺  仿真行为i)\text{验证完备性} = \sum_{i=1}^{N} \left( \text{设计预期}_i \;\Longleftrightarrow\; \text{仿真行为}_i \right)
  1. 观测点下标 i$i$ 表示第几个可观测的行为约束点,例如总线握手时 valid 与 ready 的配合。
    i∈{1,2,…,N}\displaystyle i \in \{1, 2, \dots, N\}
  2. 设计预期$\text{设计预期}_i$ 是用规范文字描述的期望结果,如“请求信号拉高后最多三拍内必须得到应答”。
    设计预期i\displaystyle \text{设计预期}_i
  3. 仿真行为$\text{仿真行为}_i$ 是仿真波形中实际记录的信号取值。
    仿真行为i\displaystyle \text{仿真行为}_i
  4. 双向等价$\Longleftrightarrow$ 表示预期与实际完全一致,断言检查的正是这个等式是否成立。
    设计预期i⟺仿真行为i\displaystyle \text{设计预期}_i \Longleftrightarrow \text{仿真行为}_i
  5. 总和$\sum_{i=1}^{N}$ 把全部检查点的对错汇总;只要有一个点不成立,验证完备性就有缺口。

立即断言

如果你只在网约车驶过路口的那一瞬间用闪光灯拍一张照片,判断它是否违规停车——这就是“立即断言”的第一直觉。立即断言在仿真执行的某个具体时刻立即求值,不等待时钟,不回顾过去,只看当前这一刹那的状态。

立即断言的语法很直观,通常写在 initial 或 always 过程块中:

其中 assert(...) 是显式检查,else $error() 是违规后的报错动作。它等价于传统代码里的 if-else 判错,但因为不是工程师临时的软件分支,而是语言级关键字,能与仿真器统一集成报告。

立即断言与并发断言最大的不同在于执行语义由过程块触发:仿真器执行到这一行才求值,因此它无法表达“连续两拍 a 都保持为真”这类跨时钟行为。它的逻辑可用真值表表达为:

就像交警只看一眼当前画面就开出罚单,立即断言简单、直接,适合快速检查组合逻辑状态是否合法。但要看清“车辆先左转再直行”的完整轨迹,就需要下一章的并发断言。

assert(P)={pass,P=truefail,P=false\text{assert}(P) =\begin{cases}\text{pass}, & P = \text{true} \\\text{fail}, & P = \text{false}\end{cases}
  1. P 值$P$ 是当前时刻要检查的表达式,比如 a && b,取值只有真或假。
    P∈{true,false}\displaystyle P \in \{\text{true}, \text{false}\}
  2. 通过分支当 $P = \text{true}$ 时断言通过,仿真继续,不做额外处理。
    pass,P=true\displaystyle \text{pass}, \quad P = \text{true}
  3. 失败分支当 $P = \text{false}$ 时,触发挂接的动作,如 $error、$fatal。
    fail,P=false\displaystyle \text{fail}, \quad P = \text{false}
systemverilog1 行
check_name: assert (a && b) else $error("a和b不能同时为1");

并发断言

路口真正需要的不是一张照片,而是全天候录像回放:不仅要记录“这一秒发生了什么”,还要追问“三秒前那辆车有没有打转向灯”。并发断言正是基于时钟的连续录像机——它由时钟沿驱动,在每一个采样沿自动评估属性,不需要人为调用,跨越多拍的时序行为都能被捕捉。

并发断言的基本结构由序列和属性构成。序列描述信号的时序展开,属性描述一条完整的待验证规则。最常写的形式是一句 assert property( ... ),其中 @(posedge clk) 指定的时钟沿是采样节拍。并发断言可以直接挂在模块、接口或程序(program)中,验证平台无需额外调用函数。

一个简单的并发断言可以这样理解:只看第0拍和第1拍两个窗口——若第0拍 a 与 b 同时成立,则第1拍 c 必须成立。写成 SVA 为:

其数学本质是:

录像机的优势在于持续执法。并发断言会一直盯着路口,不管仿真跑到第几拍,只要规则被违反,它一定会在对应时钟沿留下一条“违章记录”。

property:(a∧b)  ##1  c\text{property:}\quad (a \wedge b) \;\#\#1\; c
  1. 当前拍表达式$(a \wedge b)$ 在当前时钟沿对信号 a、b 做与运算。
    (a∧b)\displaystyle (a \wedge b)
  2. 延迟操作符$\#\#1$ 表示从当前沿向后延迟一个时钟周期,这是 SVA 中最核心的时间刻度。
    ##1\displaystyle \#\#1
  3. 下一拍表达式$c$ 在延迟后的下一个时钟沿处求值。
    c\displaystyle c
  4. 整体属性整个式子为一个属性,只有“当前拍 a 且 b 成立,下一拍 c 也成立”时,断言才通过。
    (a∧b)  ##1  c\displaystyle (a \wedge b) \;\#\#1\; c
systemverilog1 行
assert property (@(posedge clk) (a && b) ##1 c);

序列与属性

十字路口的交通场景可以拆成一个个小剧本,比如“车辆接近路口 → 打转向灯 → 减速停在停止线”。在 SVA 中,这些小剧本称为序列(sequence),它把按时间顺序展开的事件描述出来。

序列的典型写法是:

它表示:第0拍 a 成立,第1拍 b 成立,第2拍 c 成立。序列像函数一样可以被复用;属性则像完整条款,把序列作为条件或结论嵌入。序列关注时间上的事件骨架,属性在这个骨架之上追加验证语义。例如:

一个序列从第一个元素到最后一个元素的时间跨度可以表达为:

一张录像包含许多小剧本。序列就是剧本中的分镜头,属性则是把分镜头串成完整故事线的导演;若要检查更复杂的规则,还要在分镜头间加修饰词——这正是下一章的操作符。

S=e0  ##1  e1  ##1  ⋯  ##1  enS = e_0 \;\#\#1\; e_1 \;\#\#1\; \cdots \;\#\#1\; e_n
  1. 序列起点$e_0$ 是序列匹配的第一个事件,必须在该拍为真。
    e0\displaystyle e_0
  2. 相邻延迟$\#\#1$ 连接两个相邻事件,表示间隔一个时钟周期。
    ##1\displaystyle \#\#1
  3. 中间事件$e_1, \dots, e_{n-1}$ 是中间事件,它们依次成立才能维持序列匹配。
    e1  ##1  ⋯\displaystyle e_1 \;\#\#1\; \cdots
  4. 序列终点$e_n$ 是最后一个事件;从 $e_0$ 到 $e_n$ 共经过 $n$ 个时钟周期,序列才算匹配成功。
    en\displaystyle e_n
systemverilog3 行
sequence s_cross;  a ##1 b ##1 c;endsequence
systemverilog3 行
property p_cross;  @(posedge clk) s_cross;endproperty

操作符用法

城市路口的规则不只是“红灯停、绿灯行”,还有“黄灯亮后的三拍内,车辆必须完成减速并停在停止线”。要描述这种带条件、带重复的规则,单靠序列不够,需要蕴含与重复操作符的配合。

蕴含操作符把前件和后件连接起来:前件是触发条件,后件是必须满足的结果。SVA 提供两种蕴含。重叠蕴含 |->:前件满足的那一拍,后件在同一拍开始检查。非重叠蕴含 |=>:前件满足一拍之后,后件从下一拍开始检查。例如,“当 valid 为高时,下一拍 ready 必须为高”,可写成 valid |=> ready。

重复操作符则描述同一信号按某种节奏多次成立。a[*3] 表示连续重复——a 在连续三个时钟周期都为真。a[->3] 表示非连续重复——a 恰好出现3次,中间可以有其他拍。a[=3] 表示非连续非重叠重复——a 出现3次,且最后一次恰好在匹配窗口末尾。蕴含的数学含义与逻辑蕴含一致:

连续重复的本质是连续三拍的事件展开:

就像交规中加入了“连续三秒不得变道”的细则,操作符把监控中心的规则扩展成更复杂的判断;规则虽细,但摄像头看得明明白白。

a∣⇒b表示∀t,  a(t)=1  ⇒  b(t+1)=1a \mid\Rightarrow b \quad \text{表示} \quad \forall t,\; a(t)=1 \;\Rightarrow\; b(t+1)=1
a[∗3]  ≡  a  ##1  a  ##1  aa[*3] \;\equiv\; a \;\#\#1\; a \;\#\#1\; a
  1. 蕴含前件$a(t)=1$ 表示在周期 $t$ 时前件成立。
    a(t)=1\displaystyle a(t)=1
  2. 蕴含后件$b(t+1)=1$ 表示在下一拍 $t+1$ 时后件必须成立;若后件为假,则断言失败。
    b(t+1)=1\displaystyle b(t+1)=1
  3. 全称量词$\forall t$ 表示每个时钟周期都要满足这条规则,仿真器会在所有周期自动检查。
    ∀t\displaystyle \forall t
  4. 连续重复展开$a[*3]$ 等价于 $a$ 在三个相邻周期分别成立一次,合并为 $a \;\#\#1\; a \;\#\#1\; a$。
    a  ##1  a  ##1  a\displaystyle a \;\#\#1\; a \;\#\#1\; a

覆盖率度量

规则定好了,摄像头也装了——可你怎么知道监控有没有盲区?这就涉及覆盖率度量。覆盖率是一张“盲区地图”:哪些路口已拍到关键违法形式,哪些时段还完全没有数据。验证团队依靠它来回答“测够了没有”。

覆盖率首先分两类。代码覆盖率衡量设计代码被“执行到位”的程度,包括行覆盖率、分支覆盖率、条件覆盖率、翻转覆盖率和状态机覆盖率。它容易收集,但只相当于“摄像头有没有打开”。功能覆盖率则更贴近设计意图:验证工程师用 covergroup 定义关注点,内部用 coverpoint 指向信号,再用 bins 把信号取值划分成箱格。例如,针对总线突发长度,可以把长度 1、2、4、8 分别划成不同 bin;仿真中出现对应取值时,该 bin 就被标记为已覆盖。还可以用 cross 把多个覆盖点交叉组合,得到组合覆盖。

覆盖率不是等仿真结束才看的报表,而是贯穿整个验证周期。每当覆盖率增速停滞,监控中心就需要定向补充测试,把还未录入“案卷”的场景找出来。

功能覆盖率=已覆盖的 bin 数定义的 bin 总数×100%\text{功能覆盖率} = \frac{\text{已覆盖的 bin 数}}{\text{定义的 bin 总数}} \times 100\%
  1. 分子已覆盖的 bin 数,表示仿真过程中至少被命中一次的箱格数量。
    已覆盖的 bin 数\displaystyle \text{已覆盖的 bin 数}
  2. 分母定义的 bin 总数,是验证计划中预先设计好的全部关注箱格。
    定义的 bin 总数\displaystyle \text{定义的 bin 总数}
  3. 百分比换算乘以 100% 把比值变成直观的百分数,用于与目标阈值对比。
    ×100%\displaystyle \times 100\%

覆盖率闭合

有了规则、有了监控、有了盲区地图,最后一步是“结案”。覆盖率闭合代表验证活动的终止条件:拿到多少证据才敢在流片签署单上签字?如果只跑几千个随机种子就说“测完了”,无异于只看了一周录像就断言全年无违规。

覆盖率闭合流程通常分四步。第一,回归收集:让约束随机测试不断跑回归,融合所有测试的覆盖率。第二,分析热点:从工具导出的报告里找出未覆盖项,判断是可覆盖却未覆盖,还是不可达。第三,定向补充:对未覆盖项写定向测试,重新回归。第四,签署:当各项指标达标后宣告闭合。闭合的签署标准可以表达为:

其中 $\theta$ 是验证计划中预设的功能覆盖率阈值,比如 95% 或 98%。

监控中心终于可以盖上“结案”大章。但真正的验证工程师明白,覆盖率闭合不是验证的终点——新需求一来,新的盲区地图又会展开。

sign-off  ⟺  (line coverage=100%)∧(func coverage≥θ)∧(未关闭 bug=0)\text{sign-off} \;\Longleftrightarrow\; \left(\text{line coverage}=100\%\right) \wedge \left(\text{func coverage} \geq \theta\right) \wedge \left(\text{未关闭 bug}=0\right)
  1. 签署含义$\text{sign-off}$ 表示验证完成,可以进入流片或交付阶段。
    sign-off\displaystyle \text{sign-off}
  2. 行覆盖达标$\text{line coverage}=100\%$ 表示所有可执行代码行至少被执行一次,排除不可达代码后达到100%才算合格。
    line coverage=100%\displaystyle \text{line coverage}=100\%
  3. 功能覆盖阈值$\text{func coverage} \geq \theta$ 表示功能覆盖率达到预设目标 $\theta$。
    func coverage≥θ\displaystyle \text{func coverage} \geq \theta
  4. 无效 bug$\text{未关闭 bug}=0$ 表示严重级缺陷已全部修复且回归通过。
    未关闭 bug=0\displaystyle \text{未关闭 bug}=0
  5. 逻辑与三个条件用 $\wedge$ 连接,缺一不可。
    (⋯ )∧(⋯ )∧(⋯ )\displaystyle (\cdots) \wedge (\cdots) \wedge (\cdots)

AI 应用场景

AI芯片验证中的总线协议检查

阶段:RTL 仿真验证阶段

解决的问题:AI 加速芯片内部往往布满高速总线(如 AXI),valid/ready 握手信号偶发错位很难用人工 if-else 查全。传统人工检查既慢又容易遗漏,且随机约束下复现困难。

具体案例:某 AI 推理芯片的验证团队在 AXI 接口上挂了一组并发断言,专门检查“valid 拉高后不允许无 ready 地撤销”这一条规则。回归到第 3 万次时,断言抓到一个概率极低的握手重叠错误,帮助设计团队提前两周定位修复。

神经网络加速器的覆盖率闭合

阶段:覆盖率驱动验证(CDV)阶段

解决的问题:AI 加速器的数据通路包含多种算子类型、输入通道数和位宽组合,只靠手工列举用例无法量化验证完备度,难以回答“还有哪些组合没测过”。

具体案例:验证团队用 covergroup 定义“算子类型 × 通道数 × 位宽”的交叉 bin,再配合约束随机激励。初始功能覆盖率只有 42%,经过两轮覆盖率分析、定向补充激励和回归,最终把功能覆盖率提升到 98%,达到闭合签署标准。

ISO 26262 功能安全下的断言复用

阶段:安全验证阶段

解决的问题:自动驾驶芯片对功能安全(ISO 26262)有硬性要求,希望关键路径的时序违规不仅在仿真中被发现,还能在芯片运行期间实时上报。

具体案例:某车载 AI 芯片将 SVA 断言转化为可综合的安全监控器,实时监视关键数据路径的握手与超时行为,一旦异常立即触发安全中断。这个做法把“离线仿真检查”升级为“在线自检机制”,显著提升了系统诊断覆盖率。

Python 演示

python47 行
class TrafficVerifier:    """迷你验证平台:用 SVA 风格的断言检查红绿灯时序,    并收集功能覆盖率 bin。"""     def __init__(self, total_cycles=32, inject_bug_cycle=2):        self.total_cycles = total_cycles        self.inject_bug_cycle = inject_bug_cycle        self.violations = []        self.coverage_bins = set()     def tick(self, cycle):        """返回该周期的南北、东西绿灯状态。"""        ns_green = cycle % 4 < 2        ew_green = cycle % 4 >= 2        if cycle == self.inject_bug_cycle:            ns_green = True   # 注入 bug:东西相位时南北也放行        return ns_green, ew_green     def check_assertions(self, cycle):        ns_green, ew_green = self.tick(cycle)        # 并发断言:a |-> !b,同一时刻只能一个方向放行        if ns_green and ew_green:            self.violations.append(cycle)        # 序列检查:绿灯必须连续两拍保持(a[*2] 的简化)        if cycle % 4 == 1:            prev_ns, _ = self.tick(cycle - 1)            if not (prev_ns and ns_green):                self.violations.append(cycle)     def sample_coverage(self, cycle):        ns_green, ew_green = self.tick(cycle)        state = "NS" if ns_green else "EW"        self.coverage_bins.add(state + "_" + str(cycle % 2))     def run(self):        for cycle in range(self.total_cycles):            self.check_assertions(cycle)            self.sample_coverage(cycle)        total_bins = 4        hit_bins = len(self.coverage_bins)        print("Violations:", self.violations)        print("Coverage: {}/{} = {:.0f}%".format(            hit_bins, total_bins, hit_bins * 100.0 / total_bins))  if __name__ == "__main__":    TrafficVerifier().run()
目的:用 Python 模拟一个迷你的红绿灯验证平台,演示 SVA 风格的并发断言如何抓到注入的 bug,以及功能覆盖率 bin 如何统计验证充分度。
  1. self.coverage_bins = set()用集合保存已覆盖的箱格,自动去重,体现覆盖率的“击中性”。
  2. def tick(self, cycle):生成每个时钟周期的红绿灯相位,相当于 DUT 的采样信号。
  3. if cycle == self.inject_bug_cycle:故意注入一个缺陷,用于验证断言能否捕捉到。
  4. if ns_green and ew_green:对应并发断言 a |-> !b:两个方向不允许同时放行。
  5. if cycle % 4 == 1:序列检查的采样窗口,模拟 a[*2] 的连续两拍保持。
  6. state = "NS" if ns_green else "EW"决定当前覆盖点落入哪个功能状态。
  7. self.coverage_bins.add(state + "_" + str(cycle % 2))打点收集,只有实际出现过的取值才会进入集合。
  8. for cycle in range(self.total_cycles):每个时钟周期自动执行断言与采样,对应仿真时钟推进。
  9. print("Coverage: {}/{} = {:.0f}%".format(...))输出覆盖率报告,等价于仿真结束后工具生成的覆盖率汇总。

常见误区

误区很多人看到断言 `fail` 就立刻认定 RTL 有 bug,火急火燎地翻代码、改逻辑,结果越改越乱。

正解断言失败只代表“当前仿真序列与预期不符”,原因可能有多种:测试激励写错、参考模型不对、复位初始状态不一致、甚至断言本身写错。就像路口摄像头拍到“闯红灯”,可能是红灯是临时维修设置的,也可能摄像机时钟没对齐。正确做法是先隔离原因,再决定是否修改设计。

为何常见:断言被当作“结果”而非“检查工具”,初学者看到红色报错就产生应激反应。

误区有的工程师认为行覆盖、分支覆盖都到 100%,功能上就万无一失,可以放心流片。

正解代码覆盖率只回答“代码是否被执行过”,不回答“行为是否正确”。功能覆盖率才是设计意图的量化。好比你把整座城市的行车记录仪都打开,并不等于拍到了所有违章类型。只有代码覆盖率与功能覆盖率同时达标,证据链才完整。

为何常见:仿真工具默认输出代码覆盖率,数字直观,容易造成“数字到位=质量到位”的错觉。

误区为了显得专业,把能想到的每条信号性质都写成断言,导致仿真性能骤降,报告里堆满无价值的违规信息。

正解断言要有目的,只验证与协议、安全、核心功能强相关的性质。过量断言会显著增加仿真内存与时间开销,还会产生大量误报。这就像在路口所有角落堆满摄像头却没有分析系统,只是在浪费电力。

为何常见:担心写漏,又缺乏“验证计划驱动”的思维,误把数量当质量。

误区总以为只要随机仿真跑得足够久,那些未覆盖的 bin 总会自动被命中。

正解约束随机仿真的状态空间极大,很多高价值场景概率极低,纯靠延长仿真时间如同守株待兔。应该分析未覆盖 bin 的语义,写定向约束或补充 sequence,这正是覆盖率分析存在的意义。

为何常见:延长仿真时间成本最低,看起来也在“努力”,实际上掩盖了测试设计缺乏针对性的问题。

误区以为功能覆盖率达到 100% 才能流片,否则就是验证没过关。

正解业内通常会把不可达的 bin 在充分论证后排除,并对剩余未覆盖项做合理性分析。预设目标阈值(比如 95%~98%)本质是风险与成本的平衡。盲目追求 100% 既浪费算力,也未必提升真实质量。

为何常见:对“覆盖率”字面意义的机械理解,忽略了不可达场景与工程折衷的现实。

面试题

Q1. SVA 中立即断言和并发断言的核心区别是?

单选题 · easy

  • A.立即断言同时检查多个时钟周期
  • B.并发断言由时钟驱动持续采样← 正确答案
  • C.立即断言依赖覆盖组来触发
  • D.并发断言只能用于初始块

答案:B。立即断言在仿真执行到当前语句时立刻求值,只检查当前时刻;并发断言以时钟沿为节奏,自动持续采样并检查跨拍时序。就像抓拍照片与持续录像的区别。A 把立即断言说反了,C、D 则混淆了断言与覆盖组、过程块的概念。

Q2. a |-> b 蕴含操作符的含义是?

单选题 · easy

  • A.a成立时b在同一拍必须成立← 正确答案
  • B.b成立后反过来要求a成立
  • C.a和b必须永远保持相反
  • D.只要b不成立就会中断仿真

答案:A。|-> 是重叠蕴含,意思是“如果 a 成立,则 b 必须在同一拍成立”;|=> 才是下一拍检查。B 颠倒了因果方向,C、D 把蕴含语义误解为相等或强制中断。

Q3. a[*3] 在 SVA 中表示什么?

单选题 · mid

  • A.表示a连续三个周期都为真← 正确答案
  • B.表示a至少出现且允许间断
  • C.表示a出现三次且必须重叠
  • D.表示a连续三个周期都为假

答案:A。[*3] 是连续重复操作符,要求信号在连续 3 个时钟周期都为真,等价于 a ##1 a ##1 a。B 描述的是 [->3],C 说法含糊,D 把为真写成了为假,均不正确。

Q4. covergroup 中用于将信号取值划分箱格的关键字是?

单选题 · mid

  • A.coverpoint 声明一个覆盖点
  • B.bins 将信号取值划分为箱格← 正确答案
  • C.cross 对多个覆盖点取交集
  • D.sample 通知工具结束仿真

答案:B。coverpoint 定义需要采样的信号,bins 才是把该信号的各个取值划分成具体箱格的机制。cross 负责交叉组合,sample 触发采样流程而非结束仿真,因此选 B。

Q5. ##1 操作符的作用是?

单选题 · mid

  • A.把两个事件的间隔延迟一拍← 正确答案
  • B.表示对信号逻辑取反操作
  • C.表示前件重复出现三次
  • D.表示两个信号逻辑与操作

答案:A。##1 是 SVA 中最核心的时钟延迟操作符,表示前后两个事件之间间隔一个时钟周期。取反是 ! 或 ~,重复是 [*n],逻辑与是 &&,B、C、D 均张冠李戴。

Q6. 覆盖率闭合的签署条件,通常不包括下列哪项?

单选题 · hard

  • A.行覆盖率到达一百并且排除不可达行
  • B.功能覆盖率不低于预先设定的阈值
  • C.所有严重错误修复且回归全部通过
  • D.每个断言都至少报告过一次错误← 正确答案

答案:D。签署条件看的是“覆盖率达标、bug 清零”,而不是“断言必须报过错”。断言报错说明发现问题,但验证目标是把问题修复到不再报错。D 把失败当成了成果,恰恰颠倒了验证的目标。

Q7. 关于并发断言,下列说法正确的是?

多选题 · mid

  • A.并发断言由时钟沿自动采样并评估← 正确答案
  • B.并发断言只能写在同一模块内部
  • C.并发断言能检查跨时钟周期关系← 正确答案
  • D.并发断言必须依赖功能覆盖率数据

答案:AC。并发断言的采样与评估由时钟沿驱动,且能通过 ##1、蕴含等结构检查跨拍时序,所以 A、C 正确。它可以在模块、接口、程序等位置声明,并非只能在同一模块内部;它与功能覆盖率是两套独立机制,D 错误。

Q8. 下列描述 SVA 操作符语义正确的有哪些?

多选题 · hard

  • A.a 成立后的下一拍开始检查 b← 正确答案
  • B.a 连续重复三拍等价于取反操作
  • C.a 连续重复两拍等价于 a##1a← 正确答案
  • D.a until b 表示 b 永远不能成立

答案:AC。a |=> b 表示 a 成立后下一拍检查 b,A 正确。a[*2] 展开为 a ##1 a,C 正确。[->3] 是非连续重复而非取反,B 错误。until 表示在 b 成立前 a 持续为真,并非 b 永远不能成立,D 错误。

Q9. 下列哪项属于代码覆盖率?

单选题 · easy

  • A.行覆盖率衡量每行是否被执行← 正确答案
  • B.功能覆盖率衡量设计意图实现
  • C.断言覆盖率只统计断言数量
  • D.交叉覆盖率只看交叉组合箱格

答案:A。行覆盖率衡量每行 RTL 代码是否被执行过,是代码覆盖率的典型成员。功能覆盖率、交叉覆盖率属于功能覆盖率体系,断言覆盖率更关注断言触发情况,因此只有 A 属于代码覆盖率。

Q10. 关于功能覆盖率收集,有效做法包括?

多选题 · mid

  • A.covergroup 收集关注点的覆盖情况← 正确答案
  • B.bins 对信号取值做精细划分← 正确答案
  • C.代码覆盖率完全等效于功能覆盖
  • D.cross 组合多个覆盖点得到交叉← 正确答案

答案:ABD。covergroup 定义覆盖组,bins 划分取值箱格,cross 生成交叉覆盖,A、B、D 都是功能覆盖率的正确手段。C 错在把代码覆盖率与功能覆盖率等同,二者衡量的是不同维度:前者看执行,后者看设计意图。