VHDL rules for arithmetic operations

Status
Not open for further replies.

shaiko

Advanced Member level 5
Joined
Aug 20, 2011
Messages
2,644
Helped
303
Reputation
608
Reaction score
297
Trophy points
1,363
Visit site
Activity points
18,302
Hello,

1.When multiplying 2 unsigned vectors in VHDL, must they be at the same length?
2.Is it legal to multiply an unsigned vector with an integer? Or both operands must be of the same type?
 

I'm pretty sure for 1. the inputs to a multiply can be different lengths and the result will be the two lengths added together.
For 2. the numeric_std package for 97 shows unsigned-natural and signed-integer, which makes sense as integer can have negative values.
 
Reactions: shaiko

    shaiko

    Points: 2
    Helpful Answer Positive Rating
Thanks,
I verified #1 (modelim compilation + Quartus synthesis). Works as you said.
Regarding #2 - what about multiplying an unsigned vector with type natural (or positive)?
 

Reactions: shaiko and FvM

    FvM

    Points: 2
    Helpful Answer Positive Rating

    shaiko

    Points: 2
    Helpful Answer Positive Rating
Tricky are you sure you aren't mistaken, I just looked at the package on the IEEE site and the 1076.2-1996 package doesn't define * for unsigned/signed.

Code VHDL - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
-- Id: A.15
  function "*" (L, R: UNSIGNED) return UNSIGNED;
  -- Result subtype: UNSIGNED((L'LENGTH+R'LENGTH-1) downto 0)
  -- Result: Performs the multiplication operation on two UNSIGNED vectors
  --         that may possibly be of different lengths.
 
  -- Id: A.16
  function "*" (L, R: SIGNED) return SIGNED;
  -- Result subtype: SIGNED((L'LENGTH+R'LENGTH-1) downto 0)
  -- Result: Multiplies two SIGNED vectors that may possibly be of
  --         different lengths.
 
  -- Id: A.17
  function "*" (L: UNSIGNED; R: NATURAL) return UNSIGNED;
  -- Result subtype: UNSIGNED((L'LENGTH+L'LENGTH-1) downto 0)
  -- Result: Multiplies an UNSIGNED vector, L, with a nonnegative
  --         INTEGER, R. R is converted to an UNSIGNED vector of
  --         SIZE L'LENGTH before multiplication.
 
  -- Id: A.18
  function "*" (L: NATURAL; R: UNSIGNED) return UNSIGNED;
  -- Result subtype: UNSIGNED((R'LENGTH+R'LENGTH-1) downto 0)
  -- Result: Multiplies an UNSIGNED vector, R, with a nonnegative
  --         INTEGER, L. L is converted to an UNSIGNED vector of
  --         SIZE R'LENGTH before multiplication.
 
  -- Id: A.19
  function "*" (L: SIGNED; R: INTEGER) return SIGNED;
  -- Result subtype: SIGNED((L'LENGTH+L'LENGTH-1) downto 0)
  -- Result: Multiplies a SIGNED vector, L, with an INTEGER, R. R is
  --         converted to a SIGNED vector of SIZE L'LENGTH before
  --         multiplication.
 
  -- Id: A.20
  function "*" (L: INTEGER; R: SIGNED) return SIGNED;
  -- Result subtype: SIGNED((R'LENGTH+R'LENGTH-1) downto 0)
  -- Result: Multiplies a SIGNED vector, R, with an INTEGER, L. L is
  --         converted to a SIGNED vector of SIZE R'LENGTH before
  --         multiplication.


https://standards.ieee.org/downloads/1076/1076.2-1996/numeric_std.vhdl

It has been change to the following in the 1076-2008, which also doesn't define * for signed/unsigned. :???:

