如何在Verilog顶层模块中实例化子目录内的模块
嘿,这个问题我之前做项目的时候也碰到过,其实有几种实用的方法能解决,具体选哪种要看你用的EDA工具和项目结构,我给你详细说说:
方法1:修改编译脚本/工程设置(最推荐)
这是业界最常用的方式,能让你的Verilog代码保持干净,不用硬编码路径,移植性也更好。不同工具的操作略有不同:
- ModelSim/QuestaSim:在编译.do脚本里,先添加子目录到包含路径,再编译子目录里的文件:
或者用# 添加子目录到包含路径 +incdir+./your_subdir # 编译子目录下的所有Verilog文件 vlog ./your_subdir/*.v # 再编译顶层模块 vlog top.v-y选项指定模块搜索路径,工具会自动在该目录下查找你实例化的模块:vlog -y ./your_subdir top.v - Vivado:可以在Tcl脚本里直接读取子目录的文件:
也可以在图形界面右键工程→Settings→IP→Verilog Include Directories,添加子目录后再把subdir里的文件加入工程。read_verilog ./your_subdir/*.v read_verilog top.v - Quartus Prime:在工程界面的Files标签下点击Add Files,选择子目录里的Verilog文件;或者在Settings→Compiler Settings→Include Directories里添加子目录路径。
方法2:使用`include指令(小项目临时用用)
如果是小项目不想折腾脚本,也可以直接在顶层模块里用include把子目录的模块文件包含进来。比如子目录叫sub_modules,里面有my_module.v`,顶层代码可以这么写:
// 先包含子目录里的模块文件 `include "./sub_modules/my_module.v" module top( // 顶层端口定义 ); // 实例化子目录里的模块 my_module u_my_module( .clk(clk), .rst_n(rst_n), // 其他端口连接 ); endmodule
不过这种方式有几个坑要注意:
- 如果子目录里的文件还`include了其他文件,路径要相对于顶层模块所在的目录,不然会找不到;
- 容易出现重复包含问题,建议在被包含的模块文件里加保护宏:
`ifndef MY_MODULE_V `define MY_MODULE_V module my_module(...); // 模块内容 endmodule `endif - 大项目不推荐,会让代码耦合度变高,维护起来麻烦。
方法3:工具扩展的路径语法(少用,不通用)
有些EDA工具支持非标准的Verilog语法指定路径,比如Synopsys工具可用-y编译选项指定模块搜索路径,或者在代码里用`define定义路径,但这种方式不通用,换工具可能就失效,除非迫不得已不建议用。
总的来说,优先选方法1,既能保持代码整洁,又方便项目维护。
内容的提问来源于stack exchange,提问作者David




