Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

log2 function?

221 views
Skip to first unread message

Mikhail Matusov

unread,
Mar 24, 2000, 3:00:00 AM3/24/00
to
Hi all,

I am doing a parameterizable design where I need to use log2 function to
determine parameter value for a component instantiated inside of this
design. What library should I include if it is at all possible? Here is the
idea of what I am trying to do:


library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
use work.defines.all;

entity par_design is
generic (size: integer := 4);
port (
clk : in STD_LOGIC;
din : in STD_LOGIC_VECTOR(size-1 downto 0);
dout : buffer STD_LOGIC
);
end par2ser;

architecture par_design_rtl of par_design is

begin

CNT: COUNTER
generic map (n => log2(size))
port map (
....
);

SHR: SHIFTREG
generic map (n => size)
port map (
....
);

end par_design_rtl;


I know I could define 'size' differently and use 'size' and '2**size '
instead of trying to find log2 function but it would not be what I want the
module to look like from the top hierarchy...

Thanks,
Mikhail Matusov


a...@z.com

unread,
Mar 24, 2000, 3:00:00 AM3/24/00
to
Hi Mikhail,

You do not need any library, just define your own function:

function LOG2(COUNT:INTEGER) return INTEGER is -- COUNT should be >0
variable TEMP:INTEGER;
begin
TEMP:=0;
while COUNT>1 loop
TEMP:=TEMP+1;
COUNT:=COUNT/2;
end loop;
return TEMP;
end;

Regards,
Catalin


Ray Andraka

unread,
Mar 25, 2000, 3:00:00 AM3/25/00
to
I wrote this quite some time ago. It resides in a package I use in many of my
designs. Should do the trick for you.

function Log2( input:integer ) return integer is
variable temp,log:integer;
begin
temp:=input;
log:=0;
while (temp /= 0) loop
temp:=temp/2;
log:=log+1;
end loop;
return log;
end function log2;


Mikhail Matusov wrote:

--
-Ray Andraka, P.E.
President, the Andraka Consulting Group, Inc.
401/884-7930 Fax 401/884-7950
email rand...@ids.net
http://users.ids.net/~randraka

Jos De Laender

unread,
Mar 28, 2000, 3:00:00 AM3/28/00
to

Hi,

people have answered here with a (nearly)
correct implementation of log2(). (Catalins
answer contained an error in COUNT being used for
updating, which is not possible in this function.
One should make a local copy as Ray did)

Nevertheless, I would not be surprised if the
answer doesn't help Mikhail.

Once he goes to synthesis (at least Synopsys, but
I believe others will give similar problems),
the log2() function will give problems.

The reason is that he wants to determine the
generics in some static way. ('standardeze' talkers
will express this nicer). However the loop calculation
inside the log2() does make believe synthesizer that
some circuit is involved (not static) after which
he complains and stop.

Funny enough, there's an elegant solution to it
by describing the log2 function recursive (no syntax):

log2(N) : if N=1 then return 0 else return 1+log2(N/2)

The reason is that this is for synthesis unrolled at
analysis time. So the function is expanded with concrete
numbers for N. And so it works as no further calculations
(others than SomeConstant+SomeConstant) are involved.

I'm pretty sure that's where Mikhail is looking after ...

Best regards,

Jos

a...@z.com

unread,
Mar 28, 2000, 3:00:00 AM3/28/00
to
Hi Jos,

Jos De Laender wrote:

> Hi,
>
> people have answered here with a (nearly)
> correct implementation of log2(). (Catalins
> answer contained an error in COUNT being used for
> updating, which is not possible in this function.
> One should make a local copy as Ray did)
>

You are of course right. My solution can also be fixed with:

function LOG2(variable COUNT:INTEGER) return INTEGER is -- COUNT should be >0


variable TEMP:INTEGER;
begin
TEMP:=0;
while COUNT>1 loop
TEMP:=TEMP+1;
COUNT:=COUNT/2;
end loop;
return TEMP;
end;

>


