In Verilog, how can I define the width of a port at instantiation?

16,348

Parameter are defined for exactly his reason you just have to pass the parameters to the instance:

module Top();
localparam WIDE   = 8;
localparam NARROW = 4;

wire [NARROW-1:0] narrow_product;
wire   [WIDE-1:0]   wide_product;
reg  [NARROW-1:0] narrow_factor_1;
reg    [WIDE-1:0]   wide_factor_1;
reg  [NARROW-1:0] narrow_factor_2;
reg    [WIDE-1:0]   wide_factor_1;

Multiplier #(
  .WIDTH  (WIDE),
  .WIDTH1 (WIDE),
  .WIDTH2 (WIDE)
) mWide (
  .product (wide_product),
  .factor1 (wide_factor_1),
  .factor2 (wide_factor_2)
);


Multiplier #(
  .WIDTH  (NARROW),
  .WIDTH1 (NARROW),
  .WIDTH2 (NARROW)
) mNarrow(
  .product (narrow_product),
  .factor1( narrow_factor_1),
  .factor2( narrow_factor_2)
); // NOT A PROBLEM

endmodule

Multiplier :

module Multiplier #(
  parameter WIDTH = 8, 
  parameter WIDTH1 = 8,
  parameter WIDTH2 = 8
) (
    output [WIDTH-1:0]   product,
    input  [WIDTH1-1:0]  factor1,
    input  [WIDTH2-1:0]  factor2
);
//...
Share:
16,348
wdb
Author by

wdb

Updated on June 28, 2022

Comments

  • wdb
    wdb about 2 years

    In a Verilog 2001 module, how can I define the width of a port at instantiation?

    For example, a multiplier and the module that instantiates it might look like this:

    module Multiplier #(parameter WIDTH = 8, parameter WIDTH1 = 8, WIDTH2 = 8) (
        output [WIDTH-1:0] product,
        input [WIDTH1-1:0]  factor1,
        input [WIDTH2-1:0]  factor2
    );
    
    parameter WIDTHI = WIDTH1+WIDTH2;
    wire [WIDTHI-1:0] intermediate_product;
    assign intermediate_product = factor1 * factor2;
    assign product = (intermediate_product >>> (WIDTHI-WIDTH));
    
    endmodule
    
    module User();
    
    parameter WIDTH_OF_PRODUCT = 8;
    parameter WIDTH_OF_FACTOR_1 = 8;
    parameter WIDTH_OF_FACTOR_2 = 8;
    
    wire [WIDTH_OF_PRODUCT] product;
    reg  [WIDTH_OF_FACTOR_1] factor1;
    reg  [WIDTH_OF_FACTOR_2] factor2;
    
    Multiplier #(WIDTH_OF_PRODUCT,WIDTH_OF_FACTOR_1,WIDTH_OF_FACTOR_2) 
        m0(product, factor1, factor2);
    
    endmodule
    

    If the widths of the nets in User are defined at compile time, is there any way that the widths of the ports in the instantiation of Multiplier can be defined automatically?

    I'd like an instantiation that looks like this:

    Multiplier m0(product, factor1, factor2);
    

    That would probably involve changing the definition of the Multiplier module.

    Keep in mind that these are just examples. The point of my question regards how the two modules are defined with respect to their nets and ports.

    Thanks in advance!

    Update:

    Here is a case that would not work with Multiplier defined as it is:

    module Top();
    parameter WIDE = 8;
    parameter NARROW = 4;
    
    wire [NARROW-1:0] narrow_product;
    wire [WIDE-1:0]   wide_product;
    reg  [NARROW-1:0] narrow_factor_1;
    reg  [WIDE-1:0] wide_factor_1;
    reg  [NARROW-1:0] narrow_factor_2;
    reg  [WIDE-1:0] wide_factor_1;
    
    Multiplier mWide(wide_product, wide_factor_1, wide_factor_2);
    Multiplier mNarrow(narrow_product, narrow_factor_1, narrow_factor_2); // PROBLEM
    
    endmodule
    

    My motivation for this is that the nets represent fixed point numbers, a representation of numbers with fractional parts. I will have to specify a precision for the fixed point numbers. While that could be a global constant, I may want to use different precisions. So, I will probably need parameters to specify the precisions of the ports in modules.

    Update: Well, I can't do what I wanted to do. So here is what I have done, in case this helps anyone:

    Since the widths of input and output are the same I defined them this way:

    module Multiplier #(parameter WIDTH = 8,
        parameter WIDTH1 = WIDTH,
        parameter WIDTH2 = WIDTH1) (
        output [WIDTH-1:0] product,
        input [WIDTH1-1:0]  factor1,
        input [WIDTH2-1:0]  factor2
    );
    
    ...
    
    endmodule
    

    So then I can instantiate this way:

    Multiplier #(16) m0(product, factor1, factor2);
    

    if the product and the factors all have the same length. It's a little less verbose than specifying all of them, especially when I working with fixed point numbers where the instantiation would look like this:

    Multiplier #(16,8) m0(product, factor1, factor2); 
    

    where the second number is a PRECISION parameter giving the width of the fractional part. (This would require an update to the Multiplier module definition to include PRECISION, PRECISION1, and PRECISION2 with definitions analogous to the WIDTH definitions.