Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

Sizing a VHDL input port

Status
Not open for further replies.
Really appreciate your patience. I'm doing that with every new message.
Let me ask a series of Yes/No questions - this will help me understand.

Do you agree that your implementation of what you call ceil_log2:
And this combination:
Code:
ceil ( log2 ( real ( x ) ) ) -- uses the math.real log2 function

Will give different results?

We do not agree. The testbench that verifies that the 'synthesizable' version of log2 (i.e. the one from comp.lang.vhdl FAQ) along with my ceil_log2 function matches exactly with the ieee.math_real version of ceil(log2(x)) at least in the range of x from 1 to 4096. No mismatches.

As an aside, for those values of x that are integer powers of 2, ieee.math_real.log2(x) mostly matches the synthesizable log2(x) as noted below. This is somewhat of a tangent from the path that this thread has taken, but it goes back to what started the whole thread because the particular case of x=8 happens to be one of the cases where the ieee.math_real.log2 function does not return exactly the same value as the synthesizable version of log2 and x=8 was the value you happened to be using.

But again, this is about the performance of the log2 function, not the ceil_log2 function which is what is needed to define bit widths.

x Match?
1 Match
2 Match
4 Match
8 No Match
16 Match
32 Match
64 No Match
128 No Match
256 Match
512 Match
1024 Match
2048 Match
4096 No Match

Kevin Jennings
 
We're getting to it...

Post #19
I think you need to sit down and re-read this thread (at least up to post #4). The log2 function is not the same thing as the ceil_log2 function and neither of those are functions to compute the MSB. However, the MSB is simply the output of the ceil_log2 function minus one. The ceil_log2 function calls the log2 function. The log2 function (that I use) is the recursive version of the one from comp.lang.vhdl FAQ that I posted the link.

Code:
ceil ( log2 ( real ( x ) ) ) -- uses the math.real log2 function

Example x=8 ("1000"). MSB position should be 3.
Starting to calculate...
ceil ( log2 ( real ( 8 ) ) ) = 3
the MSB is simply the output of the ceil_log2 function minus one
3-1 = 2

If your ceil_log2 function and ceil ( log2 ( real ( x ) ) ) are equivalent they both don't give the MSB value by simply applying them on x and decreasing 1 from the result.
 

Your example is not complete. You say 'x=8', but you do not say if '8' is the number of combinations or the upper end of the range. Please refer back to post #15 where I walked through how to handle this for either situation.

Kevin Jennings
 
  • Like
Reactions: shaiko

    shaiko

    Points: 2
    Helpful Answer Positive Rating
OK,
Lets sum it up:

If you have an array in which N is the highest number and you want to create a vector that can express N, you use:
(ceil(log2(N+1))-1 downto 0)

If you have an array of N elements and you want to create a vector that can address 0 to N-1, you use:
(ceil(log2(N))-1 downto 0)

Both of the above fail when N = 1. Therefore you use a custom function to overcome this specific case.

Is everything correct?
 

OK,
Lets sum it up:

If you have an array in which N is the highest number and you want to create a vector that can express N, you use:
(ceil(log2(N+1))-1 downto 0)

If you have an array of N elements and you want to create a vector that can address 0 to N-1, you use:
(ceil(log2(N))-1 downto 0)
Basically correct. I use my 'ceil_log2' function (which as I mentioned in an earlier post has already been validated to ieee.math_real.ceil(log2()).

Both of the above fail when N = 1. Therefore you use a custom function to overcome this specific case.

Is everything correct?
I do not use any custom functions to overcome the case for N=1.

N=1 is not an issue for "(ceil(log2(N+1))-1 downto 0)" since this will become a "0 downto 0" vector which is legitimate. Maybe you meant to say N=0 for this case?

N=1 is not necessarily an issue for "(ceil(log2(N))-1 downto 0)" either. What you will get is a "-1 downto 0" vector which is a Null vector in VHDL, which is legitimate as well. Even though it is a null vector, the reason that everything can be made to work out is because if N=1, then you have only one thing to be addressed which implies that there are no 'other' things that can possibly be addressed which implies that you don't need any addressing.

If you're creating designs that you intend to be reusable, and you have bus widths that are defined as a function of some input generic, then you will want to test out the case where you cause that vector to be a null vector, and you may (or may not) have to fix something in your code, but I haven't run across a situation where that fix wasn't something that is also appropriate regardless of the vector size. In other words, the fix did not involve any special case code anywhere. As an example, if you have two vectors that are the same size, you can assign them to each other (i.e. vec1 <= vec2) and it doesn't matter if the dimensions of the vectors are "-1 downto 0" or not. You can also place a vector that is "-1 downto 0" on a port map, etc. It will all hang together just fine.

Kevin Jennings
 
  • Like
Reactions: shaiko

    shaiko

    Points: 2
    Helpful Answer Positive Rating
If you can do the things described in this post with standard functions (i.e: ceil + log2) why do choose to use your custom ceil_log2 function (post #20) instead?
 

If you can do the things described in this post with standard functions (i.e: ceil + log2) why do choose to use your custom ceil_log2 function (post #20) instead?
A couple of reasons:
- In the not too distant past, synthesis tools did not support anything in ieee.math_real even though I was only using it to compute constants.
- There are times when I need a synthesizable log2 function that operates on signals, not just constants. In that situation, I don't know if synthesis tools support use of ieee.math_real.log2.
- For synthesis, I typically need integer interfaces, not reals. Since the ieee.math_real functions work with reals, there are type conversions that are needed on the argument and the end result. My log2 and ceil_log2 functions have that interface so there are no type conversions required so the code is less cluttered.

Since I have the functions and they are validated and I have full access to the source code now I'm even less motivated to move away from them since there is no measurable benefit to doing so and since I don't have full access to or control over the ieee.math_real source code. As you probably realize now, the log2 function, while computing a number that was 'close' to the correct answer, the combination of "floor(log2(8))" gave you an unexpected result. At that point, those two functions were black boxes that can't be examined any closer.

Kevin Jennings
 
  • Like
Reactions: shaiko

    shaiko

    Points: 2
    Helpful Answer Positive Rating
Thanks for the explanation.

One more question:

In post #4 you mention that your function uses recursion...
But the oldest reference that I know of is from the venerable FAQ for comp.lang.vhdl at **broken link removed** which lists both a recursive version (which is what I use), as well as the iterative version from Ray Andraka.

This is your function:
Code:
    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;
I can't trace any recursion here...Please explain
 

The 'recursive version' is referring to the log2 function which I use, but did not write. The ceil_log2 function that you showed is a different function that I wrote and use. Ceil_log2 calls log2, it is not a replacement for log2.
 
  • Like
Reactions: shaiko

    shaiko

    Points: 2
    Helpful Answer Positive Rating
The 'recursive version' is referring to the log2 function which I use, but did not write.

This one?

Code:
function log2 (x : positive) return natural is 
begin
  if x <= 1 then
    return 0;
  else
    return log2 (x / 2) + 1;
  end if;
end function log2;
 

If so, when did you have to use this one instead of the standard log2 from math_real ?
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top