M.Eren Çelik
M.Eren Çelik

Reputation: 155

Verilog: generic parameters

I have several verilog (not system-verilog) blocks where I want to generate them depending on other parameters. As an example:

module some_module (in, out)

realtime p = 3.5; // the parameter which I want to change

initial begin
if ('global_parameter == 1)
    p = 5.8;
if ('global_parameter == 2)
    p = 4.4;
end

core_module #(p) core (in, out);
endmodule

Here, "global_parameter" is defined in a header file but overridden at simulation time by using simulator parameters. And my core module uses "p" for delay value like in this example:

module core_module(in, out)

parameter p = 1;

always out <= #p in; // p should be constant

endmodule

Therefore, I'm hoping to have the core module with updated parameter "p". But this scenario is not simulate-able. Could you please recommend me a possible solid solution for this problem if possible?

Thank you

Upvotes: 0

Views: 4033

Answers (1)

Greg
Greg

Reputation: 19094

A parameter needs to be a parameter type throughout the design. You cannot pass a variable as a parameter.

You can use a generate block to control instantiation:

module core_module#(parameter realtime P=1)(input in, output out);
  always @(in) out <= #(P) in; // p should be constant
endmodule

module some_module (input in, output out);
  generate
    if (GLOBAL_PARAMETER == 1) begin : cfg_1
      core_module #(5.8) core (in, out);
    end
    else if (GLOBAL_PARAMETER == 2) begin : cfg_2
      core_module #(4.4) core (in, out);
    end
    else begin : cfg_dflt
      core_module #(3.5) core (in, out); // default
    end
  endgenerate
endmodule

You can also calculate the parameter in a single line:

module some_module (input in, output out);
  parameter P = (GLOBAL_PARAMETER == 1) ? 5.8 : (GLOBAL_PARAMETER == 2) ? 4.4 : 3.5;
  core_module #(P) core (in, out); // default
endmodule

Alternatively (since you can not synthesizing), you can have the delay value be a variable, then force the value through hierarchical reference. Example:

module core_module (input in, output out);
  realtime p = 1;
  always @(in) out <= #(p) in; // this p is a variable
endmodule

module some_module (input in, output out);
  realtime p = 3.5;
  core_module core (in, out);
  initial begin
    if (GLOBAL_PARAMETER == 1)
      p = 5.8;
    else if (GLOBAL_PARAMETER == 2)
      p = 4.4;
    force core.p = p; // force hierarchical variable assignment
  end
endmodule

Note: all example are compatible with IEEE Std 1364-2001 and IEEE Std 1364-2005, utilizing ANSI header style and generate blocks. These features do not exist in IEEE Std 1364-1995


I'm not aware of any clean Verilog only solutions. You can try embed code (such as Perl's EP3, Ruby's eRuby/ruby_it, Python's prepro, etc.) As I mention in another answer to a somewhat similar question, here. A challenge with embedded is the need to be pre-compiled/processed, making them more like `define then parameters.

If SystemVerilog is an option, you can do the following: (Refer to IEEE Std 1800-2012 § 6.20 Constants; example near the end of § 6.20.2)

module some_module (input in, output out);
  parameter realtime P [3] = '{3.5, 5.8, 4.4};
  core_module #(P[GLOBAL_PARAMETER]) core (in, out);
endmodule

Upvotes: 1

Related Questions