![]() |
Problems switching to ieee.numeric_std.all
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 :) |
Re: Problems switching to ieee.numeric_std.all
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 |
Re: Problems switching to ieee.numeric_std.all
> 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(). |
Re: Problems switching to ieee.numeric_std.all
"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? |
Re: Problems switching to ieee.numeric_std.all
"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" |
Re: Problems switching to ieee.numeric_std.all
> 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"; |
Re: Problems switching to ieee.numeric_std.all
"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." |
Re: Problems switching to ieee.numeric_std.all
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 |
Re: Problems switching to ieee.numeric_std.all
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? |
Re: Problems switching to ieee.numeric_std.all
"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. |
| All times are GMT. The time now is 10:25 AM. |
Powered by vBulletin®. Copyright ©2000 - 2013, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.