ystemVerilog(SV) 中宏的几种常见类型:类对象宏(Object-like Macro)、类函数宏(Function-like Macro) 和 链式宏(Chain Macro)。
1. 类对象宏(Object-like Macro)
类对象宏是最简单的一种宏,它只是一个简单的标识符,用来替换一些固定的代码片段。可以把它看作是一个简单的文本替换工具,就像是数据对象一样使用。
举个例子:
1 | `define WIDTH 8 |
在这个例子中,WIDTH
是一个类对象宏,当你在代码中使用 WIDTH
时,它会被替换成 8
。它类似于一个常量,但具有宏的特性:在编译时替换。
1 | reg [WIDTH-1:0] my_reg; // 这行代码会被替换为 reg [7:0] my_reg; |
在实际工程中,类对象宏非常常用,尤其是在设计中需要定义常量宽度、位宽、地址等情况下。
2. 类函数宏(Function-like Macro)
类函数宏是类对象宏的扩展,它允许你在宏定义中使用参数。使用这种宏时,它看起来像是调用函数一样,可以在宏定义中传递参数,并且这些参数在宏展开时会被替换为相应的文本。
举个例子:
1 | `define ADD(a, b) (a + b) |
这个宏 ADD
就像是一个函数,它接受两个参数 a
和 b
,并且返回它们的和。在代码中使用时,宏展开时会将参数替换为实际的数值:
1 | wire [7:0] result; |
类函数宏的强大之处在于它支持参数替换,可以进行非常灵活的宏定义。具体的应用场景有:
宏参数作为信号或变量名:比如你可以使用宏来动态地生成信号名。(根据仿真的结果来看,需要将替换的文本放在``xx``(xx就是宏变量,需要前后都有两个重音符号(就是键盘tab上面那个),但是只有一个的时候,好像是在后面有两个就行了,前面不需要了。)
1
2`define SIGNAL_NAME(prefix) ``prefix``_signal
`SIGNAL_NAME(test) // 替换为 test_signal宏参数作为字符串:可以将宏参数直接替换为字符串。比如当你想在显示中打印某个值时,可以使用宏参数作为字符串的一部分。
- 就是`“Macro`“,字符串的双引号前后都有一个重音符号
1
2`define PRINT_SIGNAL(signal) $display(`"Signal value: %s`", signal);
`PRINT_SIGNAL(test_signal); // 替换为 $display("Signal value: `test_signal`");宏参数替换到嵌套的字符串中:宏参数不仅仅可以替换文本,还可以插入到嵌套的字符串中。这样可以更灵活地生成复杂的字符串内容。
- 我有看到用 `\`”的,下面举一个例子吧。
1
`\`"data`\`" //这个最后会解析成\"data\",又因为这整个式子是在字符串中的,"this is `\`"data`\`" ",所有最后就变成了"this is \"data\" ",data最后会被宏参数代替。
- 我自己实验了一下
1
2
3
4`define ARGV_TO_TXT_2(argv) $display(`"[OUTPUT] ARGV_TO_TXT_2(`\`"argv`\`")`");
`ARGV_TO_TXT_2(zlin);
//最后的结果
[OUTPUT] ARGV_TO_TXT_2("zlin")- 但是其实我发现下面这种写法几种写法和上面的都一样,我感觉下面的写法简便一些吧,目前我没有看到上面的有什么优势。
1
2`define ARGV_TO_TXT_2(argv) $display("[OUTPUT] ARGV_TO_TXT_2(\"argv\")");
`define ARGV_TO_TXT_2(argv) $display(`"[OUTPUT] ARGV_TO_TXT_2(\"argv\")`");
这种方式使得宏在验证环境中非常有用,尤其是当需要大量重复的代码或模板时,使用类函数宏可以减少代码的重复性。
3. 链式宏(Chain Macro)
链式宏指的是在宏定义中引用其他宏,这样宏就可以进行嵌套和组合。宏 A 可以引用宏 B,而宏 B 又可以包含其他宏,从而形成一个宏的链条。链式宏在 SystemVerilog 中非常强大,可以通过嵌套宏参数来提高代码的复用性,减少冗余。
链式宏的应用场景:
- 生成代码模板:比如你可以定义一个宏来生成一系列具有相似结构的代码段,通过组合多个宏来生成不同的代码模板。
- 提高代码复用性:在复杂的验证环境中,宏链的组合可以帮助你高效地复用验证代码,避免重复编写。
宏的参数构造
``分隔词法标记而不引入空白,允许从参数构造标识符。我发现如果宏参数在第一个的话,第一个前面的分隔符号可以不写的。
1 | `define TWO_STATE_NET(name, suffix) bit ``name``suffix``;\ |
本文链接: https://talent-tudou.github.io/2024/12/21/DV/SystemVerilog的宏/
版权声明: 本作品采用 CC BY-NC-SA 4.0 进行许可。转载请注明出处!