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
How to define a counter whose width is big enough to hold integer 27?
A user asked for the most efficient way to define a VHDL counter width based on a constant integer value, specifically to hold the number 27. The discussion explores various methods for calculating the required bit-width using logarithms or custom integer functions.
Participants debated the merits of using ieee.math_real functions versus writing a custom synthesizable log2 function to avoid complex type casting and potential off-by-one errors. The thread concludes with the recommendation to use a simple loop-based function or VHDL's built-in integer range constraints for clearer code.
- A custom integer function using a while-loop to divide by two is a common, synthesizable way to calculate bit-width.
- Using ieee.math_real's ceil and log2 functions requires multiple type conversions between real and integer types.
- Calculations like ceil(log2(N)) can lead to off-by-one errors if N is a power of two; using N+1 or a floor-based approach is safer.
- Declaring a signal with an integer range (e.g., range 0 to N) is often simpler than manually calculating bit-width for a counter.
On Friday, March 4, 2016 at 5:34:42 AM UTC-8, Gabor wrote:> Weng Tianxiang wrote: > > 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 > > 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. > > -- > GaborHi 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
On Friday, March 4, 2016 at 1:20:19 PM UTC-5, Weng Tianxiang wrote:> > 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 >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
On 3/4/2016 1:20 PM, Weng Tianxiang wrote:> On Friday, March 4, 2016 at 5:34:42 AM UTC-8, Gabor wrote: >> Weng Tianxiang wrote: >>> 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 >> >> 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 > > 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 NI 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
On 3/4/2016 3:08 PM, KJ wrote:> On Friday, March 4, 2016 at 1:20:19 PM UTC-5, Weng Tianxiang wrote: >> >> 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 >> > > 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))Isn't it a floor function that is required? Floor and add one. No? -- Rick
In article <nbcq1j$i1q$1@dont-email.me>, rickman <gnuarm@gmail.com> wrote:>On 3/4/2016 1:20 PM, Weng Tianxiang wrote: >> On Friday, March 4, 2016 at 5:34:42 AM UTC-8, Gabor wrote: >>> Weng Tianxiang wrote: >>>> 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 >>> >>> 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 >> >> 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 > >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 beceiling(log2(8+1)) = 4; What's the trouble? Regards, Mark
On 3/4/2016 5:03 PM, Mark Curry wrote:> In article <nbcq1j$i1q$1@dont-email.me>, rickman <gnuarm@gmail.com> wrote: >> On 3/4/2016 1:20 PM, Weng Tianxiang wrote: >>> On Friday, March 4, 2016 at 5:34:42 AM UTC-8, Gabor wrote: >>>> Weng Tianxiang wrote: >>>>> 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 >>>> >>>> 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 >>> >>> 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 >> >> 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 > > ceiling(log2(8+1)) = 4; > > What's the trouble?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
On Friday, March 4, 2016 at 2:27:55 PM UTC-8, rickman wrote:> On 3/4/2016 5:03 PM, Mark Curry wrote: > > In article <nbcq1j$i1q$1@dont-email.me>, rickman <gnuarm@gmail.com> wrote: > >> On 3/4/2016 1:20 PM, Weng Tianxiang wrote: > >>> On Friday, March 4, 2016 at 5:34:42 AM UTC-8, Gabor wrote: > >>>> Weng Tianxiang wrote: > >>>>> 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 > >>>> > >>>> 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 > >>> > >>> 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 > >> > >> 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 > > > > ceiling(log2(8+1)) = 4; > > > > What's the trouble? > > 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. > > -- > > RickHi 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
On 3/4/2016 8:01 PM, Weng Tianxiang wrote:> On Friday, March 4, 2016 at 2:27:55 PM UTC-8, rickman wrote: >> On 3/4/2016 5:03 PM, Mark Curry wrote: >>> In article <nbcq1j$i1q$1@dont-email.me>, rickman <gnuarm@gmail.com> wrote: >>>> On 3/4/2016 1:20 PM, Weng Tianxiang wrote: >>>>> On Friday, March 4, 2016 at 5:34:42 AM UTC-8, Gabor wrote: >>>>>> Weng Tianxiang wrote: >>>>>>> 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 >>>>>> >>>>>> 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 >>>>> >>>>> 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 >>>> >>>> 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 >>> >>> ceiling(log2(8+1)) = 4; >>> >>> What's the trouble? >> >> 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 > > 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 debuggedI 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
On 3/5/2016 12:23 AM, rickman wrote:> On 3/4/2016 8:01 PM, Weng Tianxiang wrote: >> On Friday, March 4, 2016 at 2:27:55 PM UTC-8, rickman wrote: >>> On 3/4/2016 5:03 PM, Mark Curry wrote: >>>> In article <nbcq1j$i1q$1@dont-email.me>, rickman <gnuarm@gmail.com> >>>> wrote: >>>>> On 3/4/2016 1:20 PM, Weng Tianxiang wrote: >>>>>> On Friday, March 4, 2016 at 5:34:42 AM UTC-8, Gabor wrote: >>>>>>> Weng Tianxiang wrote: >>>>>>>> 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 >>>>>>> >>>>>>> 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 >>>>>> >>>>>> 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 >>>>> >>>>> 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 >>>> >>>> ceiling(log2(8+1)) = 4; >>>> >>>> What's the trouble? >>> >>> 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 >> >> 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 > > 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"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






