br1992
br1992

Reputation: 15

Function to calculate a value inside a Verilog generate loop

I am trying to create a parametrized circuit for the multiplication stage of a BCD Wallace Tree Multiplier, which I implemented in Orcad. The trouble I'm having is that I need to calculate the bit positions that each two digits that result from BCD multiplication will inhabit. Here is my code:

module bcd_mult_1_n #(parameter N = 8)
  (input [N * 4 - 1:0] num1, num2, output reg [2 * 4 * N * N - 1:0] partProds);

  genvar i, j;

  generate
    for(i = 0; i < N; i = i + 1) begin : dig1
      for(j = 0; j < N; j = j + 1) begin : dig2
        localparam lsd = posLSD(i, j);
        localparam msd = posMSD(i, j);
        bcd_mult_1 bcd_mult(num1[i * 4 + 3:i * 4], num2[j * 4 + 3:j * 4],
                            partProds[msd * 4 + 3:msd * 4], partProds[lsd * 4 + 3: lsd * 4]);
      end
    end
  endgenerate

In the above code, numPrev(i + j) needs to return a value calculated something like this

int numPrev(int x) {
  int acc = 0;
  for(int i = x; i > 0; i++) acc = acc + 2 * i;
  return acc;
}

Thanks to help from @Morgan I have created the following function; the logic is meant to count up and down a sort of triangle of values which rise from 1 to N and back down to 1.

  function integer posLSD;
    input integer x, y;
    integer weight;
    integer acc;
    integer num;
    integer i;
    weight = x + y;
    acc = 0;
    if(weight >= N) num = N - 1;
    else num = weight;
    for(i = num; i > 0; i = i - 1)
      acc = acc + 2 * i;
    if(weight >= N) begin
      for(i = 2 * N - weight; i <= N; i = i + 1) begin
        acc = acc + 2 * i;
      end
      acc = acc + N - weight + y - 1;
    end
    else
      acc = acc + y;
    posLSD = acc;
  endfunction

  function integer posMSD;
    input integer x, y;
    integer acc;
    integer weight;
    acc = posLSD(x, y);
    weight = x + y;
    if(weight < N) acc = acc + weight + 1;
    else acc = acc + 2 * N - weight - 1;
    posMSD = acc;
  endfunction

How could I achieve this functionality? If needed, I could use SystemVerilog constructs.

Upvotes: 0

Views: 2384

Answers (1)

Morgan
Morgan

Reputation: 20554

When I change to use a function I get the error Packed dimension must specify a range. I think you need to think about your partProds width and connections.

Using a function:

module bcd_mult_1_n #(
  parameter N = 8
)  (
  input [N * 4 - 1:0] num1, 
  input [N * 4 - 1:0] num2, 
  output reg [2 * 4 * N * N] partProds
);

  integer prev = 1;
  genvar i, j;
  generate
    for(i = 0; i < N; i = i + 1) begin : dig1
      for(j = 0; j < N; j = j + 1) begin : dig2
        bcd_mult_1 
          bcd_mult(
            num1[i * 4 + 3:i * 4],
            num2[j * 4 + 3:j * 4], 
            partProds[numPrev(i+j) + 2*j + i + 1], 
            partProds[numPrev(i+j) + j]
          );
      end
    end
  endgenerate

  function numPrev;
    input integer x ;
    integer acc;
    begin
      acc = 0;
      for(int ij = x; ij > 0; ij++) begin
        acc = acc + 2 * ij;
      end
      numPrev = acc;
    end
  endfunction

endmodule

module bcd_mult_1(
  input [3:0]a,
  input [3:0]b,
  input c,
  input d
);

endmodule

Example on EDA Playground.

Upvotes: 1

Related Questions