Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generate If Statements in Verilog

Tags:

verilog

I'm trying to create a synthesizable, parametrized priority encoder in Verilog. Specifically, I want to find the least significant 1 in a vector and return a vector containing just that 1. For example:

IN[3:0] | OUT[4:0]
--------+---------
1010    | 00010
1111    | 00001
0100    | 00100
0000    | 10000   (special case)

So if the vectors are four bits wide, the code is:

if (in[0]==1'b1) least_one = 1;
else if (in[1]==1'b1) least_one = 2;
else if (in[2]==1'b1) least_one = 4;
else if (in[3]==1'b1) least_one = 8;
else out = 16; // special case in==0, set carry bit

I need a general, scalable way to do this because the input/output vector length is parametrized. My current code is:

module least_one_onehot
#(parameter ADDR_WIDTH=4)
(output reg [ADDR_WIDTH:0] least_one,
input [ADDR_WIDTH-1:0] in);

genvar i;

always @(in) begin
    if (in[0]==1'b1) least_one = 1;
    generate for (i=1; i<ADDR_WIDTH; i=i+1) begin : U 
        else if (in[i]==1'b1) least_one = 2**i; 
        end 
        endgenerate
    else least_one = 2**ADDR_WIDTH;
    end

endmodule

When I try to compile this, I receive the following errors:

file: least_one_onehot.v
        generate for (i=1; i<ADDR_WIDTH; i=i+1) begin : U
               |
ncvlog: *E,GIWSCP (least_one_onehot.v,10|8): Generated instantiation can only be valid within a module scope [12.1.3(IEEE 2001)].
                        else if (in[i]==1'b1) least_one = 2**i; 
                           |
ncvlog: *E,NOTSTT (least_one_onehot.v,11|6): expecting a statement [9(IEEE)].
                endgenerate
                          |
ncvlog: *E,GIWSCP (least_one_onehot.v,13|12): Generated instantiation can only be valid within a module scope [12.1.3(IEEE 2001)].
                else least_one = 2**ADDR_WIDTH;
                   |
ncvlog: *E,NOTSTT (least_one_onehot.v,14|5): expecting a statement [9(IEEE)]

I've tried various arrangements of the generate, if, and always statements, all without success. Anyone know the proper syntax for this? Case-statement implementation or other alternatives would also be fine. Thanks.

like image 644
DrDean Avatar asked Dec 03 '25 18:12

DrDean


1 Answers

I think you misunderstand how generate works. It isn't a text pre-processor that emits the code in between the generate/endgenerate pair with appropriate substitutions. You have to have complete syntactic entities withing the pair. I don't have access to a simulator right this minute but this might do the trick for you (totally untested)

genvar i;
generate
    for (i = 1; i < ADDR_WIDTH; i = i + 1) begin : U
        least_one[i] = in[i] & ~|in[i - 1:0];
    end
endgenerate
least_one[0] = in[0];
least_one[ADDR_WIDTH] = ~|in;

Ordinarily Verilog would complain about the non-constant bit slice width but since it's within a generate loop it might work.

Failing something like the above you just test for the first set bit in a for-loop and then decode that result.

like image 150
Brian Magnuson Avatar answered Dec 07 '25 01:12

Brian Magnuson



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!