ASIC-WORLD Verilog(6)运算符
写在前面
在自己准备写一些简单的verilog教程之前,参考了许多资料----asic-world网站的这套verilog教程即是其一。这套教程写得极好,奈何没有中文,在下只好斗胆翻译过来(加了自己的理解)分享给大家。
这是网站原文:Verilog Tutorial
这是系列导航:Verilog教程系列文章导航
算术运算符(Arithmetic Operators)
- 二元运算符:+、-、*、/、%(取模运算符)
- 一元运算符:+、-(这个用来指定符号)
- 整数除法截断任何小数部分
- 模运算的结果符号取第一个操作数的符号
- 如果任何操作数位值是未知值 x,则整个结果值是 x
- 寄存器数据类型用作无符号值(负数以补码形式存储)
这是一些算术运算的示例:
module arithmetic_operators();
initial begin
$display (" 5 + 10 = %d", 5 + 10);
$display (" 5 - 10 = %d", 5 - 10);
$display (" 10 - 5 = %d", 10 - 5);
$display (" 10 * 5 = %d", 10 * 5);
$display (" 10 / 5 = %d", 10 / 5);
$display (" 10 / -5 = %d", 10 / -5);
$display (" 10 %s 3 = %d","%", 10 % 3);
$display (" +5 = %d", +5);
$display (" -5 = %d", -5);
#10 $finish;
end
endmodule
这是仿真结果:
5 + 10 = 15
5 - 10 = -5
10 - 5 = 5
10 * 5 = 50
10 / 5 = 2
10 / -5 = -2
10 % 3 = 1
+5 = 5
-5 = -5
关系运算符(Relational Operators)
运算符 | 描述 |
a < b | a 小于 b |
a > b | a 大于 b |
a <= b | a 小于等于 b |
a >= b | a 大于等于 b |
- 结果是一个标量值(例如 a < b)
- 如果关系为假则结果为0(a 比 b 大)
- 如果关系为真则结果为1(a 小于 b)
- 如果任何操作数具有未知的 x 位则结果为x(如果 a 或 b 包含 X)
注:如果任何操作数是 x 或 z,则该测试的结果将被视为假 (0)
这是一些关系运算的示例:
module relational_operators();
initial begin
$display (" 5 <= 10 = %b", (5 <= 10));
$display (" 5 >= 10 = %b", (5 >= 10));
$display (" 1'bx <= 10 = %b", (1'bx <= 10));
$display (" 1'bz <= 10 = %b", (1'bz <= 10));
#10 $finish;
end
endmodule
这是仿真结果:
5 <= 10 = 1
5 >= 10 = 0
1'bx <= 10 = x
1'bz <= 10 = x
相等运算符(Equality operators)
有两种类型的相等运算符。
运算符 | 描述 |
a === b | a等于b, 包括 x 和 z |
a !== b | a不等于b, 包括 x 和 z |
a == b | a等于b, 结果可能是未知 |
a != b | a不等于b, 结果可能是未知 |
- 操作数逐位比较,如果两个操作数的长度不相同,则补零
- 结果为 0(假)或 1(真)
- 对于 == 和 != 运算符,如果任一操作数包含 x 或 z,则结果为 x
- 对于 === 和 !== 运算符,带有 x 和 z 的位包含在比较中并且必须匹配才能使结果为真
注:结果始终为 0 或 1。
这是一些相等运算的示例:
module equality_operators();
initial begin
// Case Equality
$display (" 4'bx001 === 4'bx001 = %b", (4'bx001 === 4'bx001));
$display (" 4'bx0x1 === 4'bx001 = %b", (4'bx0x1 === 4'bx001));
$display (" 4'bz0x1 === 4'bz0x1 = %b", (4'bz0x1 === 4'bz0x1));
$display (" 4'bz0x1 === 4'bz001 = %b", (4'bz0x1 === 4'bz001));
// Case Inequality
$display (" 4'bx0x1 !== 4'bx001 = %b", (4'bx0x1 !== 4'bx001));
$display (" 4'bz0x1 !== 4'bz001 = %b", (4'bz0x1 !== 4'bz001));
// Logical Equality
$display (" 5 == 10 = %b", (5 == 10));
$display (" 5 == 5 = %b", (5 == 5));
// Logical Inequality
$display (" 5 != 5 = %b", (5 != 5));
$display (" 5 != 6 = %b", (5 != 6));
#10 $finish;
end
endmodule
这是仿真结果:
4'bx001 === 4'bx001 = 1
4'bx0x1 === 4'bx001 = 0
4'bz0x1 === 4'bz0x1 = 1
4'bz0x1 === 4'bz001 = 0
4'bx0x1 !== 4'bx001 = 1
4'bz0x1 !== 4'bz001 = 1
5 == 10 = 0
5 == 5 = 1
5 != 5 = 0
5 != 6 = 1
逻辑运算符(Logical Operators)
运算符 | 描述 |
! | 逻辑非 |
&& | 逻辑与 |
|| | 逻辑或 |
- && 和 || 连接的表达式 从左到右计算
- 结果是一个标量值:
- 如果关系为假则为 0;如果关系为真则为 1
- 如果任何操作数有 x(未知)位则结果为x
这是一些逻辑运算的示例:
module logical_operators();
initial begin
// Logical AND
$display ("1'b1 && 1'b1 = %b", (1'b1 && 1'b1));
$display ("1'b1 && 1'b0 = %b", (1'b1 && 1'b0));
$display ("1'b1 && 1'bx = %b", (1'b1 && 1'bx));
// Logical OR
$display ("1'b1 || 1'b0 = %b", (1'b1 || 1'b0));
$display ("1'b0 || 1'b0 = %b", (1'b0 || 1'b0));
$display ("1'b0 || 1'bx = %b", (1'b0 || 1'bx));
// Logical Negation
$display ("! 1'b1 = %b", (! 1'b1));
$display ("! 1'b0 = %b", (! 1'b0));
#10 $finish;
end
endmodule
这是仿真结果:
1'b1 && 1'b1 = 1
1'b1 && 1'b0 = 0
1'b1 && 1'bx = x
1'b1 || 1'b0 = 1
1'b0 || 1'b0 = 0
1'b0 || 1'bx = x
! 1'b1 = 0
! 1'b0 = 1
按位运算符(Bit-wise Operators)
按位运算符对两个操作数执行按位运算。他们取一个操作数中的每一位,然后用另一个操作数中的相应位执行操作。如果一个操作数比另一个短,它将在左侧用零扩展以匹配较长操作数的长度。
运算符 | 描述 |
~ | 非 |
& | 与 |
| | 或 |
^ | 异或 |
^~ or ~^ | 同或 |
- 计算包括未知位,方式如下:
- ~x = x
- 0 & x = 0
- 1 & x = x & x = x
- 1 | x = 1
- 0 | x = x | x = x
- 0 ^ x = 1 ^ x = x ^ x = x
- 0 ^ ~x = 1 ^ ~x = x ^ ~x = x
- 当操作数的位长度不相等时,较短的操作数将在最高有效位位置补零
这是一些按位运算的示例:
module bitwise_operators();
initial begin
// Bit Wise Negation
$display (" ~4'b0001 = %b", (~4'b0001));
$display (" ~4'bx001 = %b", (~4'bx001));
$display (" ~4'bz001 = %b", (~4'bz001));
// Bit Wise AND
$display (" 4'b0001 & 4'b1001 = %b", (4'b0001 & 4'b1001));
$display (" 4'b1001 & 4'bx001 = %b", (4'b1001 & 4'bx001));
$display (" 4'b1001 & 4'bz001 = %b", (4'b1001 & 4'bz001));
// Bit Wise OR
$display (" 4'b0001 | 4'b1001 = %b", (4'b0001 | 4'b1001));
$display (" 4'b0001 | 4'bx001 = %b", (4'b0001 | 4'bx001));
$display (" 4'b0001 | 4'bz001 = %b", (4'b0001 | 4'bz001));
// Bit Wise XOR
$display (" 4'b0001 ^ 4'b1001 = %b", (4'b0001 ^ 4'b1001));
$display (" 4'b0001 ^ 4'bx001 = %b", (4'b0001 ^ 4'bx001));
$display (" 4'b0001 ^ 4'bz001 = %b", (4'b0001 ^ 4'bz001));
// Bit Wise XNOR
$display (" 4'b0001 ~^ 4'b1001 = %b", (4'b0001 ~^ 4'b1001));
$display (" 4'b0001 ~^ 4'bx001 = %b", (4'b0001 ~^ 4'bx001));
$display (" 4'b0001 ~^ 4'bz001 = %b", (4'b0001 ~^ 4'bz001));
#10 $finish;
end
endmodule
这是仿真结果:
~4'b0001 = 1110
~4'bx001 = x110
~4'bz001 = x110
4'b0001 & 4'b1001 = 0001
4'b1001 & 4'bx001 = x001
4'b1001 & 4'bz001 = x001
4'b0001 | 4'b1001 = 1001
4'b0001 | 4'bx001 = x001
4'b0001 | 4'bz001 = x001
4'b0001 ^ 4'b1001 = 1000
4'b0001 ^ 4'bx001 = x000
4'b0001 ^ 4'bz001 = x000
4'b0001 ~^ 4'b1001 = 0111
4'b0001 ~^ 4'bx001 = x111
4'b0001 ~^ 4'bz001 = x111
规约运算符(Reduction Operators)
运算符 | 描述 |
& | 规约与 |
~& | 规约与非 |
| | 规约或 |
~| | 规约或非 |
^ | 规约异或 |
^~ or ~^ | 规约同或 |
- 归约运算符是一元的。
- 它们对单个操作数执行按位运算以产生单个位结果。
- 归约一元 NAND 和 NOR 运算符分别作为 AND 和 OR 运行,但它们的输出取反。
- 如前所述处理未知位。
这是一些规约运算的示例:
module reduction_operators();
initial begin
// Bit Wise AND reduction
$display (" & 4'b1001 = %b", (& 4'b1001));
$display (" & 4'bx111 = %b", (& 4'bx111));
$display (" & 4'bz111 = %b", (& 4'bz111));
// Bit Wise NAND reduction
$display (" ~& 4'b1001 = %b", (~& 4'b1001));
$display (" ~& 4'bx001 = %b", (~& 4'bx001));
$display (" ~& 4'bz001 = %b", (~& 4'bz001));
// Bit Wise OR reduction
$display (" | 4'b1001 = %b", (| 4'b1001));
$display (" | 4'bx000 = %b", (| 4'bx000));
$display (" | 4'bz000 = %b", (| 4'bz000));
// Bit Wise OR reduction
$display (" ~| 4'b1001 = %b", (~| 4'b1001));
$display (" ~| 4'bx001 = %b", (~| 4'bx001));
$display (" ~| 4'bz001 = %b", (~| 4'bz001));
// Bit Wise XOR reduction
$display (" ^ 4'b1001 = %b", (^ 4'b1001));
$display (" ^ 4'bx001 = %b", (^ 4'bx001));
$display (" ^ 4'bz001 = %b", (^ 4'bz001));
// Bit Wise XNOR
$display (" ~^ 4'b1001 = %b", (~^ 4'b1001));
$display (" ~^ 4'bx001 = %b", (~^ 4'bx001));
$display (" ~^ 4'bz001 = %b", (~^ 4'bz001));
#10 $finish;
end
endmodule
这是仿真结果:
& 4'b1001 = 0
& 4'bx111 = x
& 4'bz111 = x
~& 4'b1001 = 1
~& 4'bx001 = 1
~& 4'bz001 = 1
| 4'b1001 = 1
| 4'bx000 = x
| 4'bz000 = x
~| 4'b1001 = 0
~| 4'bx001 = 0
~| 4'bz001 = 0
^ 4'b1001 = 0
^ 4'bx001 = x
^ 4'bz001 = x
~^ 4'b1001 = 1
~^ 4'bx001 = x
~^ 4'bz001 = x
移位运算符(Shift Operators)
运算符 | 描述 |
<< | 左移 |
>> | 右移 |
- 左操作数移动右操作数给定的位数
- 腾出来的位置用零填充
这是一些移位运算的示例:
module shift_operators();
initial begin
// Left Shift
$display (" 4'b1001 << 1 = %b", (4'b1001 << 1));
$display (" 4'b10x1 << 1 = %b", (4'b10x1 << 1));
$display (" 4'b10z1 << 1 = %b", (4'b10z1 << 1));
// Right Shift
$display (" 4'b1001 >> 1 = %b", (4'b1001 >> 1));
$display (" 4'b10x1 >> 1 = %b", (4'b10x1 >> 1));
$display (" 4'b10z1 >> 1 = %b", (4'b10z1 >> 1));
#10 $finish;
end
endmodule
这是仿真结果:
4'b1001 << 1 = 0010
4'b10x1 << 1 = 0x10
4'b10z1 << 1 = 0z10
4'b1001 >> 1 = 0100
4'b10x1 >> 1 = 010x
4'b10z1 >> 1 = 010z
拼接运算符(Concatenation Operator)
- 拼接使用大括号字符 { 和 } 表示,用逗号分隔其中的表达式
- 示例:+ {a, b[3:0], c, 4'b1001} // 如果 a 和 c 是 8 位数字,则结果有 24 位
- 拼接中不允许有未定大小的常数
这是一些拼接运算的示例:
module concatenation_operator();
initial begin
// concatenation
$display (" {4'b1001,4'b10x1} = %b", {4'b1001,4'b10x1});
#10 $finish;
end
endmodule
这是仿真结果:
{4'b1001,4'b10x1} = 100110x1
复制运算符(Replication Operators)
复制运算符用于将一组位复制 n 次。假设你有一个 4 位变量,你想复制它 4 次以获得一个 16 位变量:那么我们可以使用复制运算符。
运算符 | 描述 |
{n{m}} | 复制m的值n次 |
- 可以使用重复的乘数(必须是常量):
- {3{a}} // 这相当于 {a, a, a}
- 嵌套拼接和复制运算符是可能的:
- {b, {3{c, d}}} // 这相当于 {b, c, d, c, d, c, d}
这是一些复制运算的示例:
module replication_operator();
initial begin
// replication
$display (" {4{4'b1001}} = %b", {4{4'b1001}});
// replication and concatenation
$display (" {4{4'b1001,1'bz}} = %b", {4{4'b1001,1'bz}});
#10 $finish;
end
endmodule
这是仿真结果:
{4{4'b1001} = 1001100110011001
{4{4'b1001,1'bz} = 1001z1001z1001z1001z
条件运算符(Conditional Operators)
- 条件运算符具有以下类似 C 的格式:
- cond_expr ? true_expr : false_expr
- true_expr 或 false_expr 的计算结果取决于 cond_expr 的计算结果(true 或 false)
这是一些条件运算的示例:
module conditional_operator();
wire out;
reg enable,data;
// Tri state buffer
assign out = (enable) ? data : 1'bz;
initial begin
$display ("time\t enable data out");
$monitor ("%g\t %b %b %b",$time,enable,data,out);
enable = 0;
data = 0;
#1 data = 1;
#1 data = 0;
#1 enable = 1;
#1 data = 1;
#1 data = 0;
#1 enable = 0;
#10 $finish;
end
endmodule
这是仿真结果:
time enable data out
0 0 0 z
1 0 1 z
2 0 0 z
3 1 0 0
4 1 1 1
5 1 0 0
6 0 0 z