0
\$\begingroup\$

I am trying to create an n-bit barrel shifter using the diagram in the answer to this question: https://stackoverflow.com/questions/26551049/vhdl-n-bit-barrel-shifter

I've read that if the variable in a for loop has a single name, then each loop iteration has a separate scope and a separate variable; however, I'm not sure whether the rows in my barrel module will be created in the same style as the reference diagram from above. This is my barrel module:

module barrel
    #(parameter n = 8; parameter control = $clog2(n))
    (input logic[n-1:0] data, input logic [control-1:0] select,
    output logic [n-1:0] result);

    for(genvar i = 0; i < control; i++) begin : label
            logic [n-1:0] tempResult;

            always_comb
                    if(i == 0) row #(n,2**i) shiftLevel(data,select[i],tempResult);
                    else if(i == control-1) row #(n,2**i) shiftLevel(label[i-1].shiftLevel.tempResult,select[i],result);
                    else row #(n,2**i) shiftLevel(label[i-1].shiftLevel.tempResult,select[i],tempResult);
    end

endmodule

My question is this: will the labeled for loop preserve the row modules that I create in each iteration? Or does each row get destroyed once the iteration finishes?

Here are the other modules that I'm using to implement this:

row module:

module row
    #(parameter n=8, parameter shift=4) // n is the number of bits
                                            // shift is the max amount of shift at this level
    (input logic [n-1:0] data,
    input logic select,
    output logic [n-1:0] end);

    for(genvar i = 0; i < n; i++) begin : label
            logic [1:0] dataTemp;

            always_comb
                    dataTemp[0] <= data[i]; // 0 option of the mux is set to the normal data value

                    if(i+shift < n) dataTemp[1] <= data[i+shift]; // assigns the shifted bit
                    else dataTemp[0] <= 0; // assigns 0

            mux2 bit(dataTemp,select,end[i]); // Assembles a mux for a bit of the row output

endmodule

2-1 Mux module:

module mux2(input logic [1:0] data, select,
            output logic y);

    assign y = select ? data[1] : data[0];
endmodule
\$\endgroup\$

1 Answer 1

1
\$\begingroup\$

The SystemVerilog generate statements are elaborated at compile time, they are not procedural code. That means they are processed much like a macro or `ifdef statement, except that they can evaluate parameters, understand scope, and create new scopes. You need to get rid of the always_comb construct. The if/else if/else is also a generated block that produces only one row instance per iteration. Assuming n=8, then you will get three generated for-loop blocks named label[0], label[1], and label[2]. Your code get elaborated as if you could have written something like the following(assuming n gets overridden to 16.:

module barrel
    #(parameter n = 8; parameter control = $clog2(n))
    (input logic[n-1:0] data, input logic [control-1:0] select,
    output logic [n-1:0] result);

            logic [n-1:0] logic[0].tempResult;
            logic [n-1:0] logic[1].tempResult;
            logic [n-1:0] logic[2].tempResult;
            row #(n,1) logic[0].shiftLevel(
                    data,select[0],label[0].tempResult);
            row #(n,2) label[1].shiftLevel(
                    label[0].tempResult,select[1],label[1].tempResult);
            row #(n,4) label[1].shiftLevel(
                    label[1].tempResult,select[2],label[2].tempResult);
            row #(n,8) label[3].shiftLevel(
                    label[2].tempResult,select[3],result);
endmodule

Note that you could not declare identifiers (the variable names or the module instance names) with the label[x]. prefix without using the generate block construct.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.