multiplying std logic vectors

Guest
Hi,
I have the following code.

signal a,b,c,d:std_logic_vector(17 downto 0);
signal out :std_logic_vector(36 downto 0);
out <= a*b + c*d;

My synthesis tool errors out complaining of mismatched array sizes.

A work around I used was this:
out <= ('0' & (a*b)) + ('0' & (c*d)) ;

Is this the general practice or is there an easier way around?

Thanks.
 
Signal "out" is declared as 37-bit. The product of two 18-bit unsigned
values will be 36-bit. If your result must have 37 bits, you could just
concatenate one bit to the original equation for "out". You don't really
need to distribute.

Regards,
Bob



abilashreddyg@gmail.com wrote:
Hi,
I have the following code.

signal a,b,c,d:std_logic_vector(17 downto 0);
signal out :std_logic_vector(36 downto 0);
out <= a*b + c*d;

My synthesis tool errors out complaining of mismatched array sizes.

A work around I used was this:
out <= ('0' & (a*b)) + ('0' & (c*d)) ;

Is this the general practice or is there an easier way around?

Thanks.
 
Abilash,

Which package are you using (to multiply the two std_logic_vectors) ?
Let me take a guess : The Synopsis "std_logic_unsigned" (or signed) package ?
They are both based on the Synopsys "std_logic_arith" package, which has a function called
"EXT" which does zero-extension, and SEXT which does sign extension.
So here you go :

out <= ext(a*b + c*d, out'length)

Rob

<abilashreddyg@gmail.com> wrote in message news:1166183951.985931.106020@73g2000cwn.googlegroups.com...
Hi,
I have the following code.

signal a,b,c,d:std_logic_vector(17 downto 0);
signal out :std_logic_vector(36 downto 0);
out <= a*b + c*d;

My synthesis tool errors out complaining of mismatched array sizes.

A work around I used was this:
out <= ('0' & (a*b)) + ('0' & (c*d)) ;

Is this the general practice or is there an easier way around?

Thanks.
 
abilashreddyg@gmail.com a écrit :
Hi,
I have the following code.

signal a,b,c,d:std_logic_vector(17 downto 0);
signal out :std_logic_vector(36 downto 0);
out <= a*b + c*d;

My synthesis tool errors out complaining of mismatched array sizes.

A work around I used was this:
out <= ('0' & (a*b)) + ('0' & (c*d)) ;

Is this the general practice or is there an easier way around?
First, drop the std_logic_arith packages and use numeric_std. Replace
your std_logic_vector's with signed's or unsigned's (depending on what
you need).
Second, resize your vectors before adding them (almost as you did) :

out <= resize(a*b, out'length) + resize(a*b, out'length);

The '+' operator will always return a result the size of its longest
operand. If you want the carry bit, you need to extend the operand.

Nicolas
 
Ditto on numeric_std functions and types, especially since in this
case, the result is too large for integer subtypes (my preference).

And, as Robert mentioned, you can do the arithmetic and then resize
once:

out <= resize(a * b + c * d, out'length);


Andy


Nicolas Matringe wrote:
abilashreddyg@gmail.com a écrit :
Hi,
I have the following code.

signal a,b,c,d:std_logic_vector(17 downto 0);
signal out :std_logic_vector(36 downto 0);
out <= a*b + c*d;

My synthesis tool errors out complaining of mismatched array sizes.

A work around I used was this:
out <= ('0' & (a*b)) + ('0' & (c*d)) ;

Is this the general practice or is there an easier way around?

First, drop the std_logic_arith packages and use numeric_std. Replace
your std_logic_vector's with signed's or unsigned's (depending on what
you need).
Second, resize your vectors before adding them (almost as you did) :

out <= resize(a*b, out'length) + resize(a*b, out'length);

The '+' operator will always return a result the size of its longest
operand. If you want the carry bit, you need to extend the operand.

Nicolas
 
Andy a écrit :
Ditto on numeric_std functions and types, especially since in this
case, the result is too large for integer subtypes (my preference).

And, as Robert mentioned, you can do the arithmetic and then resize
once:

