Verilog运算符

Verilog 中的运算符是构成表达式的基础,用于对变量进行操作。Verilog 提供了非常丰富的运算符,其中一些与软件编程语言(如 C 语言)类似,但也有一些是专门为硬件描述而设计的。

以下是 Verilog 运算符的详细分类和说明:

一、运算符


1. 算术运算符

这些运算符执行算术计算。如果操作数中有 xz,则整个结果也是 x

运算符 描述 示例
+ 加法 c = a + b;
- 减法 c = a - b;
* 乘法 c = a * b;
/ 除法 c = a / b; // 整数除法
% 取模 c = a % b; // 求余数
** 幂运算 c = a ** 2; // a 的平方

注意:

  • 对于 regwire 类型,操作通常被视为无符号整数

  • 除法和对 2 的幂次取模可以被综合,但一般的除法和取模运算通常不可综合,或者会生成非常复杂的电路。


2. 关系运算符

比较两个值的大小关系,返回一个布尔值(1'b1 表示真,1'b0 表示假)。如果操作数中有 xz,则结果为 x

运算符 描述 示例
> 大于 a > b
< 小于 a < b
>= 大于等于 a >= b
<= 小于等于 a <= b
== 逻辑相等 a == b
!= 逻辑不等 a != b

3. 等式运算符

比关系运算符更严格,它们会比较所有的位,包括 xz

运算符 描述 示例
=== 逻辑相等(Case Equality) a === b
!== 逻辑不等(Case Inequality) a !== b

== vs === 的区别:

  • a == b:如果 ab 中有 xz,结果为 x

  • a === b:会逐位精确比较,0, 1, x, z 都必须完全一致才返回 1。例如 1'bx === 1'bx 的结果是 1'b1,而 1'bx == 1'bx 的结果是 1'bx

综合注意: ===!== 通常不可综合,主要用于仿真和测试平台。


4. 逻辑运算符

对操作数进行逻辑运算,操作数被视为布尔值(非零为真,零为假)。返回一位的真假值。

运算符 描述 示例
! 逻辑非 if (!enable) ...
&& 逻辑与 if (a && b) ...
|| 逻辑或 `if (a

5. 按位运算符

对操作数的每一位进行独立的逻辑运算。如果操作数长度不同,较短的会在高位补零。

| 运算符 | 描述 | 示例(设 a=4'b1100, b=4'b1010) |
|------|------|----------------------------|---|---|
| ~ | 按位取反 | ~a 得到 4'b0011 |
| & | 按位与 | a & b 得到 4'b1000 |
| | | 按位或 | a | b 得到 4'b1110 |||
| ^ | 按位异或 | a ^ b 得到 4'b0110 |
| ^~ | 按位同或 | a ^~ b 得到 4'b1001 |


6. 缩减运算符

单个操作数 的所有位进行运算,最终产生一位的结果。可以看作是一系列按位运算的累积。

运算符 描述 示例(设 a=4'b1100)
& 缩减与 &a 等价于 1 & 1 & 0 & 0,结果为 1'b0
~& 缩减与非 ~&a 结果为 1'b1
| 缩减或 |a`等价于1
~| 缩减或非 ~|a结果为1'b0
^ 缩减异或 ^a 等价于 1 ^ 1 ^ 0 ^ 0,结果为 1'b0
^~ 缩减同或 ~^a 结果为 1'b1

7. 移位运算符

将操作数向左或向右移动指定的位数。空出的位用 0 填充。

运算符 描述 示例(设 a=4'b1101)
<< 逻辑左移 a << 2 得到 4'b0100
>> 逻辑右移 a >> 1 得到 4'b0110
<<< 算术左移 与逻辑左移 << 相同
>>> 算术右移 空出的位用符号位 填充。 对于有符号数 $signed(a) >>> 1,结果为 4'b1110

注意: 算术移位要求操作数被声明为有符号数(例如 reg signed [3:0] a;)或使用 $signed() 系统函数。


8. 条件运算符

这是一个三目运算符,根据条件选择两个表达式中的一个。

运算符 描述 示例
?: 条件运算符 assign out = sel ? a : b; // 2选1 MUX

这非常有用,可以直接综合成一个多路选择器。


9. 连接运算符

用于将多个操作数的位连接起来,形成一个新的、更宽的向量。

运算符 描述 示例
{} 连接 c = {a[3:0], b[1:0]}; // 将 a 的低 4 位和 b 的低 2 位连接成一个 6 位向量
{``{}} 复制 d = {4{a}}; // 等价于 {a, a, a, a}

10. 赋值运算符

主要用于过程赋值(在 alwaysinitial 块中)。

运算符 描述 示例
= 阻塞赋值 b = a; // 立即执行
<= 非阻塞赋值 b <= a; // 在块结束时才执行

关键区别(非常重要!):

  • 阻塞赋值 =:顺序执行。语句执行完毕后才执行下一条语句。常用于组合逻辑建模。

  • 非阻塞赋值 <= :并行执行。所有右边的表达式同时求值,在 always 块结束时才同时赋值给左边。必须用于时序逻辑(寄存器)的建模。

好的编码风格:

  • 在描述组合逻辑的 always @(*) 块中,使用 阻塞赋值 =

  • 在描述时序逻辑的 always @(posedge clk) 块中,使用 非阻塞赋值 <=


二、运算符优先级总结

从最高到最低排列:

优先级 运算符类型 运算符 描述
最高 单目运算符 + - ! ~ & ~& ` ~
乘除取模 * / % 乘法、除法、取模
加减 + - 加法、减法
移位 << >> <<< >>> 逻辑左移/右移、算术左移/右移
关系 < <= > >= 小于、小于等于、大于、大于等于
等式 == != === !== 逻辑相等、逻辑不等、 case 相等、 case 不等
缩减与 & ~& 按位与、按位与非
缩减异或 ^ ~^ 按位异或、按位同或
缩减或 ` ~
逻辑与 && 逻辑与
逻辑或 `
最低 条件 ?: 条件运算符(三目运算符)

最佳实践: 为了代码清晰并避免错误,强烈建议使用括号 () 来明确指定运算的优先级,而不是依赖记忆。

希望这个全面的总结能帮助你更好地理解和使用 Verilog 运算符!

相关推荐
syker2 小时前
NEWBASIC 2.06.7 API 帮助与用户使用手册
开发语言·人工智能·机器学习·自动化
努力还债的学术吗喽2 小时前
【项目】pyqt5基于python的照片整蛊项目
开发语言·python·qt
m0_569531012 小时前
shell(4)--shell脚本中的循环:(if循环,for,while,until)和退出循环(continue,break, exit)
开发语言
星释2 小时前
Rust 练习册 :掌握文本处理与词频统计
开发语言·后端·rust
火龙谷2 小时前
DrissionPage遇到iframe
开发语言·前端·javascript
HalvmånEver3 小时前
Linux的第二章 : 基础的指令(二)
linux·运维·服务器·开发语言·学习
egoist20233 小时前
[linux仓库]线程同步与生产者消费者模型[线程·陆]
linux·c语言·开发语言·线程同步·阻塞队列·生产者消费者模型
资深web全栈开发5 小时前
[特殊字符]图解 Golang 反射机制:从底层原理看动态类型的秘密
开发语言·后端·golang
独隅9 小时前
在 Lua 中,你可以使用 `os.date()` 函数轻松地将时间戳转换为格式化的时间字符串
开发语言·lua