相关博文:
【驯服野生verilog-mode全记录】day0 —— verilog-mode的安装
【驯服野生verilog-mode全记录】day1 —— 常用链接与基本命令模板
verilog-mode语法下,最简单的例化模块方式就是:
fw_pipe u_pipe1(/*AUTOINST*/);
执行生成后就是你要的样子(之后如无必要就不写input/output/wire的生成语句了):
/*AUTOINPUT*/
// Beginning of automatic inputs (from unused autoinst inputs)
input clk; // To u_pipe1 of fw_pipe.v, ...
input data_in_valid; // To u_pipe1 of fw_pipe.v, ...
input data_out_ready; // To u_pipe1 of fw_pipe.v, ...
input [IN_INFO_WD-1:0] in_info; // To u_pipe1 of fw_pipe.v, ..., Couldn't Merge
input rst_n; // To u_pipe1 of fw_pipe.v, ...
// End of automatics
/*AUTOOUTPUT*/
// Beginning of automatic outputs (from unused autoinst outputs)
output data_in_ready; // From u_pipe1 of fw_pipe.v, ...
output [IN_INFO_WD-1:0] data_out; // From u_pipe1 of fw_pipe.v, ..., Couldn't Merge
output data_out_valid; // From u_pipe1 of fw_pipe.v, ...
// End of automatics
/*AUTOWIRE*/
fw_pipe u_pipe1(/*AUTOINST*/
// Outputs
.data_in_ready (data_in_ready),
.data_out (data_out[WIDTH-1:0]),
.data_out_valid (data_out_valid),
// Inputs
.clk (clk),
.rst_n (rst_n),
.data_in (in_info[WIDTH-1:0]), // Templated
.data_in_valid (data_in_valid),
.data_out_ready (data_out_ready));
当然了,这样做的前提是,你的信号名做的非常完美,内部的接口定义与最终的接口一致,或者说两个模块的互连接口名称完全一致(当然,这也算基本要求吧)。
进一步的,我们可以把parameter也显示的连接出来:
fw_pipe #(/*AUTOINSTPARAM*/)
u_pipe1(/*AUTOINST*/);
但是verilog-mode有个特性,他会自动查找最近的TEMPLATE模板,所以我这个文件里这行下面有一个TEMPLATE模板,所以展开后就是这个样子:
fw_pipe #(/*AUTOINSTPARAM*/
// Parameters
.WIDTH (OUT_INFO_WD)) // Templated
u_pipe1(/*AUTOINST*/
// Outputs
.data_in_ready (data_in_ready),
.data_out (data_out[OUT_INFO_WD-1:0]),
.data_out_valid (data_out_valid),
// Inputs
.clk (clk),
.rst_n (rst_n),
.data_in (in_info[OUT_INFO_WD-1:0]), // Templated
.data_in_valid (data_in_valid),
.data_out_ready (data_out_ready));
当然了,如果不通过/*AUTOINSTPARAM*/,也可以手写parameter:
fw_pipe #(.WIDTH(5))
u_pipe1(/*AUTOINST*/);
展开之后,信号位宽已经适配:
fw_pipe #(.WIDTH(5))
u_pipe1(/*AUTOINST*/
// Outputs
.data_in_ready (data_in_ready),
.data_out (data_out[4:0]),
.data_out_valid (data_out_valid),
// Inputs
.clk (clk),
.rst_n (rst_n),
.data_in (in_info[4:0]), // Templated
.data_in_valid (data_in_valid),
.data_out_ready (data_out_ready));
AUTOINSTPARAM甚至能够帮你算位宽:
fw_pipe #(.WIDTH(5*4+6))
u_pipe1(/*AUTOINST*/
// Outputs
.data_in_ready (data_in_ready),
.data_out (out_info), // Templated
.data_out_valid (data_out_valid),
// Inputs
.clk (clk),
.rst_n (rst_n),
.data_in (in_info[25:0]), // Templated
.data_in_valid (data_in_valid),
.data_out_ready (data_out_ready));
如果简单例化不能满足需求了,那么就要上template例化了。template的模板就是这样子:
/* fw_pipe AUTO_TEMPLATE (
.WIDTH(OUT_INFO_WD),
.data_in(in_info[]),
.data_out(out_info),
);
*/
fw_pipe #(/*AUTOINSTPARAM*/)
u_pipe2(/*AUTOINST*/);
可以对接口和parameter进行大杂烩的重命名:
/* fw_pipe AUTO_TEMPLATE (
.WIDTH(OUT_INFO_WD),
.data_in(in_info[]),
.data_out(out_info),
);
*/
fw_pipe #(/*AUTOINSTPARAM*/
// Parameters
.WIDTH (OUT_INFO_WD)) // Templated
u_pipe2(/*AUTOINST*/
// Outputs
.data_in_ready (data_in_ready),
.data_out (out_info), // Templated
.data_out_valid (data_out_valid),
// Inputs
.clk (clk),
.rst_n (rst_n),
.data_in (in_info[OUT_INFO_WD-1:0]), // Templated
.data_in_valid (data_in_valid),
.data_out_ready (data_out_ready));
最好用的是,支持正则匹配,比如这样“.data_\(.*\)(info_\1),”就把所有data_为前缀的信号都修改为了info_为前缀的信号:
/* fw_pipe AUTO_TEMPLATE (
.WIDTH(OUT_INFO_WD),
.data_\(.*\)(info_\1),
);
*/
fw_pipe #(/*AUTOINSTPARAM*/
// Parameters
.WIDTH (OUT_INFO_WD)) // Templated
u_pipe2(/*AUTOINST*/
// Outputs
.data_in_ready (info_in_ready), // Templated
.data_out (info_out), // Templated
.data_out_valid (info_out_valid), // Templated
// Inputs
.clk (clk),
.rst_n (rst_n),
.data_in (info_in), // Templated
.data_in_valid (info_in_valid), // Templated
.data_out_ready (info_out_ready)); // Templated
然后就发现怎么接口的信号都没有位宽了呢?因为忘记了[]:
/* fw_pipe AUTO_TEMPLATE (
.WIDTH(OUT_INFO_WD),
.data_\(.*\)(info_\1[]),
);
*/
fw_pipe #(/*AUTOINSTPARAM*/
// Parameters
.WIDTH (OUT_INFO_WD)) // Templated
u_pipe2(/*AUTOINST*/
// Outputs
.data_in_ready (info_in_ready), // Templated
.data_out (info_out[OUT_INFO_WD-1:0]), // Templated
.data_out_valid (info_out_valid), // Templated
// Inputs
.clk (clk),
.rst_n (rst_n),
.data_in (info_in[OUT_INFO_WD-1:0]), // Templated
.data_in_valid (info_in_valid), // Templated
.data_out_ready (info_out_ready));
接口上支持对信号进行截位:
/* fw_pipe AUTO_TEMPLATE (
.WIDTH(IN_INFO_WD),
.data_in(in_info[4:0]),
);
*/
fw_pipe #(/*AUTOINSTPARAM*/
// Parameters
.WIDTH (IN_INFO_WD)) // Templated
u_pipe3(/*AUTOINST*/
// Outputs
.data_in_ready (data_in_ready),
.data_out (data_out[IN_INFO_WD-1:0]),
.data_out_valid (data_out_valid),
// Inputs
.clk (clk),
.rst_n (rst_n),
.data_in (in_info[4:0]), // Templated
.data_in_valid (data_in_valid),
.data_out_ready (data_out_ready));
补位:
/* fw_pipe AUTO_TEMPLATE (
.WIDTH(IN_INFO_WD),
.data_in({2'b0, in_info[4:0]}),
);
*/
fw_pipe #(/*AUTOINSTPARAM*/
// Parameters
.WIDTH (IN_INFO_WD)) // Templated
u_pipe3(/*AUTOINST*/
// Outputs
.data_in_ready (data_in_ready),
.data_out (data_out[IN_INFO_WD-1:0]),
.data_out_valid (data_out_valid),
// Inputs
.clk (clk),
.rst_n (rst_n),
.data_in ({2'b0, in_info[4:0]}), // Templated
.data_in_valid (data_in_valid),
.data_out_ready (data_out_ready));
还有一个神奇的操作符:@,这个操作符会自动抓取例化名里的第一个数字,然后给你安在对应的位置:
/* fw_pipe AUTO_TEMPLATE (
.WIDTH(IN_INFO_WD@),
.data_in(in_info@[]),
);
*/
fw_pipe #(/*AUTOINSTPARAM*/
// Parameters
.WIDTH (IN_INFO_WD3)) // Templated
u_pipe3(/*AUTOINST*/
// Outputs
.data_in_ready (data_in_ready),
.data_out (data_out[IN_INFO_WD3-1:0]),
.data_out_valid (data_out_valid),
// Inputs
.clk (clk),
.rst_n (rst_n),
.data_in (in_info3[IN_INFO_WD3-1:0]), // Templated
.data_in_valid (data_in_valid),
.data_out_ready (data_out_ready));
关于模块例化,个人常用的操作就是这些。