Search code examples
verilogsystem-veriloghdl

Modifying variables inside generate statements


I am trying to write the Verilog code for a multiplexer module, that has a parametrized number of inputs. I am aware that you can pack the inputs together and use the select input to slice that packed variable but I want to use a binary tree structure for my multiplexer.

The problem lies in using auxiliary variables to properly index inner wires (interm_w), meaning I need to be able to modify certain integer variables after each iteration of my inner for loop, but I don't know how. These variables include P, M, and K.

module multiplexer_v2(input_data_array, select, output_data);

    parameter WIDTH = 16;
    parameter NUMBER_OF_INPUTS = 8;
    parameter SELECT_WIDTH = $clog2(NUMBER_OF_INPUTS);
    
    localparam INTERMEDIATE_WIRES_COUNT = interm_value(SELECT_WIDTH, NUMBER_OF_INPUTS);  // this is a function, that works correctly.

    input [SELECT_WIDTH-1:0] select; 
    input [WIDTH-1:0] input_data_array [0:NUMBER_OF_INPUTS-1];

    output [WIDTH-1:0] output_data;

    wire [WIDTH-1:0] interm_w [0:INTERMEDIATE_WIRES_COUNT-1]; 

    genvar i;
    genvar j;
    
    int K = NUMBER_OF_INPUTS / 2; 
    int M = NUMBER_OF_INPUTS; 
    int P = 0; 

    generate 
        for(i = 0; i < SELECT_WIDTH; i=i+1) begin 
            for(j = 0; j < K; j=j+1) begin
                multiplexer_2_input #(
                    .WIDTH(WIDTH)
                    ) mux_i (
                        .input_0(interm_w[P + j * 2]),
                        .input_1(interm_w[P + j * 2 + 1]),
                        .select(select[SELECT_WIDTH - i - 1]),
                        .output_data(interm_w[M + j])
                    );
            end

            P = M;                      // line 51 is here
            M = M + K;                   
            K = K / 2;                  
        end
    endgenerate

endmodule

I have tried using datatypes such as localparam, int, integer, parameter, and genvar for these variables, and moving around their initialization, but I face the same errors each time:

** Error: (vlog-13069) .../multiplexer_v2.sv(51): near "=": syntax error, unexpected '='.
** Error: .../multiplexer_v2.sv(51): (vlog-13205) Syntax error found in the scope following 'P'. Is there a missing '::'?

I would greatly appreciate any help I can get.

The interm_value() function is as follows:

function int interm_value(input int select_width, input int number_of_inputs);
    begin
        int i;
        int interm_value;
        int K;
        interm_value = 0;
        K = number_of_inputs;
        for(i = 0; i < select_width; i=i+1) begin 
            interm_value = interm_value + K;
            K = K / 2;
        end
        return interm_value + 1;
    end
endfunction

Solution

  • The reason for the syntax errors is that variables require procedural assignments (from within an always block, for example). But, you are not doing that.

    One approach to debugging problems associated with generate for loops is to manually unroll the loop.

    In your code, the outer loop iterates 3 times. Removing the loop code, you are left with these assignments for M and P:

    int M = NUMBER_OF_INPUTS; 
    int P = 0; 
    
    P = M;
    P = M;
    P = M;
    
    M = M + K;                   
    M = M + K;                   
    M = M + K;                   
    

    Those assignments should be inside a procedural block. Also, as you can see, it doesn't make much sense to assign the same value to P multiple times.

    With that explanation, I recommend trying to design something simpler without the loops at first.