One Hot to Binary Encoder
This function will take a one hot binary vector and encode it into binary. If the left most bit of the one hot input is set, the output is zero.
Synthesis:
The function should synthesise to the minimum number of OR gates required to convert one hot to binary.
Reuse:
The function uses unconstrained parameters so it can be reused for a binary vector of any size (n), and a one-hot vector of size 2**n. By removing the assert statement, the function can be used with vectors of any size, though the results are undocumented if the vector sizes are not n and 2**n.
package one_hot_encode_p is
function one_hot_to_binary(One_Hot : bit_vector ; size:natural) return bit_vector;
end package;
package body one_hot_encode_p is
function one_hot_to_binary(One_Hot : bit_vector ; size:natural) return bit_vector is
variable Bin_Vec_Var : bit_vector(size-1 downto 0);
begin
assert 2**size = One_Hot'length
report "Vectors wrong lengths!"
severity failure;
Bin_Vec_Var := (others => '0');
for I in Bin_Vec_Var'range loop
for J in One_Hot'range loop
if (((J / (2**I)) mod 2) = 0) then
Bin_Vec_Var(I) := Bin_Vec_Var(I) or One_Hot(J);
end if;
end loop;
end loop;
return Bin_Vec_Var;
end function;
end package body;
To use this function, use the appropriate library and package, then simply call the function with the one hot vector and output size as parameters:
use work.one_hot_encode_p.all;
architecture Demo of one_hot is
begin
process(One_Hot)
begin
Bin_Vec <= one_hot_to_binary(One_Hot , Bin_Vec'length);
end process;
end;
How It Works:
The basic idea is simple - it use several bit masks, one for each bit in the binary output. Each bit mask is the same size as the one hot vector. The bit mask is then combined with the original one hot vector.
Consider an input vector 0001000000000000
For bit 0, the bit mask is 0101010101010101
For bit 1, the bit mask is 0011001100110011
For bit 2, the bit mask is 0000111100001111
For bit 3, the bit mask is 0000000011111111
So, the output is 0011, found by reading the column corresponding to the 1 in the original input vector.
The bit mask is calculated using two nested for loops. The first loop (I) counts through each bit in the output, while the second loop (J) then counts through each bit of the input. There is a clear pattern in the bit masks - it is simply a number of 0s followed by the same number of 1s. The pattern then repeats. In general, for mask n there are always 2**n 0s followed by 2**n 1s. Since we want one mask for each bit in the output, and I is looping through each bit of the output, each mask must use (2**I) 0s followed by (2**I) 1s. As J loops through each bit in the mask/one hot input, J/2**I is constant for each block of 1s or 0s. Furthermore, if J/2**I is even (mod 2 = 0) then we must be at a 1 in the bit mask!