Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > VHDL > Computing the width of an unsigned variable from maximum value?

Reply
Thread Tools

Computing the width of an unsigned variable from maximum value?

 
 
Torsten Landschoff
Guest
Posts: n/a
 
      02-20-2007
Hello World!

I am new to VHDL and after getting my first FPGA configured to blink
an LED, I have a number of questions that I did not find any answers
for. While VHDL seems to be very high level in some aspects, I still
haven't found some features that I would expect are easy to implement.

generic prescaler entity
---------------------
For controlling the on and off time of my led, I used a prescaler to
scale down the 50 MHz clock of the FPGA to microseconds. The output of
the prescaler is connected to a timer which finally toggles the led.

The prescaler has the following component declaration:

component prescaler is
generic (
divider : unsigned );
port (
clock_in : in std_logic;
clock_out : out std_logic );
end prescaler;

To get a fixed time base, I instantiate the component like this:

tick_provider : component prescaler
generic map (
divider => CONV_UNSIGNED(CLOCKHZ / 1_000_000, 6) )
port map (
clock_in => clock, clock_out => tick_us );

Now I'd like to get rid of the "6" for the length of the unsigned
parameter but I did not find any way to infer the length required for
the binary representation of some value. Is there any way to do
something like that:

constant tick_divider : positive := CLOCKHZ / 1_000_000;
...
divider => CONV_UNSIGNED(divider, divider'width)

??

Any insight appreciated.

Greetings, Torsten

 
Reply With Quote
 
 
 
 
KJ
Guest
Posts: n/a
 
      02-20-2007

"Torsten Landschoff" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed) ups.com...
> Hello World!
>
> I am new to VHDL and after getting my first FPGA configured to blink
> an LED, I have a number of questions that I did not find any answers
> for. While VHDL seems to be very high level in some aspects, I still
> haven't found some features that I would expect are easy to implement.
>
> generic prescaler entity
> ---------------------
> For controlling the on and off time of my led, I used a prescaler to
> scale down the 50 MHz clock of the FPGA to microseconds. The output of
> the prescaler is connected to a timer which finally toggles the led.
>
> The prescaler has the following component declaration:
>
> component prescaler is
> generic (
> divider : unsigned );
> port (
> clock_in : in std_logic;
> clock_out : out std_logic );
> end prescaler;
>
> To get a fixed time base, I instantiate the component like this:
>
> tick_provider : component prescaler
> generic map (
> divider => CONV_UNSIGNED(CLOCKHZ / 1_000_000, 6) )
> port map (
> clock_in => clock, clock_out => tick_us );
>
> Now I'd like to get rid of the "6" for the length of the unsigned
> parameter but I did not find any way to infer the length required for
> the binary representation of some value. Is there any way to do
> something like that:
>
> constant tick_divider : positive := CLOCKHZ / 1_000_000;
> ...
> divider => CONV_UNSIGNED(divider, divider'width)
>
> ??
>
> Any insight appreciated.
>
> Greetings, Torsten
>

I'd first suggest a different more flexible approach....

1. Change 'divider' from an unsigned to 'natural'.
2. Where you instantiate the component get rid of the call to function
'CONV_UNSIGNED' in the generic map.
3. Inside your component where you actually use divider, change all usages
of 'divider' to work with type 'natural' (it might even work with no
changes).

To answer your specific question though, divider'length gives you what you
called the 'width' of a vector (i.e. the number of bits).

Lastly, since you're using 'CNV_UNSIGNED' this implies that you're using the
std_logic_arith library. This is not a standard, use numeric_std instead
and save yourself some problems down the road.

Kevin Jennings


 
Reply With Quote
 
 
 
 
Torsten Landschoff
Guest
Posts: n/a
 
      02-20-2007
On Feb 20, 11:29 am, "KJ" <(E-Mail Removed)> wrote:
> I'd first suggest a different more flexible approach....
>
> 1. Change 'divider' from an unsigned to 'natural'.


I thought that would not synthesize. Guess I'll give it a try. Thanks
for the suggestion!

> 2. Where you instantiate the component get rid of the call to function
> 'CONV_UNSIGNED' in the generic map.


Sure, that's what I had originally anyway.

> 3. Inside your component where you actually use divider, change all usages
> of 'divider' to work with type 'natural' (it might even work with no
> changes).


Most likely, minus the counter declaration which currently is

variable counter : unsigned(divider'range);

> To answer your specific question though, divider'length gives you what you
> called the 'width' of a vector (i.e. the number of bits).


Yes, and divider'range gives me the range, but I can call that only
after having given the width to CONV_UNSIGNED.

> Lastly, since you're using 'CNV_UNSIGNED' this implies that you're using the
> std_logic_arith library. This is not a standard, use numeric_std instead
> and save yourself some problems down the road.


Grmbl, why do they call it std_logic_arith then?

Thanks for your quick response, Torsten

 
Reply With Quote
 
KJ
Guest
Posts: n/a
 
      02-20-2007

"Torsten Landschoff" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed) oups.com...
> On Feb 20, 11:29 am, "KJ" <(E-Mail Removed)> wrote:
>> I'd first suggest a different more flexible approach....
>>
>> 1. Change 'divider' from an unsigned to 'natural'.

>
> I thought that would not synthesize. Guess I'll give it a try. Thanks
> for the suggestion!

It will synthesize.

>> 3. Inside your component where you actually use divider, change all
>> usages
>> of 'divider' to work with type 'natural' (it might even work with no
>> changes).

>
> Most likely, minus the counter declaration which currently is
>
> variable counter : unsigned(divider'range);


'counter' could also be type natural...
variable counter : natural range 0 to divider;

>
> Grmbl, why do they call it std_logic_arith then?
>

Back in the late 80s there was no math packages, so Synopsys came up with
std_logic_arith and even put it in the ieee library even though it is not
(and never has been) an IEEE package. A couple years later, IEEE came out
with numeric_std which added math support and cleaned up some of the trash
that Synopsys allowed....15 years later it is still not uncommon to see
usage of std_logic_arith where numeric_std should be....it's not at all
uncommon but should still be pointed out when seen.

Kevin Jennings


 
Reply With Quote
 
KJ
Guest
Posts: n/a
 
      02-20-2007
I think I kind of missed your real question when reading your posts. If you
know the maximum value of something and simply need to know how many bits
you'll need to represent it, then you need to take the log (base 2) of that
number...and then generally tack on an extra bit

So if you have an integer 'abc' and want to represent it as an unsigned
signal 'xyz' then you would declare 'xyz' as...

signal xyz: unsigned(log2(abc) + 1 downto 0);

The '+1' is so that if you happen to take the log2() of something that does
not happen to be an integer power of 2 you'll still get enough bits of
precision.

You can also embed the log2 function in your entity. Let's say that signal
'xyz' was an output of your entity. You can do something like this

entity Foo is generic(abc: natural)
port(abc: out unsigned(log2(abc)+1 downto 0));
end Foo;

The magic log2 function is posted below as well as where I got it from.

Kevin Jennings
---------------------------------------------------------------------------------------- -- A synthesizable function that returns the integer part of the base 2logarithm for a -- positive number (posted by Tuukka Toivonen) to VHDL FAQ forum -- http://www.vhdl.org/comp.lang.vhdl/FAQ1.html ---------------------------------------------------------------------------------------- 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;

 
Reply With Quote
 
KJ
Guest
Posts: n/a
 
      02-20-2007
Arggg....typo

> port(abc: out unsigned(log2(abc)+1 downto 0));


should have been

port(xyz: out unsigned(log2(abc)+1 downto 0));

Kevin Jennings


 
Reply With Quote
 
Mike Treseler
Guest
Posts: n/a
 
      02-20-2007
Torsten Landschoff wrote:

> While VHDL seems to be very high level in some aspects, I still
> haven't found some features that I would expect are easy to implement.


VHDL can be used as a "high level"
language inside of a process.
Wiring procedures and entities together
is mostly non-procedural.


> generic prescaler entity
> ---------------------
> For controlling the on and off time of my led, I used a prescaler to
> scale down the 50 MHz clock of the FPGA to microseconds. The output of
> the prescaler is connected to a timer which finally toggles the led.
>
> The prescaler has the following component declaration:


I would use clock enables, rather than
dividing clocks and eliminate the component:

procedure update_regs is
-- a counts every clock, b counts when a rolls, c counts when b rolls
begin
a:a_v := a_v + 1; -- fast count
b:if a_v(a_v'left) = '1' then -- a carry?
a_v(a_v'left) := '0'; -- clear carry
b_v := b_v + 1;
c:if b_v(b_v'left) = '1' then -- b carry?
b_v(b_v'left) := '0'; -- clear carry
c_v := c_v + 1; -- slow count, unsigned rolls over, no carry
end if c;
end if b;
end procedure update_regs;

See "clock enable counters" below for details.
http://home.comcast.net/~mike_treseler/

> Now I'd like to get rid of the "6" for the length of the unsigned
> parameter but I did not find any way to infer the length required for
> the binary representation of some value.


> Any insight appreciated.


You can write a function, as KJ outlined,
but to calculate an integer value, I prefer to
use ieee.math_real.all;
and keep the calculations in the code
something like this:

constant cal_ratio_r : real := 400*1.0e-6; -- 400ppm
constant magic_number_r : real := 2 ** 25 * 2500.0 / 12500.0;
constant cal_range_r : real := magic_number_r * cal_ratio_r;
constant cal_range_nat_c : natural := natural(cal_range_r);

This works fine for Leo/Quartus.
If it doesn't for ISE, you can put it
in the testbench instead and take the
value from simulation.

-- Mike Treseler
 
Reply With Quote
 
Mike Treseler
Guest
Posts: n/a
 
      02-20-2007
typo:

> Wiring procedures and entities together

processes
---------

-- Mike Treseler
 
Reply With Quote
 
Torsten Landschoff
Guest
Posts: n/a
 
      02-22-2007
Hi again,

On 20 Feb., 12:22, "KJ" <(E-Mail Removed)> wrote:
> I think I kind of missed your real question when reading your posts. If you
> know the maximum value of something and simply need to know how many bits
> you'll need to represent it, then you need to take the log (base 2) of that
> number...and then generally tack on an extra bit


Right, exactly what I thought.

> The magic log2 function is posted below as well as where I got it from.


Great, thanks. That's what I was looking for.

Greetings, Torsten

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
(int) -> (unsigned) -> (int) or (unsigned) -> (int) -> (unsigned):I'll loose something? pozz C Programming 12 03-20-2011 11:32 PM
Optical Computing: special issue - Natural Computing, Springer optical supercomputing C Programming 0 01-16-2009 12:18 PM
Optical Computing: special issue - Natural Computing, Springer optical supercomputing C Programming 0 12-19-2008 12:22 PM
Razer Tarantula Gaming Keyboard Review at XYZ Computing at XYZ Computing Silverstrand Front Page News 0 11-01-2006 05:13 PM
Textbox width scaling to width of data not width of page? AndrewF ASP .Net 1 10-10-2005 04:38 PM



Advertisments