在Verilog中避免代码重复

在Verilog中避免代码重复,verilog,Verilog,我发现这种情况在Verilog代码中经常发生: wire my_module_output_1; wire my_module_output_2; wire my_module_output_3; ... MyModule my_module( .output_1(my_module_output_1), .output_2(my_module_output_2), .output_3(my_module_output_3), ... ); MyOtherMo

我发现这种情况在Verilog代码中经常发生:

wire my_module_output_1;
wire my_module_output_2;
wire my_module_output_3;
...

MyModule my_module(
    .output_1(my_module_output_1),
    .output_2(my_module_output_2),
    .output_3(my_module_output_3),
    ...
);

MyOtherModule my_other_module(
    .input_1(my_module_output_1),
    .input_2(my_module_output_2),
    .input_3(my_module_output_3),
    ...
);
我希望我能做的是:

MyModule my_module();
MyOtherModule my_other_module(
    .input_1(my_module.output_1),
    .input_2(my_module.output_2),
    .input_3(my_module.output_3),
    ...
);

有没有这样的方法让我达到同样的效果,也就是说,每次我需要某个模块的输出时,我都不必一遍又一遍地重复自己的操作?

人们还没有到处使用Verilog AUTOs吗

特别要注意有关自动安装的部分。这并不能解决你所有的问题,但是明智地使用AUTOs可以减少生成结构化Verilog的繁琐工作


不要介意它是一个Emacs节点。我自己也是一个vim人,但当我需要更新我的汽车时,我只是通过emacs加载这个模式,将我的缓冲区传输到emacs。

人们还没有到处使用Verilog汽车吗

特别要注意有关自动安装的部分。这并不能解决你所有的问题,但是明智地使用AUTOs可以减少生成结构化Verilog的繁琐工作


不要介意它是一个Emacs节点。我自己也是一名vim人员,但当我需要更新汽车时,我只需通过emacs加载此模式即可使用缓冲区。

以下是一些减少重复次数的方法

起点 下面是一个连接两个子模块的简单示例。正如你在问题中提到的,将它们缝合在一起需要大量的重复

module source(output A, output B);
  assign A = 0;
  assign B = 1;
endmodule

module sink(input A, input B);
  initial begin
    #1 $display("A=%0d B=%0d", A, B);
  end
endmodule

module top();

  wire A;
  wire B;

  source the_source(
    .A(A),
    .B(B)
  );

  sink the_sink(
    .A(A),
    .B(B)
  );

endmodule

使用隐式导线 Verilog允许隐式声明导线。因此,如下所示,您不需要将
A
B
声明为导线。如果它们出现在端口映射中,它们将被隐式声明。唯一的问题是它们总是声明为单位导线/网络。因此,虽然这对单位信号很好,但对于总线,互连仍然需要明确声明

// Verilog, implicit wires
module top();

source the_source(
  .A(A),
  .B(B)
);

sink the_sink(
  .A(A),
  .B(B)
);

endmodule

使用Verilog模式AUTOs 可以极大地减少将模块缝合在一起所需的键入量。下面是上面使用AUTOs的示例

展开汽车前:

// Verilog, explicit connections using AUTOs
module top();

  /*AUTOWIRE*/

  source the_source (/*AUTOINST*/);

  sink the_sink (/*AUTOINST*/);

endmodule
// Verilog, explicit using AUTOs
module top();

  /*AUTOWIRE*/
  // Beginning of automatic wires (for undeclared instantiated-module outputs)
  wire                A;                      // From the_source of source.v
  wire                B;                      // From the_source of source.v
  // End of automatics

  source the_source (/*AUTOINST*/
                     // Outputs
                     .A               (A),
                     .B               (B));

  sink the_sink (/*AUTOINST*/
                 // Inputs
                 .A                   (A),
                 .B                   (B));

endmodule
展开汽车后:

// Verilog, explicit connections using AUTOs
module top();

  /*AUTOWIRE*/

  source the_source (/*AUTOINST*/);

  sink the_sink (/*AUTOINST*/);

endmodule
// Verilog, explicit using AUTOs
module top();

  /*AUTOWIRE*/
  // Beginning of automatic wires (for undeclared instantiated-module outputs)
  wire                A;                      // From the_source of source.v
  wire                B;                      // From the_source of source.v
  // End of automatics

  source the_source (/*AUTOINST*/
                     // Outputs
                     .A               (A),
                     .B               (B));

  sink the_sink (/*AUTOINST*/
                 // Inputs
                 .A                   (A),
                 .B                   (B));

endmodule
正如Brian在他的回答中指出的,您不需要使用emacs来使用Verilog模式。我还使用Vim和从Vim中启用Verilog模式


SystemVerilog选项 如果可以使用SystemVerilog,则可以使用点星表示法按名称连接端口。这非常方便,但是您仍然需要声明对等模块之间互连的导线

