写在前面
在自己准备写一些简单的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;
endendmodule
这是仿真结果:
5 + 10 = 155 - 10 = -510 - 5 = 510 * 5 = 5010 / 5 = 210 / -5 = -210 % 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;
endendmodule
这是仿真结果:
5 <= 10 = 15 >= 10 = 01'bx <= 10 = x1'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;
endendmodule
这是仿真结果:
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;
endendmodule
这是仿真结果:
1'b1 && 1'b1 = 11'b1 && 1'b0 = 01'b1 && 1'bx = x1'b1 || 1'b0 = 11'b0 || 1'b0 = 01'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;
endendmodule
这是仿真结果:
~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;
endendmodule
这是仿真结果:
& 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;
endendmodule
这是仿真结果:
4'b1001 << 1 = 00104'b10x1 << 1 = 0x104'b10z1 << 1 = 0z104'b1001 >> 1 = 01004'b10x1 >> 1 = 010x4'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;
endendmodule
这是仿真结果:
{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;
endendmodule
这是仿真结果:
{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