Code VHDL - [expand] 1 2 3 4 5 6 7 8 9 10 function log2_unsigned ( x : natural ) return natural is variable temp : natural := x ; variable n : natural := 0 ; begin while temp > 1 loop temp := temp / 2 ; n := n + 1 ; end loop ; return n ; end function log2_unsigned ;
Hello,
I use this VHDL log function for vector length sizing.
function log2_unsigned ( x : natural ) return natural is
variable temp : natural := x ;
variable n : natural := 0 ;
begin
while temp > 1 loop
temp := temp / 2 ;
n := n + 1 ;
end loop ;
return n ;
end function log2_unsigned ;
The problem is that is rounds down results.
For example:
log2 of 50,000,000 is 25.575
However the output of my function rounds it down to 25.
I want, to round it up to 26 instead. How should I modify it ?
-----------------------------------------------------------------------------------
-- Combine the ceil and log2 functions. ceil_log2(x) then gives the minimum number
-- of bits required to represent 'x'. ceil_log2(4) = 2, ceil_log2(5) = 3, etc.
-----------------------------------------------------------------------------------
function ceil_log2 (Arg : positive) return natural is
variable RetVal: natural;
begin
RetVal := log2(Arg);
if (Arg > (2**RetVal)) then
return(RetVal + 1); -- RetVal is too small, so bump it up by 1 and return
else
return(RetVal); -- Just right
end if;
end function ceil_log2;
Code VHDL - [expand] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 function log2_unsigned ( x : natural ) return natural is variable temp : natural := x ; variable n : natural := 0 ; begin while temp > 1 loop temp := temp / 2 ; n := n + 1 ; end loop ; if x > 2 ** n then return ( n + 1 ) ; else return ( n ) ; end if ; end function log2_unsigned ;
Hello Kevin,
Combine how ?
Please elaborate
---------- Post added at 20:14 ---------- Previous post was at 19:34 ----------
Do you mean like this
USE ieee.math_real.log2;
USE ieee.math_real.ceil;
CONSTANT vector_length: integer = integer(ceil(log2(1.0*highest_value)));
I simply showed how I took my own log2 function (which appears to be similar to yours) and combined that with a simple ceiling function to solve the same problem that you are trying to solve. Whether or not yours is equivalent or not is up to you to check.Kevin,
Can you explain please how what I wrote is different then combining the 2 functions ?
Even though these functions are used to compute constants and therefore could be synthesizable, support for anything having to do with 'real' type by a synthesis tool should be checked first.I assume, that the log2 problem is related to compile time calculations? Instead of writing your own integer log2() or ceil(log2()) functions, you can also utilize ieee.math real for the calculation.
function log2_unsigned ( x : natural ) return natural is
variable temp : natural := x ;
variable n : natural := 1 ;
begin
while temp > 1 loop
temp := temp / 2 ;
n := n + 1 ;
end loop ;
end function log2_unsigned ;
Code VHDL - [expand] 1 2 3 4 5 6 7 8 9 10 11 function log2( i : natural) return integer is variable temp : integer := i; variable ret_val : integer := 1; --log2 of 0 should equal 1 because you still need 1 bit to represent 0 begin while temp > 1 loop ret_val := ret_val + 1; temp := temp / 2; end loop; return ret_val; end function;
PHP:function log2_unsigned ( x : natural ) return natural is variable temp : natural := x ; variable n : natural := 1 ; begin while temp > 1 loop temp := temp / 2 ; n := n + 1 ; end loop ; end function log2_unsigned ;
like that ?
yes.
Its exactly the same as the "log2" function Ive used for several years for sizing arrays.
copied and pasted from my "testbench_tools" package:
Code VHDL - [expand] 1 2 3 4 5 6 7 8 9 10 11 function log2( i : natural) return integer is variable temp : integer := i; variable ret_val : integer := 1; --log2 of 0 should equal 1 because you still need 1 bit to represent 0 begin while temp > 1 loop ret_val := ret_val + 1; temp := temp / 2; end loop; return ret_val; end function;
[syntax=vhdl]library ieee;
use ieee.std_logic_1164.all;
use ieee.math_real.all;
entity tb_log2 is
end tb_log2;
architecture rtl of tb_log2 is
----------------------------------------------------------------------------------------
-- A synthesizable function that returns the integer part of the base 2 logarithm for a
-- positive number (posted by Tuukka Toivonen) to VHDL FAQ forum
-- http://www.vhdl.org/comp.lang.vhdl/FAQ1.html
----------------------------------------------------------------------------------------
function log2 (x : natural) return natural is
begin
if x <= 1 then
return 0;
else
return log2 (x / 2) + 1;
end if;
end function log2;
-----------------------------------------------------------------------------------
-- Combine the ceil and log2 functions. ceil_log2(x) then gives the minimum number
-- of bits required to represent 'x'. ceil_log2(4) = 2, ceil_log2(5) = 3, etc.
-----------------------------------------------------------------------------------
function ceil_log2 (Arg : positive) return natural is
variable RetVal: natural;
begin
RetVal := log2(Arg);
if (Arg > (2**RetVal)) then
return(RetVal + 1); -- RetVal is too small, so bump it up by 1 and return
else
return(RetVal); -- Just right
end if;
end function ceil_log2;
function log2_unsigned ( x : natural ) return natural is
variable temp : natural := x ;
variable n : natural := 1 ;
begin
while temp > 1 loop
temp := temp / 2 ;
n := n + 1 ;
end loop ;
return(n); -- KJ added
end function log2_unsigned ;
function td_log2( i : natural) return integer is
variable temp : integer := i;
variable ret_val : integer := 1; --log2 of 0 should equal 1 because you still need 1 bit to represent 0
begin
while temp > 1 loop
ret_val := ret_val + 1;
temp := temp / 2;
end loop;
return ret_val;
end function;
begin
process
begin
report LF &
"------------------------------------" & LF &
"Testing TrickyDicky's implementation" & LF &
"------------------------------------";
for i in 1 to 31 loop
assert real(ceil_log2(i)) = ceil(log2(real(i)))
report "OOPS! Log2 mismatch for i =" & integer'image(i) & LF &
"ceil_log2(i)=" & integer'image(ceil_log2(i)) & LF &
"ieee.math_real.log2(i)=" & real'image(ceil(log2(real(i))))
severity ERROR;
assert ceil_log2(i) = td_log2(i)
report "OOPS! Log2 mismatch for i =" & integer'image(i) & LF &
"ceil_log2(i)=" & integer'image(ceil_log2(i)) & LF &
"td_log2(i)=" & integer'image(td_log2(i))
severity ERROR;
end loop;
report LF &
"-------------------------------" & LF &
"Testing shaiko's implementation" & LF &
"-------------------------------";
for i in 1 to 31 loop
assert ceil_log2(i) = log2_unsigned(i)
report "OOPS! Log2 mismatch for i =" & integer'image(i) & LF &
"ceil_log2(i)=" & integer'image(ceil_log2(i)) & LF &
"log2_unsigned(i)=" & integer'image(log2_unsigned(i))
severity ERROR;
end loop;
report "Simulation completed";
wait;
end process;
end rtl;[/syntax]
Thanks for the post K-J
Can you give a specific example when TrickyDick's suggestion (to Initialise n to 1) won't work ?
I couldn't find an exception
K-J, look at the first posting in the thread. The goal is not a true log2 function, but a way to find the number of bits needed to represent a number.
TrickyDicky's function does this correctly.
Not really, my code computes ceil(log2(N)), TrickyDicky's code compute ceil(log2(N+1). But that's all beside the point. What somebody using the function wants (and was the question posed by shaiko to start the thread) is something to compute the proper vector range needed to represent a range of numbers. My function does that, the other does not. But don't take my word for it, simply try to represent a set of vectors. Presumably the representation is one of the following:There can be no doubt, that log2(1) as well as ceil(log2(1)) are 0. But it's not the correct bit count of an array to represent the numbers 0..N, which must be ceil(log2(N+1)). Kevin's code is already accounting for the +1.
x Range Ceil(log2(x)) ceil_log2(x) td_log2(x)
2 0..1 1.000000e+000 1 2 -- OOPS
3 0..2 2.000000e+000 2 2
4 0..3 2.000000e+000 2 3 -- OOPS
5 0..4 3.000000e+000 3 3
6 0..5 3.000000e+000 3 3
7 0..6 3.000000e+000 3 3
8 0..7 3.000000e+000 3 4 -- OOPS
9 0..8 4.000000e+000 4 4
10 0..9 4.000000e+000 4 4
11 0..10 4.000000e+000 4 4
12 0..11 4.000000e+000 4 4
13 0..12 4.000000e+000 4 4
14 0..13 4.000000e+000 4 4
15 0..14 4.000000e+000 4 4
16 0..15 4.000000e+000 4 5 -- OOPS
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?