ArneA
ArneA

Reputation: 11

Systemverilog localparam array with configurable size

I want to create and define a localparam array in SystemVerilog. The size of the array should be configurable, and the value of each localparam array cell calculated based on its location. Essentially this code:

localparam [7:0] [ADDR_BITS-1:0] ADDR_OFFSET = '{
  7*PAGE_SIZE,
  6*PAGE_SIZE,
  5*PAGE_SIZE,
  4*PAGE_SIZE,
  3*PAGE_SIZE,
  2*PAGE_SIZE,
  1*PAGE_SIZE,
  0
};

but where the first '7' is replaced with a parameter, and where the parameter initialization is extended to the generic case. So I need a way to loop from 0 to (N-1) and set ADDR_OFFSET(loop) = loop*PAGE_SIZE.

The "obvious" option in SystemVerilog would be generate, but I read that placing a parameter definition inside a generate block generates a new local parameter relative to the hierarchical scope within the generate block (source).

Any suggestions?

For background reference: I need to calculate an actual address based on a base address and a number. The calculation is simple: real_address = base_address + number*PAGE_SIZE

However, I don't want to have the "*" in my code since I am afraid the synt tool will generate a multiplier, that it will then try to simplify since PAGE_SIZE is a constant value. I am guessing that this can lead to more logic than if I try to do all calculations when generating the localparam array, since this for sure will not give any multiplier in logic.

So with the above localparam definition, I perform the desired address calculation like this:

  function [ADDR_BITS-1:0] addr_calc;
    input [ADDR_BITS-1:0] base_addr;
    input [NBITS-1:0]  num;

    addr_calc = base_addr + ADDR_OFFSET[num];
  endfunction

I think perhaps I found a solution. Wouldn't I essentially accomplish the same by not defining a localparam array, but rather performing the address calculation inside a loop? Since systemverilog sees the loop variable as "constant" (when it comes to generating logic) that seems to accomplish the same? Like this (inside the function I wrote above):

for (int loop1 = 0; loop1 < MAXNUM ; loop1++) begin
  if (num == loop1) begin
    addr_offset = CSP_PAGE_SIZE*loop1;
  end
  addr_calc = base_addr + addr_offset;
end

Upvotes: 1

Views: 15513

Answers (1)

dave_59
dave_59

Reputation: 42623

You can set your localparam with the return value of a function.

   localparam bit [7:0] [ADDR_BITS-1:0] ADDR_OFFSET = ADDR_CALC();
   function bit [7:0] [ADDR_BITS-1:0] ADDR_CALC();
      for(int ii=0;ii<$size(ADDR_CALC,1); ii++)
    ADDR_CALC[ii] = ii * PAGE_SIZE;
   endfunction 

Upvotes: 7

Related Questions