Reputation: 549
I'm a bit embarrassed as I thought this would be easy to write.
A fixed-width one-hot encoder would be easy to write with a case statement. But I'm wracking my brain trying to write a parameterized N-bit one-hot encoder. So far, I have:
module onehot_enc #(
parameter WIDTH
) (
input logic [WIDTH-1:0] in,
input logic [$clog2(WIDTH-1:0] out
);
genvar i;
generate
for(i = 0; i < WIDTH; i++) begin
assign out |= in[i] ? i : 0;
end
endgenerate
endmodule
But apparently "|=" is not an operator.
Anyone have any suggestions on writing this? It seemed so simple to do in my head...
Upvotes: 1
Views: 8218
Reputation: 1
This only works if your one-hot is truly one-hot, but it doesn't try to priorty-encode the inputs, so it synthesizes smaller.
// one-hot to binary encode
function binary_type_t to_binary_f(vector_type_t v);
to_binary_f = '0;
for (int i=0; i<$bits(binary_type_t); i++) begin
for (int j=0; j<$bits(vector_type_t); j++) to_binary_f[i] |= (j%(2**(i+1)) >= 2**i) ? v[j] : '0;
end
endfunction
Upvotes: 0
Reputation: 12344
You definitely need a loop for it. No generate block should be used here. The encider can be implemented within an always block.
Because you used 'logic' in your example, I assumed that system verilog syntax is ok here. So, please add the 'system verilog' tag.
In the following example the loop runs through the whole set of iterations without any 'break' to make it synthesizable. So, in this case the last '1' wins. The first out=0
statement assigns the default value of '0' to 'out'. It also makes the code combinational. Otherwise it would be a latch.
module onehot_enc #(
parameter WIDTH = 1
) (
input logic [WIDTH-1:0] in,
output logic [$clog2(WIDTH)-1:0] out
);
always_comb begin
out = 0;
for (int i = 0; i < WIDTH; i++) begin
if (in[i])
out = i;
end
end
endmodule
Upvotes: 3