SystemVerilog generate块内为实例字符串变量赋值层次路径报错
问题描述
需求为在generate块内为N个实例的字符串变量分配层次路径,执行层次赋值操作时触发报错,报错信息如下:
xmvlog: *E,EXPLPA (testbench.sv,17|9): expecting a left parenthesis ('(') [12.1.2][7.1(IEEE)]. sub.str = `STRINGIFY(`HPATH);
原测试代码如下:
module test; `define STRINGIFY(x) `"x`" `define HPATH top.chip.block subtest sub[3](); string hpath; initial begin hpath = `STRINGIFY(`HPATH); $display("HPATH is %s", hpath); end genvar r; generate for (r=0;r<2;r++)begin sub[r].str = `STRINGIFY(`HPATH); end endgenerate endmodule module subtest(); string str; initial begin $display("%s",str); end endmodule
报错根因
- 核心语法错误:
generate块内不允许直接放置过程赋值语句。generate区域只能出现模块/接口/程序实例、连续赋值语句、initial/always等过程块、条件/循环生成结构,直接在generate的for循环里写sub[r].str = xxx属于非法语法,编译器解析到该位置时找不到符合语法规则的结构起始标记(比如块定义的左括号、实例声明关键字),就会抛出EXPLPA错误。 - 实现逻辑缺陷:手动定义宏写固定路径的方式扩展性极差,实例数组的每个子实例路径本身带索引,固定宏路径无法匹配每个实例的真实层次;另外跨模块直接给子模块内部变量赋值的写法可维护性低,很容易出现层次引用错误。
- 宏写法问题:定义的
STRINGIFY宏没有做两层展开,当入参是另一个宏时无法正确完成字符串转换。
可行实现方案
最推荐的方式是在子模块内部直接获取自身层次路径,不需要父模块跨模块赋值,也不需要手动维护宏路径,不会出现语法错误,路径自动匹配实例层级:
module test; subtest sub[3](); // 实例化3个subtest endmodule module subtest(); string str; initial begin // %m格式符会自动返回当前作用域的完整层次路径,直接赋值即可 str = $sformatf("%m"); $display("Instance path is %s",str); end endmodule
运行后会自动打印每个实例的真实路径,比如test.sub[0]、test.sub[1]、test.sub[2],完全不需要手动拼接路径。
如果你确实需要从父模块批量给子实例的字符串变量赋值,按如下方式修改,把赋值逻辑放到initial过程块中即可解决语法报错:
module test; `define STRINGIFY(x) `"x`" `define HPATH top.chip.block subtest sub[3](); string hpath; initial begin hpath = `STRINGIFY(`HPATH); $display("Top HPATH is %s", hpath); // 父模块批量给子实例赋值,过程赋值放在initial块内,不需要套generate for(int r=0;r<3;r++)begin sub[r].str = $sformatf("%s.%0d", `STRINGIFY(`HPATH), r); end end endmodule module subtest(); string str; initial begin #1; // 等父模块赋值完成再打印 $display("Sub instance str is %s",str); end endmodule
注意这个方案里不需要用generate块做循环,普通for循环写在initial过程块里就可以完成批量层次引用赋值,避开generate块的语法限制。
内容的提问来源于stack exchange,提问作者newbee
相关产品推荐
相关产品推荐

