# How to define a counter whose width is big enough to hold integer 27?

• posted
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
• posted
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
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
• posted
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
• posted
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.
```--

Rick```
• posted
Isn't it a floor function that is required? Floor and add one. No?
```--

Rick```
• posted
ceiling(log2(8+1)) = 4;
What's the trouble?
Regards,
Mark
• posted
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.
```--

Rick```
• posted
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
• posted
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"
```--

Rick```
• posted
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
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);
• posted
Code like this is why people use Verilog. I'm just sayin'. ;)
Oh, it's also wrong.
```--

Rick```
• posted
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
• posted
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.
```--

Rick```
• posted
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
• posted
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.
```--

Rick```
• posted
Have you considered this?
signal Count : integer range 0 to N;
```--

Rick```
• posted
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