4 布尔表达式与HDL信号引用
4.1 问题背景
PSL属性中的核心逻辑原子是布尔表达式。无论是描述“当条件成立时得到响应”的蕴含属性,还是约束“不允许出现某状态”的拒绝属性,最终都要落在具体的信号引用与布尔运算上。实际验证中,大量初学错误并不来自属性时态逻辑本身,而是来自信号引用方式不准确:向量位序写反、位选择方向错误、整向量直接当布尔量使用、跨模块路径缺失、运算符优先级歧义等。
本章学习目标:
- 掌握信号、向量、位选择、位切片在PSL中的正确引用方式;
- 理解布尔表达式在PSL时钟采样上下文中的求值语义;
- 写出无歧义、可综合、可验证的信号引用表达式。
4.2 核心概念
信号(Signal):PSL中直接引用的HDL线网或寄存器量,通常为单比特标量,如 rst_n、hsel。标量信号可以被 PSL 直接当作布尔量使用,但工程上建议显式写成 (rst_n == 1'b1),使验证语义更清晰。
向量(Vector):多位宽总线量,如 haddr[31:0]、data[7:0]。向量不能直接作为布尔量参与 &&、|| 运算,必须通过比较运算或位选择将其转化为单比特值。
位选择与切片(Bit Select / Slice):从向量中取出单比特或连续子段。Verilog 风格为 bus[i]、bus[msb:lsb];VHDL 风格为 bus(i)、bus(msb downto lsb)。PSL 遵循 HDL 原生的位选择规则。
表达式运算符:PSL 布尔表达式支持逻辑非 !、逻辑与 &&、逻辑或 ||、关系比较 ==、!=、<、<=、>=、> 等。运算符优先级与 C/Verilog 基本一致,但复杂表达式必须加括号。
下图展示了从HDL信号引用到PSL求值上下文的核心路径:
4.3 原理机制:布尔表达式在 PSL 中的求值上下文
PSL 中的布尔表达式不是在仿真器任意时刻连续求值的组合逻辑,而是在时钟边界上采样后得到的确定真值。求值上下文由三部分决定:
- 时钟约束:表达式在
default clock指定的边沿计算,例如posedge clk; - 采样语义:时钟边沿触发时,所有信号值取采样值,禁止组合竞争依赖;
- 不确定状态:形式验证中,X/Z 不参与真值判断,而是按未知态处理。
重要区别:RTL 中的 if (bus) 依赖 Verilog 的“非 0 即真”规则;PSL 布尔表达式则建议显式使用比较运算符,避免向量隐式转换带来歧义。
// 不推荐:向量隐式转布尔
assert always (bus) -> p;
// 推荐:显式比较
assert always (bus != 3'b000) -> p;
4.4 编写无歧义布尔表达式的流程步骤
- 定位信号层次:确认信号在 PSL unit 或 HDL 设计层次中可见,必要时使用
hdlpath完整路径; - 确认类型与位宽:区分标量/向量,记录位宽及位序声明;
- 选择位选择或切片:对于总线信号,按需取出特定位或子段,保证索引方向与声明一致;
- 选择运算符:使用逻辑运算符、关系运算符,将子表达式组合为单比特结果;
- 加括号明确优先级:不依赖记忆中的优先级,为每个子表达式加括号;
- 绑定时钟与采样上下文:检查
default clock是否覆盖当前属性; - 语义检查:在验证工具中运行语法与静态检查,确认表达式无类型错误。
4.5 案例说明:AHB 桥接场景下的信号引用
假设一个 AHB-APB 桥接器,DUT 接口声明片段如下:
module ahb_apb_bridge (
input wire hclk,
input wire hresetn,
input wire hsel,
input wire hwrite,
input wire [2:0] hsize,
input wire [31:0] haddr
);
PSL 属性要求:当主设备发起 4 字节或 8 字节写传输时,地址必须按传输宽度对齐。
unit psl_ahb_example {
default clock = (posedge hclk);
default disable iff (hresetn == 1'b0);
// 规则1:4字节传输时,地址低2位必须为 0
aligned_4byte: assert always
(hsel && hwrite && (hsize == 3'b010))
-> (haddr[1:0] == 2'b00);
// 规则2:8字节传输时,地址低3位必须为 0
aligned_8byte: assert always
(hsel && hwrite && (hsize == 3'b011))
-> (haddr[2:0] == 3'b000);
}
案例要点:
hsel && hwrite使用逻辑与,两个标量信号组合为传输有效条件;hsize == 3'b010通过比较将向量转化为布尔结果;haddr[1:0]与haddr[2:0]的切片方向与 Verilog 声明完全一致。
4.6 信号引用形式速查表
| 表达式形式 | HDL/PSL 作用 | 使用建议 | 常见错误 |
|---|---|---|---|
sig |
标量信号作为布尔量 | 建议显式写 sig == 1'b1 |
隐式使用标量真值产生歧义 |
bus |
整个向量 | 不能直接作为布尔量,须比较或位选择 | 把向量当布尔量参与逻辑运算 |
bus[3] |
取第 3 位 | 可用于布尔子表达式 | 位序方向写反 |
bus[7:4] |
取连续 4 位切片 | 切片方向与声明一致 | 写成 [4:7] |
bus[addr +: 8] |
Verilog-2001+ 递增切片 | 动态索引时使用 | 在 VHDL 中不可用 |
bus(7 downto 4) |
VHDL 切片 | VHDL 工程使用,保持位序 | 与 Verilog 风格混淆 |
4.7 误区提醒
- 误区 1:位选择方向写反。信号声明为
data[7:0]时,data[0:3]非法或语义错误。PSL 严格遵守 HDL 声明位序。 - 误区 2:把位运算符当作逻辑运算符。在 PSL 序列中
&代表重叠(overlap)操作,而非逻辑与。布尔表达式应使用&&、||、!。 - 误区 3:忽略运算符优先级。例如
a && b || c != d会被解析为(a && b) || (c != d),而不是按阅读直觉从左到右。务必加括号。 - 误区 4:向量整体直接作真值。
assert always (bus)在 Verilog 语义下可能合法,但 PSL 形式验证不推荐,应改为bus != 0。 - 误区 5:忘记绑定
default clock。没有时钟边界的布尔表达式在属性中无法确定采样时刻。
4.8 实践清单
写信号引用表达式前的 8 项检查:
- 信号是否在当前 PSL unit 或 HDL 层次可见;
- 向量位宽与位序是否和声明一致;
- 位选择、切片索引是否在有效范围内;
- 向量是否通过比较运算转化为布尔值;
- 复杂表达式是否已用括号显式分组;
- 当前属性是否已被
default clock覆盖; - 是否避免使用位运算符
&、|作逻辑运算; - 是否在验证工具中完成了静态语义检查。
工程建议:评审 PS 属性时,将信号引用部分单独列出,与 RTL 信号声明逐一比对。对位选择、切片和跨模块路径的审查要优先于逻辑运算符审查,因为这类错误定位成本最高。