# VHDL rules for arithmetic operations

Status
Not open for further replies.

#### shaiko 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?

##### Super Moderator
Staff member 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.

• shaiko

### shaiko

Points: 2

#### shaiko 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)?

#### FvM

##### Super Moderator
Staff member To answer the question yourself, why don't you review the source of numeric_std.vhd?

#### TrickyDicky • shaiko and FvM

Points: 2

### shaiko

Points: 2

##### Super Moderator
Staff member numeric_std defines * for unsigned/signed * integer and integer * unisnged/signed.
natural and positive are subtypes of integer, so will work just fine.
You really need a good reference book - this is basic stuff.

https://www.doulos.com/content/products/golden_reference_guides.php
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.

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.

• shaiko

### shaiko

Points: 2

#### FvM

##### Super Moderator
Staff member 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.

• shaiko

### shaiko

Points: 2

#### TrickyDicky 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.

• shaiko

### shaiko

Points: 2

#### shaiko The length of us * us will be the sum of both - simple enough.
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?

#### axcdd

##### Full Member level 3 Code:
  function "*" (L : UNRESOLVED_UNSIGNED; R : NATURAL) return UNRESOLVED_UNSIGNED;
-- Result subtype: UNRESOLVED_UNSIGNED((L'LENGTH+L'LENGTH-1) downto 0)

• shaiko

### shaiko

Points: 2

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

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

##### Super Moderator
Staff member • shaiko

### shaiko

Points: 2

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

- - - 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);

• shaiko

### shaiko

Points: 2

#### K-J 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?
If you want overflow taken into consideration, then you should consider using the fixed point package instead.
Kevin Jennings

• shaiko

### shaiko

Points: 2

#### FvM

##### Super Moderator
Staff member 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;

• shaiko

Points: 2