// SystemVerilog, dot-star notation
module top();

  wire A;
  wire B;

  source the_source(.*);
  sink the_sink(.*);

endmodule

下面是一些可以用来减少重复次数的方法

起点 下面是一个连接两个子模块的简单示例。正如你在问题中提到的,将它们缝合在一起需要大量的重复

module source(output A, output B);
  assign A = 0;
  assign B = 1;
endmodule

module sink(input A, input B);
  initial begin
    #1 $display("A=%0d B=%0d", A, B);
  end
endmodule

module top();

  wire A;
  wire B;

  source the_source(
    .A(A),
    .B(B)
  );

  sink the_sink(
    .A(A),
    .B(B)
  );

endmodule

使用隐式导线 Verilog允许隐式声明导线。因此,如下所示,您不需要将
A
B
声明为导线。如果它们出现在端口映射中,它们将被隐式声明。唯一的问题是它们总是声明为单位导线/网络。因此,虽然这对单位信号很好,但对于总线,互连仍然需要明确声明

// Verilog, implicit wires
module top();

source the_source(
  .A(A),
  .B(B)
);

sink the_sink(
  .A(A),
  .B(B)
);

endmodule

使用Verilog模式AUTOs 可以极大地减少将模块缝合在一起所需的键入量。下面是上面使用AUTOs的示例

展开汽车前:

// Verilog, explicit connections using AUTOs
module top();

  /*AUTOWIRE*/

  source the_source (/*AUTOINST*/);

  sink the_sink (/*AUTOINST*/);

endmodule
// Verilog, explicit using AUTOs
module top();

  /*AUTOWIRE*/
  // Beginning of automatic wires (for undeclared instantiated-module outputs)
  wire                A;                      // From the_source of source.v
  wire                B;                      // From the_source of source.v
  // End of automatics

  source the_source (/*AUTOINST*/
                     // Outputs
                     .A               (A),
                     .B               (B));

  sink the_sink (/*AUTOINST*/
                 // Inputs
                 .A                   (A),
                 .B                   (B));

endmodule
展开汽车后:

// Verilog, explicit connections using AUTOs
module top();

  /*AUTOWIRE*/

  source the_source (/*AUTOINST*/);

  sink the_sink (/*AUTOINST*/);

endmodule
// Verilog, explicit using AUTOs
module top();

  /*AUTOWIRE*/
  // Beginning of automatic wires (for undeclared instantiated-module outputs)
  wire                A;                      // From the_source of source.v
  wire                B;                      // From the_source of source.v
  // End of automatics

  source the_source (/*AUTOINST*/
                     // Outputs
                     .A               (A),
                     .B               (B));

  sink the_sink (/*AUTOINST*/
                 // Inputs
                 .A                   (A),
                 .B                   (B));

endmodule
正如Brian在他的回答中指出的,您不需要使用emacs来使用Verilog模式。我还使用Vim和从Vim中启用Verilog模式


SystemVerilog选项 如果可以使用SystemVerilog,则可以使用点星表示法按名称连接端口。这非常方便,但是您仍然需要声明对等模块之间互连的导线

// SystemVerilog, dot-star notation
module top();

  wire A;
  wire B;

  source the_source(.*);
  sink the_sink(.*);

endmodule

我不太清楚这个例子,你为什么不直接将“其他线路”连接到输出端口以获得相同的结果:
。output\u 1(其他线路)
@Tim:对不起,让我更改一下这个例子。。。关键是,这并不总是可能做到的,例如,如果不是
some_other_wire_1
,而是另一个模块的输入,或者如果您需要在
always
块内,等等。@Tim:Fixed,这更有意义吗?是的,这样更好。对你来说不幸的是,我认为这样的事情不存在。verilog标准确实支持分层引用,允许您在没有现有端口的情况下直接连接到模块内部的导线,但我相信大多数合成器不支持它,作为一种编码样式,我认为它通常不受欢迎。这是用于合成的吗?您的第二个示例是有效的代码。我不确定我是否完全理解该示例,您是否有理由不直接将“其他一些线路”连接到输出端口以获得相同的结果:
。输出线路1(其他一些线路)
@Tim:对不起,让我更改示例。。。关键是,这并不总是可能做到的,例如,如果不是
some_other_wire_1
,而是另一个模块的输入,或者如果您需要在
always
块内,等等。@Tim:Fixed,这更有意义吗?是的,这样更好。对你来说不幸的是,我认为这样的事情不存在。verilog标准确实支持分层引用,允许您在没有现有端口的情况下直接连接到模块内部的导线,但我相信大多数合成器不支持它,作为一种编码样式,我认为它通常不受欢迎。这是用于合成的吗?您的第二个示例是有效代码。啊,我不使用emacs+1尽管如此。啊,我不使用emacs+1尽管如此。