2
\$\begingroup\$

I am trying to write a code that converts binary to thermometer code. Thermometer (a.k.a. unary) coding is frequently used in digital systems applications to represent a natural number.

In a thermometer code, an N-bit binary number is represented by a (2 ** N)-bit digital word, which has m zeros followed by (N - m) ones or vice-versa. Basically, if you have a 4-bit binary number say 0110 (decimal is 6), the equivalent thermometer code will be of width 2^4 (=16), and its value will be 6 ones following 10 zeroes (0000000000111111).

module model (
    input [7:0] din,
    output reg [255:0] dout
);

logic [255:0] tempout;
int count;

always @ (*) begin
    count  <= din;
    tempout<= '0;
end

generate
    for (genvar i=0; i <= count; i++) begin
        tempout[i] = 1;
    end
endgenerate

assign dout = tempout;
endmodule

I am getting the following error for this code:

%Error:  Loop unrolling failed.
%Error-UNSUPPORTED:  Unsupported: Can't unroll generate for; Unable to unroll loop
For error description see https://verilator.org/warn/UNSUPPORTED?v=4.228

What is wrong with my code?

I have a working code also, but it goes through the loop 2^N number of times, and I want to reduce that.

localparam LP_DATA_SIZE = 8;

generate

    for (genvar i = 0; i < 2**LP_DATA_SIZE; i++) begin
        assign dout[i] = (i <= din);
    end

endgenerate
\$\endgroup\$
2
  • 2
    \$\begingroup\$ Your "working code" is the correct way to do this. The number of iterations of a for loop must be known at compile time; it can't be controlled by an input port. \$\endgroup\$
    – Dave Tweed
    Commented May 14, 2023 at 10:51
  • 1
    \$\begingroup\$ +1 Congrats for the well written question. "it goes through the loop 2^N number of times" It actually doesn't. It as hardware description language, and your interpretation seems to be more related to software. \$\endgroup\$
    – devnull
    Commented May 14, 2023 at 12:03

1 Answer 1

2
\$\begingroup\$

What is wrong with my code?

You get the Verilator error message because the generate for loop needs a constant for the end condition, not a variable. You can't use count for the end condition because it is a variable (int). Your "working code" correctly uses a constant (localparam) for the end condition.

Another problem with the code is that the following assignment to tempout either needs the assign keyword, or it must be inside an always block inside the generate construct:

tempout[i] = 1;

Also, you would be making assignments to tempout from multiple places (the 1st always block and the generate) which would cause contention.

it goes through the loop 2^N number of times, and I want to reduce that.

There is no concern for your working code. That is the proper way to describe the hardware you want. The for loop simply creates 256 parallel assignments (one for each bit of dout), which is what you are trying to achieve.

\$\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.