`define 和`undef指令提供了文本宏替换功能,以便使用有意义的名称来表示常用的文本片段。例如,在整个文本描述中经常重复使用常数的情况下,文本宏将非常有用,因为如果需要更改常数的值,只需修改整个文本描述中的一处即可。另外,文本宏功能不受编译器指令 `resetall的影响。
下面首先介绍`define指令:
指令 `define 可创建一个用于文本替换的宏(macro)。该指令既可在模块定义内部使用,也可在模块定义外部使用。定义文本宏后,可在源代码中使用 (`) 字符,后面跟宏名。编译器将用宏的文本代替字符串 `text_macro_name 及其后面的实际参数。所有编译器指令都应被视为预定义的宏名,但将编译器指令重新定义为宏名是非法的。文本宏可以定义参数,这样就可以为每种用途定制宏。`define的使用语法规则如下表所示:
宏文本(macro text)可以是与文本宏名称(text macro name)在同一行中指定的任意文本。如果需要用多行来指定宏文本,换行符前应加上反斜线 (\)。第一个没有反斜线的换行符将结束宏文本。
当使用形式参数定义文本宏时,形式参数的范围应延伸至宏文本的末尾,形式参数在宏文本中的使用方式与标识符相同。如果使用形式参数,则应在宏名称后用括号括起形式参数名称列表。形式参数名称应为 simple_identifiers,以逗号分隔,也可使用空白分隔。左括号应紧跟文本宏名称,中间不留空格。
如果文本中包含单行注释(即用 // 字符指定的注释),则该注释不会成为替换文本的一部分。宏文本可以是空白的,在这种情况下,文本宏定义为空,使用宏时不会替换文本。在源代码中使用文本宏的语法见下表:
对于不带参数的宏,源代码中每出现一次 `text_macro_name,文本应按原样替换。但是,对于有一个或多个参数的文本宏,应通过将每个形式参数替换为宏用法中实际参数的表达式来进行扩展。要使用带参数定义的宏,文本宏名称后应加上括号中的实际参数列表,以逗号分隔。文本宏名称和左括号之间不能留白,且实际参数个数应与形式参数个数一致。文本宏名称一旦定义,就可以在源代码描述的任何地方使用;也就是说,没有范围限制。文本宏可以交互式定义和使用。
例子1:
注意,为宏文本指定的文本不得在“注释、数字、字符串、标识符、关键字以及运算符”这些词性之间分割,例如下面的错误例子就把字符串分割了:
例子2:
当有表达式用作实际参数时,表达式将被全部替换。如果形式参数在宏文本中使用了不止一次,这可能会导致表达式被评估不止一次。例如:
将被编译器解释为:
在这里,p + q 和 r + s 这两个表达式中的较大表达式将被求值两次。
define 这个词被称为编译器指令关键字,它不属于正常的关键字集。因此,Verilog HDL 源代码描述中的普通标识符可以与编译器指令关键字相同(尽管不建议这样做)。我们应以下问题:
a) 文本宏名称可能与编译器指令关键字不同。
b) 文本宏名称可能会重复使用用作普通标识符的名称。例如,signal_name 和`signal_name 是不同的。
c) 允许重新定义文本宏;在源文本中遇到宏名时,以编译器读取的特定文本宏的最新定义为准。
宏文本可包含对其他文本宏的使用。这些用法应在原始宏被替换后,而不是在宏定义时替换。如果一个宏直接或间接扩展到包含其自身另一种用法(递归宏)的文本,则属于错误。
下面再介绍` undef指令:
指令 `undef 将取消先前定义的文本宏。如果试图用`undef指令取消先前根本就未定义的文本宏,可能会导致警告。下表提供了 `undef 编译器指令的语法:
未定义的文本宏没有任何价值,就像从未存在过一样。
点赞加关注博主(ID:FPGA小飞)的博文,咱们一起系统学习verilog最终标准IEEE Std 1364-2005吧!