Code VHDL - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
-- Id: A.15
  function "*" (L, R : UNRESOLVED_UNSIGNED) return UNRESOLVED_UNSIGNED;
  -- Result subtype: UNRESOLVED_UNSIGNED((L'LENGTH+R'LENGTH-1) downto 0)
  -- Result: Performs the multiplication operation on two UNRESOLVED_UNSIGNED vectors
  --         that may possibly be of different lengths.
 
  -- Id: A.16
  function "*" (L, R : UNRESOLVED_SIGNED) return UNRESOLVED_SIGNED;
  -- Result subtype: UNRESOLVED_SIGNED((L'LENGTH+R'LENGTH-1) downto 0)
  -- Result: Multiplies two UNRESOLVED_SIGNED vectors that may possibly be of
  --         different lengths.
 
  -- Id: A.17
  function "*" (L : UNRESOLVED_UNSIGNED; R : NATURAL) return UNRESOLVED_UNSIGNED;
  -- Result subtype: UNRESOLVED_UNSIGNED((L'LENGTH+L'LENGTH-1) downto 0)
  -- Result: Multiplies an UNRESOLVED_UNSIGNED vector, L, with a nonnegative
  --         INTEGER, R. R is converted to an UNRESOLVED_UNSIGNED vector of
  --         SIZE L'LENGTH before multiplication.
 
  -- Id: A.18
  function "*" (L : NATURAL; R : UNRESOLVED_UNSIGNED) return UNRESOLVED_UNSIGNED;
  -- Result subtype: UNRESOLVED_UNSIGNED((R'LENGTH+R'LENGTH-1) downto 0)
  -- Result: Multiplies an UNRESOLVED_UNSIGNED vector, R, with a nonnegative
  --         INTEGER, L. L is converted to an UNRESOLVED_UNSIGNED vector of
  --         SIZE R'LENGTH before multiplication.
 
  -- Id: A.19
  function "*" (L : UNRESOLVED_SIGNED; R : INTEGER) return UNRESOLVED_SIGNED;
  -- Result subtype: UNRESOLVED_SIGNED((L'LENGTH+L'LENGTH-1) downto 0)
  -- Result: Multiplies an UNRESOLVED_SIGNED vector, L, with an INTEGER, R. R is
  --         converted to an UNRESOLVED_SIGNED vector of SIZE L'LENGTH before
  --         multiplication.
 
  -- Id: A.20
  function "*" (L : INTEGER; R : UNRESOLVED_SIGNED) return UNRESOLVED_SIGNED;
  -- Result subtype: UNRESOLVED_SIGNED((R'LENGTH+R'LENGTH-1) downto 0)
  -- Result: Multiplies an UNRESOLVED_SIGNED vector, R, with an INTEGER, L. L is
  --         converted to an UNRESOLVED_SIGNED vector of SIZE R'LENGTH before
  --         multiplication.

 
Reactions: shaiko

    shaiko

    Points: 2
    Helpful Answer Positive Rating
In contrast to legacy std_logic_arith, ieee.numeric_std has no automatic type conversion from unsigned to signed, thus unsigned*signed or unsigned*negative_integer isn't supported.

But I don't hear that Tricky is suggesting anything different.
 
Reactions: shaiko

    shaiko

    Points: 2
    Helpful Answer Positive Rating
Ok - I stand a little corrcted. You can never multipliy an unsigned and signed as it wouldnt make sense.
Neither would multiplying unsigned with an integer (as it can have negative values).

Ok multiplicates:

us * us
s *s
s * integer (and other way around - this covers positives and naturals)
us * natural (and other way around - this also covers positives).

The 2008 definition uses unresolved_signed by default as this was how std_logic was changed - std_logic_vector became a subtype of std_ulogic_vector, rather than an array of std_logic. So they did the same change in numeric_std.

As unsigned/signed are just subtypes of unresolved_(un)signed, you can use the functions you quoted.
 
Reactions: shaiko

    shaiko

    Points: 2
    Helpful Answer Positive Rating
The length of us * us will be the sum of both - simple enough.
But what about:
us * natural (in case the natural is unconstrained)
Will the tool simply assume that the natural number is 32 bits long ?
Or will it treat it as a constrained unsigned exactly the length of its binary equivalent?
 

Code:
  function "*" (L : UNRESOLVED_UNSIGNED; R : NATURAL) return UNRESOLVED_UNSIGNED;
  -- Result subtype: UNRESOLVED_UNSIGNED((L'LENGTH+L'LENGTH-1) downto 0)
 
Reactions: shaiko

    shaiko

    Points: 2
    Helpful Answer Positive Rating
ads-ee,

post #6 is VERY helpful.
I couldn't find this package on IEEE site.
I found it on another site, but I'd like to have the original reference.

Can you please post the link ?

- - - Updated - - -

I stumbled upon this definition of the "+" function:
Code:
  -- Id: A.3
  function "+" (L, R: UNSIGNED) return UNSIGNED;
  -- Result subtype: UNSIGNED(MAX(L'LENGTH, R'LENGTH)-1 downto 0).
  -- Result: Adds two UNSIGNED vectors that may be of different lengths.
Can't find the scene behind it.
I'd expect the function to take into consideration the possibility of an overflaw and the result to be defined as one bit longer than the longest of operands - yet I see the length of the result is simply defined as the length of the longest operand without any extra bits.

Am I missing something?
 


Nope. No overflow is done
If you want overflow you need to extend the inputs by a bit - which is common:

op <= ('0' & a) + ('0' & b);
 
Reactions: shaiko

    shaiko

    Points: 2
    Helpful Answer Positive Rating
If you want overflow taken into consideration, then you should consider using the fixed point package instead.
Kevin Jennings
 
Reactions: shaiko

    shaiko

    Points: 2
    Helpful Answer Positive Rating
Code:
op <= ('0' & a) + ('0' & b);
It's sufficient to extend one of both operands to avoid result truncation. And you can use numeric_std resize(), which also performs the necessary sign extension of signed numbers.
Code:
op <= resize(a, op'length) + b;
 
Reactions: shaiko

    shaiko

    Points: 2
    Helpful Answer Positive Rating
Status
Not open for further replies.

Similar threads

Cookies are required to use this site. You must accept them to continue using the site. Learn more…