【驯服野生verilog-mode全记录】day2 —— 模块的例化

前言

相关博文:

【驯服野生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例化了。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));

关于模块例化,个人常用的操作就是这些。

你可能感兴趣的:(EDA工具使用笔记,fpga开发,芯片,verilog)