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?
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