Problems switching to ieee.numeric_std.all

A

aleksa

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 :)
 
B

Brian Drummond

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
 
S

scrts

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().
 
A

aleksa

scrts said:
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?
 
A

aleksa

Brian Drummond said:
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"
 
S

scrts

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";
 
A

aleksa

scrts said:
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."
 
E

Enrik Berkhan

scrts said:
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
 
A

aleksa

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?
 
A

aleksa

Alan Fitch said:
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.
 
A

aleksa

Alan Fitch said:
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!
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,754
Messages
2,569,528
Members
45,000
Latest member
MurrayKeync

Latest Threads

Top