- posted
6 years ago

I have a constant N = 27, how to define a counter whose width is big enough to hold integer 27?

Or how to get a constant = log N? Where "log" is a logarithm with base 2.

Thank you.

Weng

- posted
6 years ago

Hi,

I have a constant N = 27, how to define a counter whose width is big enough to hold integer 27?

Or how to get a constant = log N? Where "log" is a logarithm with base 2.

Thank you.

Weng

I have a constant N = 27, how to define a counter whose width is big enough to hold integer 27?

Or how to get a constant = log N? Where "log" is a logarithm with base 2.

Thank you.

Weng

Loading thread data ...

- posted
6 years ago

The function you want is the ceiling of log base 2. In Verilog
this is $clog2(). If you don't have a similar function it's quite
easy to make, since it's generally accomplished by shifting the
input value right until it becomes zero and counting the shifts
required to get there.

-- Gabor

- posted
6 years ago

Hi Gabor,

I want to use the (log N) to be the width of a counter:

signal Count : unsigned((log N)-1 downto 0); -- it can hold a known largest number N

Thank you.

Weng

I want to use the (log N) to be the width of a counter:

signal Count : unsigned((log N)-1 downto 0); -- it can hold a known largest number N

Thank you.

Weng

- posted
6 years ago

What exactly is the issue? ieee.math_real defines a log2 function that can be used to define the upper bound. Actually what you want is
ceil(log2(N))

Kevin

Kevin

- posted
6 years ago

I don't think you need a ceiling function. I think you need a floor
function and add 1. log2(8) = 3.0, log2(9) = 3.17, both need 4 bits to
represent them in binary. A ceiling function will return 3 for 8 and 4
for 9. So it would be

signal Count : unsigned(flog2(N) downto 0);

Writing flog2(N) should be trivial.

signal Count : unsigned(flog2(N) downto 0);

Writing flog2(N) should be trivial.

-- Rick

- posted
6 years ago

Isn't it a floor function that is required? Floor and add one. No?

-- Rick

- posted
6 years ago

ceiling(log2(8+1)) = 4;

What's the trouble?

Regards,

Mark

What's the trouble?

Regards,

Mark

- posted
6 years ago

This can work if you add the 1 first, but the number you want is 3. So
you have to subtract 1 from this result. Which is simpler?

Personally I prefer the simpler approach of flog2(N) rather than clog2(N+1)-1 to get where this needs to go. flog2 is a very simple function to write. If you use floating point routines for log2 and ceiling you need to then convert to integer. Are there integer functions for these routines or do you need to write them? I guess that wouldn't make sense since log2 either returns a floating point number or does some form of truncation or rounding.

Personally I prefer the simpler approach of flog2(N) rather than clog2(N+1)-1 to get where this needs to go. flog2 is a very simple function to write. If you use floating point routines for log2 and ceiling you need to then convert to integer. Are there integer functions for these routines or do you need to write them? I guess that wouldn't make sense since log2 either returns a floating point number or does some form of truncation or rounding.

-- Rick

- posted
6 years ago

Hi Gabor, KJ, Rich and Mark,

After your posts, I realized that a user-defined function's returned integer value can be used as boundary limit!!! Before the post I didn't know it.

So I decided to accept Gabor's method to write an integer function log2(integer N) in my design so that it can be repeatedly used later for my life.

Thank you.

Weng

Here is the code:

-- = floor of log2(); log2(27) = 5.

function log2(integer: N) return integer is variable K : integer; variable M : integer; -- = M mod 2 begin K := 0; M := N; loop1: while M /= 0 loop M := M mod 2; -- it cannot use M := M srl 2, because N is an integer K := K+1; end loop;

return K; end log2; -- to be debugged

After your posts, I realized that a user-defined function's returned integer value can be used as boundary limit!!! Before the post I didn't know it.

So I decided to accept Gabor's method to write an integer function log2(integer N) in my design so that it can be repeatedly used later for my life.

Thank you.

Weng

Here is the code:

-- = floor of log2(); log2(27) = 5.

function log2(integer: N) return integer is variable K : integer; variable M : integer; -- = M mod 2 begin K := 0; M := N; loop1: while M /= 0 loop M := M mod 2; -- it cannot use M := M srl 2, because N is an integer K := K+1; end loop;

return K; end log2; -- to be debugged

- posted
6 years ago

I can't recall the last time I wrote even a simple program that was 100%
correct the first time. I think when you debug your program it will
need to be M := M / 2;

You might want to make your comment, "it cannot use M := M srl 1, because N is an integer"

You might want to make your comment, "it cannot use M := M srl 1, because N is an integer"

-- Rick

- posted
6 years ago

Oh yeah, you also need to change "while M /= 0" to "while M > 1".
Otherwise you will get a return value of 1 for 1, 2 for 2, 3 for 4, 4
for 8, etc, which are all 1 more than the correct value and not optimal
for your use.

-- Rick

- posted
6 years ago

Yes, KJ is right. In code, this would look like (I use this very often in synthesizable code):

signal cnt: u_unsigned(positive(ceil(log2(real(N))))-1 downto 0);

signal cnt: u_unsigned(positive(ceil(log2(real(N))))-1 downto 0);

- posted
6 years ago

Code like this is why people use Verilog. I'm just sayin'. ;)

Oh, it's also wrong.

Oh, it's also wrong.

-- Rick

- posted
6 years ago

