Abhishek Revinipati
Abhishek Revinipati

Reputation: 33

How do i make a synthesizable parameterized encoder on Verilog?

I have tried to do it this way:

module encoder 
#(
    parameter WIDTH = 4
 )
(
    input wire [WIDTH-1: 0] in,
    output reg [$clog2(WIDTH)-1: 0] out
);

  genvar i; 
  generate
    for (i = 0;i < WIDTH;i = i+1) 
    begin :gen_block
      always @* 
      begin
        if (in[i]==1'b1) 
          out = i;
      end
    end
  endgenerate
endmodule

It works well in the simulation, but I'm not sure if this can be synthesized. The generate block will produce multiple copies of the always block, and I'm guessing there will be a race condition between the previous value of out and the updated value of out.

Am I correct about assuming that this code can't be synthesized? If so, What do I change to make it synthesize correctly?

Upvotes: 0

Views: 1687

Answers (2)

user17130007
user17130007

Reputation: 1

you can avoid break by initializing i = N-1

module encoder 
#(
    parameter WIDTH = 4
 )
(
    input wire [WIDTH-1: 0] in,
    output logic [$clog2(WIDTH)-1: 0] out
);
      always_comb begin
        out = 'x; // don't care if no 'in' bits set
        for (int i = N-1 ;i >=0;i--)
            if (in[i]) begin
               out = i;
        end
    end
endmodule

Upvotes: 0

dave_59
dave_59

Reputation: 42623

Yes, you do have a race condition in simulation and it is not synthesizable. You cannot have multiple always blocks making assignments to the same variable in parallel( happens when more than one bit in in is set). You want a regular procedural-for loop, not a generate-for loop.

module encoder 
#(
    parameter WIDTH = 4
 )
(
    input wire [WIDTH-1: 0] in,
    output logic [$clog2(WIDTH)-1: 0] out
);
      always_comb begin
        out = 'x; // don't care if no 'in' bits set
        for (int i = 0;i < WIDTH;i++)
            if (in[i]==1'b1) begin
               out = i;
               break; // priority goes from LSB-to-MSB
        end
    end
endmodule

Edit: For tools that do not support break yet

always_comb begin
        bit Break;
        Break = 0;
        out = 'x; // don't care if no 'in' bits set
        for (int i = 0;i < WIDTH;i++)
            if (in[i]==1'b1 && !Break) begin
               out = i;
               Break = 1;
        end
    end

Upvotes: 2

Related Questions