Verilog:如何实例化模块

Mor*_*gan 13 verilog system-verilog

如果我有一个Verilog模块'top'和一个verilog模块'子组件',我如何在顶部实例化子组件?

最佳:

module top(
   input        clk,
   input        rst_n,
   input        enable,
   input  [9:0] data_rx_1,
   input  [9:0] data_rx_2,
   output [9:0] data_tx_2
);
Run Code Online (Sandbox Code Playgroud)

子:

module subcomponent(
   input        clk,
   input        rst_n,
   input  [9:0] data_rx,
   output [9:0] data_tx
);
Run Code Online (Sandbox Code Playgroud)

注意
这是一个通用的问题,不断出现,它遵循自我答案的格式.鼓励添加答案和更新.

Mor*_*gan 38

这一点通常由SystemVerilog IEEE Std 1800-2012的第23.3.2节涵盖.

最简单的方法是在top的main部分实例化,创建一个命名实例并按顺序连接端口:

module top(
   input        clk,
   input        rst_n,
   input        enable,
   input  [9:0] data_rx_1,
   input  [9:0] data_rx_2,
   output [9:0] data_tx_2
);

subcomponent subcomponent_instance_name (
  clk, rst_n, data_rx_1, data_tx ); 

endmodule
Run Code Online (Sandbox Code Playgroud)

这在SystemVerilog IEEE Std 1800-2012的第23.3.2.1节中描述.

这有一些缺点,特别是关于子组件代码的端口顺序.这里简单的重构可以打破连接或改变行为.例如,如果其他人修复了一个错误并因某种原因重新排序了端口,请切换clk并重置顺序.您的编译器不会出现连接问题,但无法按预期工作.