Yes, but explicit type conversions are also one of VHDL's strengths. :)
It's better to be explicit in your code when it comes to what types you're using, instead of the tool (or language) doing the conversions implicitly for you - and later on you find out that the implicitly conversions aren't what you want.

- dan

- dan

- posted
6 years ago

Over the years I have lived on both sides of the fence. I program
hardware in strongly typed VHDL but when it comes to software I prefer
Forth which has no concept of type. People try to tell me how good
strong typing is and I agree that it can catch problems early that would
not be cause so easily later on, but the verbosity and complexity of
some code is hard to accept. Others just side step that theoretical
issues by pointing out the number of errors made which tools can't catch
such as the one you wrote. You didn't even address that.

Your code has a logical flaw that allocates one bit too few for any value of N that is a power of 2. I suppose the tools would flag that when you try to assign a vector of a different size to it... unless you make a similar mistake elsewhere in which case you won't find out until in simulation you exercise with the max value. If that doesn't happen you will have a very hard time trying to figure out why the design doesn't work correctly in the device.

I'm not trying to knock your code. I'm trying to point out that strong typing can impact your coding and allow mistakes to be missed because of the verbosity. Much simpler would be to write a small function to calculate a vector index max value that would replace the whole positive(ceil(log2(real(N))))-1 thing.

Your code has a logical flaw that allocates one bit too few for any value of N that is a power of 2. I suppose the tools would flag that when you try to assign a vector of a different size to it... unless you make a similar mistake elsewhere in which case you won't find out until in simulation you exercise with the max value. If that doesn't happen you will have a very hard time trying to figure out why the design doesn't work correctly in the device.

I'm not trying to knock your code. I'm trying to point out that strong typing can impact your coding and allow mistakes to be missed because of the verbosity. Much simpler would be to write a small function to calculate a vector index max value that would replace the whole positive(ceil(log2(real(N))))-1 thing.

-- Rick

- posted
6 years ago

Yes you're right there, for values of N that is a power of 2.
My earlier code should have been:
signal cnt: u_unsigned(positive(ceil(log2(real(N+1))))-1 downto 0);

Personally I prefer the simpler approach of flog2(N) rather than clog2(N+1)-1 to get where this needs to go. flog2 is a very simple function to write. If you use floating point routines for log2 and ceiling you need to then convert to integer. Are there integer functions for these routines or do you need to write them? I guess that wouldn't make sense since log2 either returns a floating point number or does some form of truncation or rounding.

Well, I don't mind writing (log2(N+1)-1), though yes, writing a function can make your life easier.

- daniel

Personally I prefer the simpler approach of flog2(N) rather than clog2(N+1)-1 to get where this needs to go. flog2 is a very simple function to write. If you use floating point routines for log2 and ceiling you need to then convert to integer. Are there integer functions for these routines or do you need to write them? I guess that wouldn't make sense since log2 either returns a floating point number or does some form of truncation or rounding.

Well, I don't mind writing (log2(N+1)-1), though yes, writing a function can make your life easier.

- daniel

- posted
6 years ago

I hope I'm not belaboring the point too much, but it's not
(log2(N+1)-1), it's (positive(ceil(log2(real(N+1))))-1) vs. flog2(N).

I think I developed an aversion to the long windiness of VHDL when I was initially learning it and didn't fully understand the typing. Also it was a bit harder back then when "10011" would not be recognized as an SLV and had to be specified as SLV. Trying to convert types all the time in efficient ways was a PITA. So I learned to write my own conversions that did it in a minimum of layers.

VHDL 2008 is better now with a lot of type issues gone. I still like to eliminate long function chains like the floating point calculation used here to count bits.

I think I developed an aversion to the long windiness of VHDL when I was initially learning it and didn't fully understand the typing. Also it was a bit harder back then when "10011" would not be recognized as an SLV and had to be specified as SLV. Trying to convert types all the time in efficient ways was a PITA. So I learned to write my own conversions that did it in a minimum of layers.

VHDL 2008 is better now with a lot of type issues gone. I still like to eliminate long function chains like the floating point calculation used here to count bits.

-- Rick

- posted
6 years ago

Have you considered this?

signal Count : integer range 0 to N;

signal Count : integer range 0 to N;

-- Rick

- posted
6 years ago

teger
M := M mod 2 is not correct. You want to divide M by 2 (M := M / 2) in
stead.

Or, rather than reinventing and debugging the wheel, Google yourself over t o

Or, rather than reinventing and debugging the wheel, Google yourself over t o

formatting link

to find the solution. There
are two log2 algorithms implemented, one uses recursive calls to a log2 fu
nction, the other uses a while loop. Both claim to be synthesizable in wor
king with constants, the recursive version I can vouch works with signals a
s well (i.e. Log_Sig1
- posted
6 years ago

Hi Rick,
I just want to 1 for 1, 2 for 2, 3 for 4, 4 for 8, the bit count that is big enough to hold N.

signal Counter : unsigned(log2(N)-1 downto 0);

I don't want to skip "-1", because all unsigned() expressions in my design uses format name(xxx-1 downto 0);

for all integer M mod 2 == M / 2, but latter is better than former.

So actually my design has no error at all!!!

Weng

signal Counter : unsigned(log2(N)-1 downto 0);

I don't want to skip "-1", because all unsigned() expressions in my design uses format name(xxx-1 downto 0);

for all integer M mod 2 == M / 2, but latter is better than former.

So actually my design has no error at all!!!

Weng

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.