Problems switching to ieee.numeric_std.all

A

aleksa

Guest
My VHD files now begin with

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

and I have some questions...



Example1:

I'm copying CURRENT to ADDR, but limiting to 999:

-- 2^10 = 1024
signal CURRENT, ADDR : unsigned(9 downto 0);

if CURRENT < 1000 then
ADDR <= CURRENT;
else
ADDR <= to_unsigned(999, ADDR'length);
end if;

At first I had "ADDR <= 999" but had to change it.
Is "to_unsigned" the correct way?

Next, if I have to use "to_unsigned", is it safe to use
"if CURRENT < 1000" or should I use
"if CURRENT < to_unsigned(1000, CURRENT'length)" ?



Example2:

I have a data bus defined like this:
signal DOUT : std_logic_vector(17 downto 0);

and DOUT is aliased into 3 unsigned indexes:

alias INDEX1 : unsigned(3 downto 0) is DOUT ( 3 downto 0);
alias INDEX2 : unsigned(8 downto 0) is DOUT (12 downto 4);
alias INDEX3 : unsigned(4 downto 0) is DOUT (17 downto 13);

I get the error that the types are incompatible.

Should I not use alias here, but create another signal?
signal INDEX1 : unsigned(3 downto 0);

INDEX1 <= DOUT(3 downto 0);
INDEX1 <= to_unsigned(DOUT(3 downto 0));
none of the above works.. how do I write it?



Example3:

signal DOUT : std_logic;
signal COUNTER : unsigned(15 downto 0);
signal INDEX : unsigned( 3 downto 0);

DOUT <= COUNTER(to_integer(INDEX));

Is that the correct way of extracting one bit?



I'll probably ask more questions after I grasp these :)
 
On Thu, 01 Mar 2012 17:27:40 +0100, aleksa wrote:

My VHD files now begin with

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
good...

Find the source for the numeric_std package.
In the Xilinx installation on this machine it's at
/opt/Xilinx/12.4/ISE_DS/ISE/vhdl/src/ieee/numeric_std.vhd

And look at the declarations in the package (you can ignore the package
body below it) - or find the same information in documentation if you
prefer.

Example1:
ADDR <= to_unsigned(999, ADDR'length);
Is "to_unsigned" the
correct way?
Essentially yes.

is it safe to use "if CURRENT < 1000" ?
You will find the package contains a declaration:
function "<" (L: UNSIGNED; R: INTEGER) return BOOLEAN;
Which tells you ... Yes.

It is a little odd that you can freely mix integers and [un]signed in
expressions, thanks to the overloaded operators, but you can't assign one
to the other, because assignment is not an operator.

(Some languages do pretend that assignment is an operator - but that
leads to problems far worse than any of VHDL's quirks!)

But back to
ADDR <= to_unsigned(999, ADDR'length);
If you find yourself doing this a lot, and the code is becoming
unbearably ugly, how about this:

subtype Address is unsigned(9 downto 0);
constant Last_Address : Address := to_unsigned(999, Address'length);
-- and other related declarations, safe in a package somewhere

signal CURRENT, ADDR : Address;

if CURRENT < Last_Address then
ADDR <= CURRENT;
else
ADDR <= Last_Address;
end if;

Can you see how this expresses the intent more clearly, as well as
behaving better if you decide to change the address range?
(e.g. if you grep for all the 999s and forget to change the 1000...)

Example2:

signal DOUT : std_logic_vector(17 downto 0);
alias INDEX1 : unsigned(3 downto 0) is DOUT ( 3 downto 0);
I get the error that the types are incompatible.
They are. So...
First, if you were to create another signal,

signal INDEX1 : unsigned(3 downto 0);
how do I write it?
INDEX1 <= unsigned(DOUT( 3 downto 0));

You need the type conversion here. (It is a conversion between related
types of the same size, and it costs nothing in HW of course! but tells
the compiler the change in types is intentional)

Now I have not used alias with different types in the alias expression.
You obviously need a type conversion, but I don't see why it shouldn't
work... So try

alias INDEX1 : unsigned(3 downto 0) is unsigned(DOUT( 3 downto 0));
and report back the result. If it works, use it.

signal DOUT : std_logic;
signal COUNTER : unsigned(15 downto 0); signal INDEX : unsigned( 3
downto 0);

DOUT <= COUNTER(to_integer(INDEX));

Is that the correct way of extracting one bit?
Yes. But again, if you find yourself always converting INDEX to integer,
don't be scared to make it an integer (actually, a natural range 0 to 15)
in the first place.

If you are writing a lot of conversions, that is a pointer that you
haven't thought the design through fully yet.

Once you learn to use the type system instead of fighting it, code will
flow with little ugliness - and a very few conversions, usually at
boundaries between "things". You should be able to point to each
remaining conversion, and argue that there is a good and necessary reason
for it. (For example, the external memory model you need, expects
std_logic_vectors on its ports, so you have to convert your unsigned
address to slv on the output port)

- Brian
 
Example1:

I'm copying CURRENT to ADDR, but limiting to 999:

-- 2^10 = 1024
signal CURRENT, ADDR : unsigned(9 downto 0);

if CURRENT < 1000 then
ADDR <= CURRENT;
else
ADDR <= to_unsigned(999, ADDR'length);
end if;
ADDR is already unsigned, what's the point to do to_unsigned here? Afaik
to_unsigned() is mainly used to type-convert integer or signed numbers to
unsigned. slv->unsigned use unsigned().
 
"scrts" <hidden@email.com> wrote in message news:jiq1gc$1kd$1@dont-email.me...
Example1:

I'm copying CURRENT to ADDR, but limiting to 999:

-- 2^10 = 1024
signal CURRENT, ADDR : unsigned(9 downto 0);

if CURRENT < 1000 then
ADDR <= CURRENT;
else
ADDR <= to_unsigned(999, ADDR'length);
end if;


ADDR is already unsigned, what's the point to do to_unsigned here?
You mean like this?
ADDR <= unsigned(999);
"The expression can not be converted to type unsigned."


to_unsigned() is mainly used to type-convert integer to unsigned
Isn't 999 an integer?
 
"Brian Drummond" <brian@shapes.demon.co.uk> wrote in message news:jip501$qo2$1@dont-email.me...

subtype Address is unsigned(9 downto 0);
constant Last_Address : Address := to_unsigned(999, Address'length);
-- and other related declarations, safe in a package somewhere

signal CURRENT, ADDR : Address;

if CURRENT < Last_Address then
ADDR <= CURRENT;
else
ADDR <= Last_Address;
end if;
Good to know, thank you.



Now I have not used alias with different types in the alias expression.
You obviously need a type conversion, but I don't see why it shouldn't
work... So try

alias INDEX1 : unsigned(3 downto 0) is unsigned(DOUT( 3 downto 0));
and report back the result. If it works, use it.
It doesn't work in ISE 13.3.
"type conversion unsigned can not be an alias name"
 
You mean like this?
ADDR <= unsigned(999);
"The expression can not be converted to type unsigned."
ADDR <= 999; but not sure. To be exact, You may use ADDR <= X"3E7";
 
"scrts" <hidden@email.com> wrote in message news:jiq641$nhb$1@dont-email.me...
You mean like this?
ADDR <= unsigned(999);
"The expression can not be converted to type unsigned."

ADDR <= 999; but not sure. To be exact, You may use ADDR <= X"3E7";
From my first post:
"At first I had "ADDR <= 999" but had to change it."
 
scrts <hidden@email.com> wrote:
ADDR <= unsigned(999);
"The expression can not be converted to type unsigned."

ADDR <= 999; but not sure. To be exact, You may use ADDR <= X"3E7";
- you can't assign an integer to unsigned without conversion.
- ADDR <= X"3E7" will work only if ADDR has 12 elements unless you are
using VHDL-2008's enhanced bit string literals.

Enrik
 
One more question:

ADDR : unsigned(9 downto 0);
OFFSET : unsigned(4 downto 0);

this is what I want:
ADDR <= OFFSET + 1000;

this is how I've written it:
ADDR <= OFFSET + to_unsigned(1000, ADDR'length);

correct?
 
On 02/03/12 13:53, aleksa wrote:
One more question:

ADDR : unsigned(9 downto 0);
OFFSET : unsigned(4 downto 0);

this is what I want:
ADDR <= OFFSET + 1000;

this is how I've written it:
ADDR <= OFFSET + to_unsigned(1000, ADDR'length);

correct?
That's not necessary. "+" is overloaded for unsigned + unsigned, natural
+ unsigned, unsigned + natural - all returning unsigned. So you can write

ADDR <= OFFSET + 1000;

regards
Alan

--
Alan Fitch
 
"Alan Fitch" <apf@invalid.invalid> wrote in message news:K8WdnZNhR-o-zc7SnZ2dnUVZ8jOdnZ2d@brightview.co.uk...
On 02/03/12 13:53, aleksa wrote:
One more question:

ADDR : unsigned(9 downto 0);
OFFSET : unsigned(4 downto 0);

this is what I want:
ADDR <= OFFSET + 1000;

this is how I've written it:
ADDR <= OFFSET + to_unsigned(1000, ADDR'length);

correct?



That's not necessary. "+" is overloaded for unsigned + unsigned, natural
+ unsigned, unsigned + natural - all returning unsigned. So you can write

ADDR <= OFFSET + 1000;
Width mismatch. <ADDR> has a width of 10 bits but assigned expression is 5-bit wide.

In the VHDL math tricks:
Y <= A + B; -- Maximum (A'Length, B'Length)
Y <= A + 10; -- A'Length

Since ISE complains if I just "+ 1000",
I wanted to convert "1000" to "B" in the first example.

It works, but I don't know if that is the correct approach.




BTW, I know that 2^5 is 32 and that 1000+32
may overflow 10 bits... but I don't care.
 
On 04/03/12 12:41, aleksa wrote:
"Alan Fitch" <apf@invalid.invalid> wrote in message news:K8WdnZNhR-o-zc7SnZ2dnUVZ8jOdnZ2d@brightview.co.uk...
On 02/03/12 13:53, aleksa wrote:
One more question:

ADDR : unsigned(9 downto 0);
OFFSET : unsigned(4 downto 0);

this is what I want:
ADDR <= OFFSET + 1000;

this is how I've written it:
ADDR <= OFFSET + to_unsigned(1000, ADDR'length);

correct?



That's not necessary. "+" is overloaded for unsigned + unsigned, natural
+ unsigned, unsigned + natural - all returning unsigned. So you can write

ADDR <= OFFSET + 1000;

Width mismatch. <ADDR> has a width of 10 bits but assigned expression is 5-bit wide.

In the VHDL math tricks:
Y <= A + B; -- Maximum (A'Length, B'Length)
Y <= A + 10; -- A'Length

Since ISE complains if I just "+ 1000",
I wanted to convert "1000" to "B" in the first example.

It works, but I don't know if that is the correct approach.




BTW, I know that 2^5 is 32 and that 1000+32
may overflow 10 bits... but I don't care.
Oops, sorry. Yes of course the widths need to match. I blame a week of
SystemC coding (and jet lag).

However the + sign itself will resize its arguments to match. So you
just have to resize one argument. Hence either

ADDR <= resize(OFFSET, ADDR'LENGTH) + 1000;

or (as you originally wrote)

ADDR <= OFFSET + to_unsigned(1000, ADDR'LENGTH);

As you say, ISE might be fussier than the language rules require.

kind regards
Alan


--
Alan Fitch
 
"Alan Fitch" <apf@invalid.invalid> wrote in message news:B5mdnQ309OGH9s7SnZ2dnUVZ8t2dnZ2d@brightview.co.uk...
On 04/03/12 12:41, aleksa wrote:
"Alan Fitch" <apf@invalid.invalid> wrote in message news:K8WdnZNhR-o-zc7SnZ2dnUVZ8jOdnZ2d@brightview.co.uk...
On 02/03/12 13:53, aleksa wrote:
One more question:

ADDR : unsigned(9 downto 0);
OFFSET : unsigned(4 downto 0);

this is what I want:
ADDR <= OFFSET + 1000;

this is how I've written it:
ADDR <= OFFSET + to_unsigned(1000, ADDR'length);

correct?



That's not necessary. "+" is overloaded for unsigned + unsigned, natural
+ unsigned, unsigned + natural - all returning unsigned. So you can write

ADDR <= OFFSET + 1000;

Width mismatch. <ADDR> has a width of 10 bits but assigned expression is 5-bit wide.

In the VHDL math tricks:
Y <= A + B; -- Maximum (A'Length, B'Length)
Y <= A + 10; -- A'Length

Since ISE complains if I just "+ 1000",
I wanted to convert "1000" to "B" in the first example.

It works, but I don't know if that is the correct approach.




BTW, I know that 2^5 is 32 and that 1000+32
may overflow 10 bits... but I don't care.



Oops, sorry. Yes of course the widths need to match. I blame a week of
SystemC coding (and jet lag).

However the + sign itself will resize its arguments to match. So you
just have to resize one argument. Hence either

ADDR <= resize(OFFSET, ADDR'LENGTH) + 1000;
Great, I didn't know about "resize", thanks!



or (as you originally wrote)

ADDR <= OFFSET + to_unsigned(1000, ADDR'LENGTH);

As you say, ISE might be fussier than the language rules require.

kind regards
Alan


--
Alan Fitch
 
Maybe someone will find this useful...

VHDL conversions
http://tinyurl.com/7ww9tvm
 
On 04/03/12 17:05, aleksa wrote:
Maybe someone will find this useful...

VHDL conversions
http://tinyurl.com/7ww9tvm


Or this...

http://www.doulos.com/knowhow/vhdl_designers_guide/numeric_std/

P.S. I work for Doulos so am biassed :-;

--
Alan Fitch
 

Welcome to EDABoard.com

Sponsor

Back
Top