module subcomponent(
  input        rst_n,       
  input        clk,
  ...
Run Code Online (Sandbox Code Playgroud)

因此,建议使用命名端口进行连接,这也有助于跟踪代码中线路的连接.

module top(
   input        clk,
   input        rst_n,
   input        enable,
   input  [9:0] data_rx_1,
   input  [9:0] data_rx_2,
   output [9:0] data_tx_2
);

subcomponent subcomponent_instance_name (
  .clk(clk), .rst_n(rst_n), .data_rx(data_rx_1), .data_tx(data_tx) ); 

endmodule
Run Code Online (Sandbox Code Playgroud)

这在SystemVerilog IEEE Std 1800-2012的第23.3.2.2节中描述.

为每个端口提供自己的行并正确缩进会增加可读性和代码质量.

subcomponent subcomponent_instance_name (
  .clk      ( clk       ), // input
  .rst_n    ( rst_n     ), // input
  .data_rx  ( data_rx_1 ), // input  [9:0]
  .data_tx  ( data_tx   )  // output [9:0]
);
Run Code Online (Sandbox Code Playgroud)

到目前为止,所有已建立的连接都重复使用输入和输出到子模块,并且没有创建连接线.如果我们要将输出从一个组件转移到另一个组件,会发生什么:

clk_gen( 
  .clk      ( clk_sub   ), // output
  .en       ( enable    )  // input

subcomponent subcomponent_instance_name (
  .clk      ( clk_sub   ), // input
  .rst_n    ( rst_n     ), // input 
  .data_rx  ( data_rx_1 ), // input  [9:0]
  .data_tx  ( data_tx   )  // output [9:0]
);
Run Code Online (Sandbox Code Playgroud)

这个名义上用作clk_sub的电线是自动创建的,存在依赖于此的危险.它默认只会创建1位线.这是一个问题的例子是数据:

请注意,第二个组件的实例名称已更改

subcomponent subcomponent_instance_name (
  .clk      ( clk_sub   ), // input
  .rst_n    ( rst_n     ), // input 
  .data_rx  ( data_rx_1 ), // input  [9:0]
  .data_tx  ( data_temp )  // output [9:0]
);
subcomponent subcomponent_instance_name2 (
  .clk      ( clk_sub   ), // input
  .rst_n    ( rst_n     ), // input 
  .data_rx  ( data_temp ), // input  [9:0]
  .data_tx  ( data_tx   )  // output [9:0]
);
Run Code Online (Sandbox Code Playgroud)

上面代码的问题是data_temp只有1位宽,会有关于端口宽度不匹配的编译警告.需要创建连接线并指定宽度.我建议明确写出所有连接线.

wire [9:0] data_temp
subcomponent subcomponent_instance_name (
  .clk      ( clk_sub   ), // input
  .rst_n    ( rst_n     ), // input 
  .data_rx  ( data_rx_1 ), // input  [9:0]
  .data_tx  ( data_temp )  // output [9:0]
);
subcomponent subcomponent_instance_name2 (
  .clk      ( clk_sub   ), // input
  .rst_n    ( rst_n     ), // input 
  .data_rx  ( data_temp ), // input  [9:0]
  .data_tx  ( data_tx   )  // output [9:0]
);
Run Code Online (Sandbox Code Playgroud)

移动到SystemVerilog有一些技巧可以节省键入一些字符.我相信它们会妨碍代码的可读性,并且会使查找错误变得更加困难.

使用.port没有括号连接到同名的电线/ reg.这看起来整洁尤其是有很多的CLK和重置,但在某些层次可能会产生不同的时钟或重置或者你其实并不想连接到同一个名字的信号,而是一个修饰的,这可能会导致配线错误是对眼睛不明显.

module top(
   input        clk,
   input        rst_n,
   input        enable,
   input  [9:0] data_rx_1,
   input  [9:0] data_rx_2,
   output [9:0] data_tx_2
);

subcomponent subcomponent_instance_name (
  .clk,                    // input **Auto connect**
  .rst_n,                  // input **Auto connect**
  .data_rx  ( data_rx_1 ), // input  [9:0]
  .data_tx  ( data_tx   )  // output [9:0]
);

endmodule
Run Code Online (Sandbox Code Playgroud)

这在SystemVerilog IEEE Std 1800-2012的第23.3.2.3节中描述.

我认为另一个技巧甚至比上面.*提到的更糟糕的是将未提及的端口连接到同一线路的信号.我认为这在生产代码中非常危险.如果新端口名称在实例化级别中具有计数器部分,则新端口已添加且丢失或者可能意外连接时,它们并不明显,它们将自动连接并且不会生成警告.

subcomponent subcomponent_instance_name (
  .*,                      // **Auto connect**
  .data_rx  ( data_rx_1 ), // input  [9:0]
  .data_tx  ( data_tx   )  // output [9:0]
);
Run Code Online (Sandbox Code Playgroud)

这在SystemVerilog IEEE Std 1800-2012的第23.3.2.4节中描述.


Mob*_*erg 5

请务必查看 verilog-mode,尤其是 verilog-auto。http://www.veripool.org/wiki/verilog-mode/这是 emacs 的 verilog 模式,但例如 vi(m?) 存在插件。

可以使用 AUTOINST 自动进行实例化。评论会扩展M-x verilog-auto,然后可以手动编辑。

subcomponent subcomponent_instance_name(/*AUTOINST*/);
Run Code Online (Sandbox Code Playgroud)

扩展

subcomponent subcomponent_instance_name (/*AUTOINST*/
  //Inputs
  .clk,         (clk)           
  .rst_n,       (rst_n)
  .data_rx      (data_rx_1[9:0]),
  //Outputs
  .data_tx      (data_tx[9:0])
);
Run Code Online (Sandbox Code Playgroud)

隐式连线可以通过 实现自动化/*AUTOWIRE*/。检查链接以获取更多信息。

警告,如您所见,自动安装默认情况下会在端口连接 ( data_tx[9:0]) 上插入切片符号,如果您更改电线的宽度,这可能会隐藏错误。