Velocity Reviews > VHDL > multiplying std logic vectors

# multiplying std logic vectors

abilashreddyg@gmail.com
Guest
Posts: n/a

 12-15-2006
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.

out <= ('0' & (a*b)) + ('0' & (c*d)) ;

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

Thanks.

Robert G. Kaimer Jr.
Guest
Posts: n/a

 12-15-2006
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

http://www.velocityreviews.com/forums/(E-Mail Removed) 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.
>
> out <= ('0' & (a*b)) + ('0' & (c*d)) ;
>
> Is this the general practice or is there an easier way around?
>
> Thanks.
>

Rob Dekker
Guest
Posts: n/a

 12-15-2006
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

<(E-Mail Removed)> wrote in message news:(E-Mail Removed) ups.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.
>
> out <= ('0' & (a*b)) + ('0' & (c*d)) ;
>
> Is this the general practice or is there an easier way around?
>
> Thanks.
>

Nicolas Matringe
Guest
Posts: n/a

 12-15-2006
(E-Mail Removed) 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.
>
> 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
Guest
Posts: n/a

 12-18-2006
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:
> (E-Mail Removed) 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.
> >
> > 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

Nicolas Matringe
Guest
Posts: n/a

 12-18-2006
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

Andy
Guest
Posts: n/a

 12-18-2006
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

Rob Dekker
Guest
Posts: n/a

 12-18-2006
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" <(E-Mail Removed)> wrote in message news:4586fc27\$0\$9756\$(E-Mail Removed)...
> 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 Matringe
Guest
Posts: n/a

 12-19-2006
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 )

Nicolas