简体   繁体   中英

Calculating a parameter in a loop generate block

I have an array of parameters WIDTHS , and I need to calculate another parameter RIGHT based on some values in WIDTHS in a generate block. Is this possible? If not, is there an alternative way?

Here is an example of what I am trying to do. Suppose we have a predefined register module REG which has inputs d, q, we (write enable), CLK and _RESET . I would like to create a new module called GroupReg , which instantiates N instances of REG . Each instance has a different width (hence the WIDTH parameter array). The d, q, and we of each group are aggregated in arrays with the same name in GroupReg and need to be specified for each instance. Specifying we is easy ( we[i] ) since it is only one bit. However, specifying d and q with the correct LEFT and RIGHT values is where I have problem with since each group has a different width.

Looks like the only way to assign a value to a parameter is upon its definition, which prevents assigning a value to it in a generate loop.

 module GroupReg(d, q, we, CLK, _RESET);
 parameter N = 4;               //Number of groups
 //INDICES has to have N+1 members. Last member should be 0
 parameter integer WIDTHS   [N:0]  = {40, 30, 20, 10, 0}; 
 parameter integer DW_TOTAL  = 128;

 input  logic [DW_TOTAL-1:0]        d;                  // Data Input
 input  logic [N-1:0]               we;                     // write enable
 input  logic                       CLK;                // Clock Input
 input  logic                       _RESET;           // Reset input (active low)
 output logic [DW_TOTAL-1:0]        q;            // Q output

 genvar i, j;
 for (i=N-1 ; i>=0 ; i--) begin:REGISTERS

  localparam WIDTH = WIDTHS[i];
  localparam LEFT  = RIGHT +  WIDTHS[i];;
  localparam RIGHT = 0;

  for (j = 0 ; j<i ; j++)        // <<----- Does not work
    RIGHT = RIGHT + WIDTH[j];  

  REG #(
             .DW              (WIDTH),
             ) 
  reg_i 
  ( 
   .d(d[LEFT:RIGHT]), 
   .q(q[LEFT:RIGHT]),
   .we(we[i]),
   .CLK(CLK),
  ._RESET(_RESET)  
  );
 end : REGISTERS
endmodule  

I tried using the sum() array reduction method on WIDTHS and it worked in Aldec Riviera PRO:

module some_module;
  parameter N = 4;               //Number of groups
  parameter integer WIDTHS   [N:0]  = '{40, 30, 20, 10, 0};

  parameter integer DW_TOTAL  = WIDTHS.sum();

  initial begin
    $display("DW_TOTAL", DW_TOTAL);
  end
endmodule

If you're lucky it's going to work in your simulator too.

I anyway don't really get what you're trying to do making N a parameter, seeing as how you're anyway hardcoding a fixed number of values for the widths.

This works in Modelsim:

module some_module;
  parameter N = 4;               //Number of groups
  parameter integer WIDTHS   [N:0]  = '{40, 30, 20, 10, 0};


  genvar i;
  for (i=N-1 ; i>=0 ; i--) begin
    localparam integer FOO[i:0] = WIDTHS[i:0];
    //localparam RIGHT = FOO.sum();

    initial begin
      foreach (FOO[i])
        $display("FOO[%0d] = %h", i, FOO[i]);
    end
  end
endmodule

The FOO parameter would only store the relevant entries from WIDTH for a specific loop iteration. If sum() would work, you'd be home free. The slicing syntax doesn't work in Riviera, however.

This is a typical example of vendors interpreting the standard differently, basically because it's not specific enough. Still, if you use a simulator from a different EDA company, try combining the two answers; maybe you're lucky and it works.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM