掌握 Verilog 语法:关键规则与最佳实践
Verilog 词法约定类似 C 语言,包含 token 流。词法 token 可由一个或多个字符组成,包括注释、关键字、数字、字符串或空白。所有行应以分号 ; 结尾。
Verilog 区分大小写,var_a 和 var_A 是不同的。
注释
Verilog 有两种注释方式:
- 单行注释 以
//开始,告诉编译器将该点到行尾视为注释。 - 多行注释 以
/*开始,以*/结束,不能嵌套。
但单行注释可嵌套在多行注释中。
// This is a single line comment
integer a; // Creates an int variable called a, and treats everything to the right of // as a comment
/* This is a multiple-line or block comment */
/* This is /* an invalid nested block comment */ */
/* However, // this one is okay */
// This is also okay
///////////// Still okay
空白字符
空白字符表示空格、制表符、换页符、换行符,通常被 Verilog 忽略,除非用于分隔 token。这有助于代码缩进以提高可读性。
module dut; // 'module' is a keyword, 'dut' is an identifier
reg [8*6:1] name = "Hello!"; // The 2 spaces in the beginning are ignored
但在字符串中,空格和制表符不被忽略。下例中,字符串变量 addr 因保留空格而获得值 "Earth "。
// There is no space in the beginning of this line,
// but there's a space in the string
reg [8*6:1] addr = "Earth ";
endmodule
运算符
三类运算符:一元、二元、三元/条件。
- 一元运算符出现在操作数左侧
- 二元运算符出现在两操作数之间
- 条件运算符有两个独立运算符分隔三个操作数
x = ~y; // ~ is a unary operator, and y is the operand
x = y | z; // | is a binary operator, where y and z are its operands
x = (y > 5) ? w : z; // ?: is a ternary operator, and the expression (y>5), w and z are its operands
若表达式 (y > 5) 为真,变量 x 取 w 的值,否则取 z 的值。
数字格式
我们习惯十进制,但数字也可用 二进制、八进制、十六进制 表示。Verilog 仿真器默认按十进制处理数字。要用不同 基数,需遵循规则。
16 // 十进制 16
0x10 // 十六进制 16
10000 // 二进制 16
20 // 八进制 16
带位宽
带位宽数字表示如下,size 仅用十进制指定位数。
[size]'[base_format][number]
- base_format 可为十进制 ('d/'D)、十六进制 ('h/'H)、八进制 ('o/'O),指定 number 部分的基数。
- number 为连续数字:十进制用 0-9,十六进制用 0-9、A-F。
3'b010; // size=3, binary, value 2
3'd2; // size=3, decimal, value 2
8'h70; // size=8, hex, 0x70 = decimal 112
9'h1FA; // size=9, hex, 0x1FA = decimal 506
4'hA = 4'd10 = 4'b1010 = 4'o12 // 十进制 10 可用四种格式表示
8'd234 = 8'D234 // 基数格式大小写均合法
32'hFACE_47B2; // 下划线分隔 16 位数字以提高可读性
十六进制基数格式时,大写字母合法。
16'hcafe; // 小写合法
16'hCAFE; // 大写合法
32'h1D40_CAFE; // 下划线分隔合法
不带位宽
无 base_format 默认十进制。无 size 默认位数取决于仿真器和机器类型。
integer a = 5423; // 默认十进制
integer a = 'h1AD7; // 无 size,因 a 为 int (32位),存储值 = 32'h0000_1AD7
负数
负数在数字 size 前加减号 -。在 base_format 和 number 间加减号非法。
-6'd3; // 8位负数,存储为 3 的二进制补码
-6'sd9; // 有符号运算
8'd-4; // 非法
字符串
双引号 " " 括起的字符序列称为字符串。不能跨多行,每字符占 1 字节。
"Hello World!" // 12 字符 -> 12 字节
"x + z" // 5 字符
"How are you feeling today ?" // 非法:字符串不能分多行
标识符
标识符 是变量名,用于后续引用。由字母数字 [a-z][A-Z][0-9]、下划线 _ 或美元符 $ 组成,区分大小写。不能以数字或美元符开头。
integer var_a; // 含字母和下划线 -> 合法
integer $var_a; // 以 $ 开头 -> 非法
integer v$ar_a; // 含字母和 $ -> 合法
integer 2var; // 以数字开头 -> 非法
integer var23_g; // 含字母数字和下划线 -> 合法
integer 23; // 仅含数字 -> 非法
关键字
关键字是定义语言结构的保留标识符,均为小写。重要关键字列表如下图。
Verilog 版本演进
Verilog 经历多次修订,1995 到 2001 年间不断增加特性,如下图所示。
Verilog
- Verilog 入门:数字电路设计完整教程
- 掌握 Verilog 拼接操作:实用指南
- 深入理解 Verilog 赋值语句:类型、语法与最佳实践
- Verilog阻塞与非阻塞赋值:关键区别详解
- 掌握Verilog函数:高效RTL设计的复用利器
- 理解Verilog任务:函数vs任务、语法与用法全解析
- Verilog 时钟发生器设计与实现指南
- 掌握 Verilog 数学函数:高效硬件设计的利器
- 掌握 Verilog $timeformat:精度控制与显示格式化
- 理解与打印 Verilog 任意作用域下的 Timescale
- 掌握 Verilog 文件 I/O:打开、读取、写入和关闭
- Verilog 入门指南:Hello World 示例