out <= resize(a * b + c * d, out'length);
I don't have any tool here at home so I can't check but are you sure
that this will actually output the adder carry on the MSB ? Seems to me
that this will only sign-extend a truncated (no carry) result.

Nicolas
 
oops, you are correct. The arithmeticly correct result requires
separate resizing of the products.

I'm too used to using integers, where it just figures it out
(arithmeticly correct). Too bad we're limited to 32 bit signed integer
values. And they simulate MUCH faster to boot.

Andy


Nicolas Matringe wrote:
Andy a écrit :
Ditto on numeric_std functions and types, especially since in this
case, the result is too large for integer subtypes (my preference).

And, as Robert mentioned, you can do the arithmetic and then resize
once:

out <= resize(a * b + c * d, out'length);

I don't have any tool here at home so I can't check but are you sure
that this will actually output the adder carry on the MSB ? Seems to me
that this will only sign-extend a truncated (no carry) result.

Nicolas
 
Nicolas,

You are right. For some reason, the standard packages (including numeric_std)
define addition as a N+N=N bit operation. The carry bit get lost by default.

To preserve the carry bit, you need to extend at least one argument first :

out <= resize(a * b, out'length) + c * d ;

For consistency, it might make more sense to concat both arguments.

out <= resize(a * b, out'length) + resize(c * d,out'length) ;

So then we are back at Abilash' original proposal, although 'resize' is more versatile
than pre-pending a '0' because 'resize' will always adjust to the size of the target,
while prepending will just adjust one bit.

The 'good' thing is that VHDL forces you to think about the carry bit and if you want to preserve it or not.

Rob

"Nicolas Matringe" <nicolas.matringe@fre.fre> wrote in message news:4586fc27$0$9756$426a34cc@news.free.fr...
Andy a écrit :
Ditto on numeric_std functions and types, especially since in this
case, the result is too large for integer subtypes (my preference).

And, as Robert mentioned, you can do the arithmetic and then resize
once:

out <= resize(a * b + c * d, out'length);

I don't have any tool here at home so I can't check but are you sure that this will actually output the adder carry on the MSB ?
Seems to me that this will only sign-extend a truncated (no carry) result.

Nicolas
 
It is interesting what different operators on different types force you
to handle yourself. With numeric_std.signed/unsigned, addition happily
rolls over silenlty, truncating the result width to that of the largest
operand, while multiply forces the maximum number of bits required to
handle the result. Fixed point is even more explicit, requiring all
kinds of incantations to do anything other than maximum width/precision
data paths.

Integers, on the other hand, "just do what's right" from an arithmetic
POV, and stop you if you make a mistake with an assertion. It forces
you to handle numeric overflows manually.

Pick your poison...

Andy

Rob Dekker wrote:
Nicolas,

You are right. For some reason, the standard packages (including numeric_std)
define addition as a N+N=N bit operation. The carry bit get lost by default.

To preserve the carry bit, you need to extend at least one argument first :

out <= resize(a * b, out'length) + c * d ;

For consistency, it might make more sense to concat both arguments.

out <= resize(a * b, out'length) + resize(c * d,out'length) ;

So then we are back at Abilash' original proposal, although 'resize' is more versatile
than pre-pending a '0' because 'resize' will always adjust to the size of the target,
while prepending will just adjust one bit.

The 'good' thing is that VHDL forces you to think about the carry bit and if you want to preserve it or not.

Rob

"Nicolas Matringe" <nicolas.matringe@fre.fre> wrote in message news:4586fc27$0$9756$426a34cc@news.free.fr...
Andy a écrit :
Ditto on numeric_std functions and types, especially since in this
case, the result is too large for integer subtypes (my preference).

And, as Robert mentioned, you can do the arithmetic and then resize
once:

out <= resize(a * b + c * d, out'length);

I don't have any tool here at home so I can't check but are you sure that this will actually output the adder carry on the MSB ?
Seems to me that this will only sign-extend a truncated (no carry) result.

Nicolas
 
Rob Dekker a écrit :
Nicolas,

You are right. For some reason, the standard packages (including numeric_std)
define addition as a N+N=N bit operation. The carry bit get lost by default.

To preserve the carry bit, you need to extend at least one argument first :

out <= resize(a * b, out'length) + c * d ;

For consistency, it might make more sense to concat both arguments.

out <= resize(a * b, out'length) + resize(c * d,out'length) ;
That actually was my previous proposal :eek:)

Nicolas
 

Welcome to EDABoard.com

Sponsor

Back
Top