> Nevertheless, I would not be surprised if the
> answer doesn't help Mikhail.
>
> Once he goes to synthesis (at least Synopsys, but
> I believe others will give similar problems),
> the log2() function will give problems.
>
> The reason is that he wants to determine the
> generics in some static way. ('standardeze' talkers
> will express this nicer). However the loop calculation
> inside the log2() does make believe synthesizer that
> some circuit is involved (not static) after which
> he complains and stop.
>
> Funny enough, there's an elegant solution to it
> by describing the log2 function recursive (no syntax):
>
> log2(N) : if N=1 then return 0 else return 1+log2(N/2)
>
> The reason is that this is for synthesis unrolled at
> analysis time. So the function is expanded with concrete
> numbers for N. And so it works as no further calculations
> (others than SomeConstant+SomeConstant) are involved.
>
> I'm pretty sure that's where Mikhail is looking after ...
>
> Best regards,
>
> Jos

While I am not saying that you are not right about Synopsis (especially FPGA
Express) my corrected solution works well with Synplicity. Recursion is a
powerful tool for describing recursive structures like adder trees and generic
width gates but unless your synthesis tools constrains you there is no reason to
use recursion where a simple loop will do.

I would also like to make the observation that for COUNT not a power of 2 you
really want floor(log2(COUNT-1))+1 and not just floor(log2). The following rather
didactic example shows what I think Mikhail is looking for:

library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;

entity mux is
port(CLK:in STD_LOGIC;
RST:in STD_LOGIC;
I:in STD_LOGIC_VECTOR; -- the input size is unconstrained, better than
generics
O:out STD_LOGIC);

end mux;

architecture mux_arch of mux is

-- returns the length of an unsigned vector needed to represent numbers 0 to
COUNT-1
function LOG2(variable COUNT:INTEGER) return INTEGER is -- COUNT should be >0
variable TEMP:INTEGER;
begin
TEMP:=1;
COUNT:=COUNT-1;


while COUNT>1 loop
TEMP:=TEMP+1;
COUNT:=COUNT/2;
end loop;
return TEMP;
end;

signal SEL:UNSIGNED(LOG2(I'length)-1 downto 0);

begin
process(CLK,RST)
begin
if RST='1' then
SEL<=(others=>'0');
elsif rising_edge(CLK) then
if SEL=I'length-1 then
SEL<=(others=>'0');
else
SEL<=SEL+1;
end if;
end if;
end process;

O<=I(I'low+TO_INTEGER(SEL));
end mux_arch;

You would use this generic mux with a matching counter like this:

library IEEE;
use IEEE.std_logic_1164.all;

entity testlog is
port(CLK:in STD_LOGIC;
RST:in STD_LOGIC;
I:in STD_LOGIC_VECTOR(7 downto 0); -- I can be any size here
O:out STD_LOGIC);
end testlog;

architecture testlog_arch of testlog is

component mux
port(CLK:in STD_LOGIC;
RST:in STD_LOGIC;
I:in STD_LOGIC_VECTOR;
O:out STD_LOGIC);
end component;

begin
m1:mux port map (CLK=>CLK,RST=>RST,I=>I,O=>O);
end testlog_arch;

Regards,
Catalin

Ray Andraka

unread,
Mar 28, 2000, 3:00:00 AM3/28/00
to
Mine works fine for synthesis under synplicity. The only problems I've had with
stuff being static have been with the use of the 'length attribute, but not with
my log function.

REcursion is a powerful tool, but be careful because not all the tools can handle
it. I've had a number of problems with recursion in synplicity. Most have been
fixed in the past year, but there are still a few gotchas. Part of the problem
there is teh tech support staff doesn't seem to understand why one would do
recursion. Each time I've had a problem they come back a day or so later saying
something to the effect that my code is calling itself and propose a 'fix' with
addtional components which fix the test case but not the general case for which I
wanted to use recursion in the first place.

Jos De Laender wrote:

> Hi,
>
> people have answered here with a (nearly)
> correct implementation of log2(). (Catalins
> answer contained an error in COUNT being used for
> updating, which is not possible in this function.
> One should make a local copy as Ray did)
>

> Nevertheless, I would not be surprised if the
> answer doesn't help Mikhail.
>
> Once he goes to synthesis (at least Synopsys, but
> I believe others will give similar problems),
> the log2() function will give problems.
>
> The reason is that he wants to determine the
> generics in some static way. ('standardeze' talkers
> will express this nicer). However the loop calculation
> inside the log2() does make believe synthesizer that
> some circuit is involved (not static) after which
> he complains and stop.
>
> Funny enough, there's an elegant solution to it
> by describing the log2 function recursive (no syntax):
>
> log2(N) : if N=1 then return 0 else return 1+log2(N/2)
>
> The reason is that this is for synthesis unrolled at
> analysis time. So the function is expanded with concrete
> numbers for N. And so it works as no further calculations
> (others than SomeConstant+SomeConstant) are involved.
>
> I'm pretty sure that's where Mikhail is looking after ...
>
> Best regards,
>
> Jos

> Mikhail Matusov wrote:
> >
> > Hi all,
> >
> > I am doing a parameterizable design where I need to use log2 function to
> > determine parameter value for a component instantiated inside of this
> > design. What library should I include if it is at all possible? Here is the
> > idea of what I am trying to do:
> >

> > library IEEE;
> > use IEEE.std_logic_1164.all;
> > use IEEE.numeric_std.all;

--

Mikhail Matusov

unread,
Mar 28, 2000, 3:00:00 AM3/28/00
to
Hi,

Thank you all. Jos is absolutely right. I tried Catalin's implementation and it
gave me exactly that problem during synthesis that Jos was predicting. I have not
tried recursive implementation yet as Jos suggested but I am going to do it right
now.

Jos De Laender wrote:

> Hi,
>
> people have answered here with a (nearly)
> correct implementation of log2(). (Catalins
> answer contained an error in COUNT being used for
> updating, which is not possible in this function.
> One should make a local copy as Ray did)

I guess something is wrong with my news server as I have never seen Ray's
posting....

Thanks again for your help, guys!

Mikhail


Jos De Laender

unread,
Mar 29, 2000, 3:00:00 AM3/29/00
to

a...@z.com wrote:
>
> While I am not saying that you are not right about Synopsis (especially FPGA
> Express) my corrected solution works well with Synplicity. Recursion is a
> powerful tool for describing recursive structures like adder trees and generic
> width gates but unless your synthesis tools constrains you there is no reason to
> use recursion where a simple loop will do.

First of all, I completely agree that recursion
should not be abused. From software point of view
it is nonsense to write log2 recursively. It
should be your loop.

Secondly, it's super that Synplicity can find out there
are no real calculations involved. Does it really mean
you can assign a _generic_ a value like log2(8) ? This
is not really straightforward : during your synthesis,
which is basically a process on structural level, you
have to do some simulation/calculation in between
(evaluating log2(8)).
Where are the limits for Synplicity ? I do assume that
the function basically must be pure ? (now() cannot be
part of it f.i. , nor a global signal ?)
Anyhow Synopsys-DC doesn't support it.



>
> I would also like to make the observation that for COUNT not a power of 2 you
> really want floor(log2(COUNT-1))+1 and not just floor(log2). The following rather
> didactic example shows what I think Mikhail is looking for:

Didn't consider the case. I assumed a power of 2.
You're right of course.

a...@z.com

unread,
Mar 29, 2000, 3:00:00 AM3/29/00
to
Hi Jos,

As a matter of fact yes, you can assign log2(8) to a generic. In the example I used in
my last message you can implement the counter like that:

library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;

entity cnt is
generic(WIDTH:INTEGER);


port(CLK:in STD_LOGIC;
RST:in STD_LOGIC;

O:out UNSIGNED(WIDTH-1 downto 0)); -- generic width instead of unconstrained
end cnt;

architecture cnt_arch of cnt is

signal SEL:UNSIGNED(O'range);

begin
process(CLK,RST)
begin
if RST='1' then
SEL<=(others=>'0');
elsif rising_edge(CLK) then

SEL<=SEL+1;
end if;
end process;

O<=SEL;
end cnt_arch;

and instantiate it in mux like this:

signal SEL:UNSIGNED(LOG2(I'length)-1 downto 0);

c1:cnt generic map(WIDTH=>LOG2(I'length))
port map(CLK=>CLK,RST=>RST,O=>SEL);

where I can be of any length. Both solutions work well in Synplicity but I find the
first one that uses implicit generics passed trough unconstrained arrays more elegant.
There are however situations where the use of generics is required and it is good to
know that these constructs work, at least in some synthesis tools.

Synthesis tools used to be very limited in the VHDL constructs you were allowed to use.
Synplicity has made huge progress in this area in the last couple of years. I suspect
that Leonardo also has similar capabilities. Can anybody confirm that?

Regards,
Catalin

0 new messages