best way to code an adder

R

Roger Bourne

Guest
hello all,

I am a newbie to vhdl. Well sorta.
I have always implemented adder code using by resorting to "variables"
and to the conv_std_logic_vector function. However, I am now at an
impasse since I have to implement a 102-bit adder and the aformentioned
function has a 32-bit limitation. (I know I can cascade adders, but I
want to be elegant :) ). I know, there are other ways to implement
adders like port-mapping a 1-bit adder cell 102 times or making a for
loop with the 1-bit adder logic code. However, since it a 102-bit
adder, I want to be sure that I am opting for the method that
synthesizes the most compactly. Which is the best way to code an
adder?, especially when bus size impedes of available fcts.

Please advise.
-Roger

P.S The adder is part of an accumulator module
P.P.S The accumulator fucntions at 50MHz, so the adder has to be
moderately fast.
 
use numeric_std types (unsigned) and operators.

signal a,b,sum : unsigned(101 downto 0);

....

sum <= a + b;


No limitations on vector length.

Andy
 
Andy wrote:
use numeric_std types (unsigned) and operators.

signal a,b,sum : unsigned(101 downto 0);

...

sum <= a + b;


No limitations on vector length.

Andy
Be aware that the produced circuity will be slow by its very nature. You
may need to do partial summation.
 
Roberto Gallo wrote:

Be aware that the produced circuity will be slow by its very nature. You
may need to do partial summation.
For Stratix2:

Info: Longest tpd from source pin "b[4]" to
destination pin "sum[100]" is 15.149 ns


-- Mike Treseler

__________________________________
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity add102 is
generic (len : natural := 102);
port(a : in unsigned(len-1 downto 0);
b : in unsigned(len-1 downto 0);
sum : out unsigned(len-1 downto 0));
end entity add102;

architecture synth of add102 is
begin
sum <= a + b;
end architecture;
 
a 102 bit acum. can run up to > 100 Mhz into a Spartan 3 -5
( default tools settings )

-------------------------------------------------------------
-- | Requested | Actual | Logic | Absolute |Number of
-- | | | Levels | Slack |errors
-------------------------------------------------------------
-- | 10.000ns | 8.408ns | | 1.592ns | 0
-- | | | | |
-------------------------------------------------------------

-- ISE 8.1.03i
-- Xilinx Spartan 3 -5

Walter;
 
If I use conv_integer and then add the integer values....and convert
them back to std_logic...then will that be a good implementation....

when using unsigned vectors can we add signals of unequal bus width....

for eg:

c <= a + b where a is 1 bit wide and b is 2 bit wide....
 
vishallko31@gmail.com wrote:

If I use conv_integer
conv_integer is a function from a non-standard library. Use
IEEE.Numeric_std.ALL and use

my_int1<=to_integer( signed(my_std_ulogic_vector) );
my_int2<=to_integer( unsigned(my_std_ulogic_vector) );

Note the difference between signed and unsigned. That's the reason, why
conv_integer should not be used!


and then add the integer values....and convert
them back to std_logic...then will that be a good implementation....
That's only a good implementation as long as your bitwidth fits into 32
bits. Integer is fixed to 32 bits. Addition of signed / unsiged vectors
does not have any limits.


when using unsigned vectors can we add signals of unequal bus width....
VHDL is a strongly typed language. It enables you to find typing errors
such as different bitwidths easily, but requires vector resizing
(function resize) if the bitwidth is unequal. Take advantage of this
feature of VHDL - it saves you a lot of gray hair searching for bugs!
Have a look at Verilog if you like that sloppy behavior.


Ralf
 
Just because I have seen that so often now:

What is wrong with
-------
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity add102 is
generic (len : natural := 102);
port(a : in std_logic_vector(len-1 downto 0);
b : in std_logic_vector(len-1 downto 0);
sum : out std_logic_vector(len-1 downto 0));
end entity add102;

architecture synth of add102 is
begin
sum <= a + b;
end architecture;
-------

Why use "unsigned" when this simply means I have to put lot's of
type conversions into my code ?

so long
lundril
 
lundril@gmx.de wrote:

Just because I have seen that so often now:

What is wrong with
...
use ieee.std_logic_unsigned.all;
....
Why use "unsigned" when this simply means I have to put lot's of
type conversions into my code ?
std_logic_unsigned is _not_ a standard library. It may be that your
simulator has a different version that your synthesis tool. Furthermore
you restrict yourself to _only_ unsigned arithmetics. I prefer to have
the choice each time I need arithmetics.

Ralf
 
On 6 May 2006 08:21:08 -0700, lundril@gmx.de wrote:

Just because I have seen that so often now:

What is wrong with
-------
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity add102 is
generic (len : natural := 102);
port(a : in std_logic_vector(len-1 downto 0);
b : in std_logic_vector(len-1 downto 0);
sum : out std_logic_vector(len-1 downto 0));
end entity add102;

architecture synth of add102 is
begin
sum <= a + b;
end architecture;
(a) The non-standard library.
(b) The ambiguities, incompatibilities and potential bugs that creep in
when some of your "std_logic_vector"s represent signed quantities; some
unsigned, and some neither.

Why use "unsigned" when this simply means I have to put lot's of
type conversions into my code ?
I didn't see lots of type conversions in Mike's example.

If you are adding lots to your code, that is usually a sign that you are
using the wrong level of abstraction; such as using std_logic_vector for
ports (signals, variables etc) that should be unsigned.

One place where conversions ARE necessary is top level ports (device
pins) where synthesis tools will create gate level equivalents for your
RTL with std_logic_vector regardless of the original type. This is
arguably a tools issue, but it's easier to "go with the flow" than
campaign for the tools to preserve port types. A wrapper for the gate
level netlist with the necessary port conversions might be an
alternative.

Another place is when mixing data types, such as signed and unsigned; or
an unavoidable std_logic_vector (e.g. from an external IP over which you
have no control) - here the conversions usefully clarify your intent.

- Brian
 
Yes, VHDL is strongly typed with integers too.

If I add two unequal range subtypes of integers, vhdl knows what to do,
because I told it they were integers, not some arbitrary datatype like
slv.

Along those lines, numeric_std.unsigned should behave like an integer,
not like an slv. If the results of an addition or subtraction
(arithmetic operators) are out of range of the result, it should cause
an error, not just roll over silently. Now who's getting sloppy? With
integers, I tell VHDL what to do if the results are out of range
numerically, or else I get an error (range violation).

Strong typing means different things to different users...

Andy
 
Andy wrote:

Yes, VHDL is strongly typed with integers too.

If I add two unequal range subtypes of integers, vhdl knows what to do,
because I told it they were integers, not some arbitrary datatype like
slv.

Along those lines, numeric_std.unsigned should behave like an integer,
not like an slv. If the results of an addition or subtraction
(arithmetic operators) are out of range of the result, it should cause
an error, not just roll over silently. Now who's getting sloppy? With
integers, I tell VHDL what to do if the results are out of range
numerically, or else I get an error (range violation).
You are talking about Numeric_std. With this library it is possible to
chose integers or signed / unsigned at free will. If you don't like roll
over, you may take integers, if you need more than 32 bits, want to
simulate something like 'X' and want to get warned if unequal operator
length occur, you may take signed / unsigned. All data types have
advantages and disadvantages.

I personally use roll over carefully and think about my bit width before
I implement any arithmetics. I want to get warned if I accidentally add
two unequal length operators. Therefore I do no choose integer.


But this is not the main problem I have discussed in my posting: I have
discussed the problem of using conv_integer from a non-standard library
and the problems, that arise, if you do conversions using that function.

Ralf
 
Actually, the length matching artifact of arithmetic with vectors stems
from the inability of vhdl functions/operators to grab the return
vector size from the instance of the function. It is impossible for a
function to know how long the vector is that is accepting the result of
the function. Therefore, they had to choose something, and they chose
to always make the return value the same as the operand width.

The real problem with overflows in vector based arithmetic is that they
are hard to detect without adding phantom bits that have to be stripped
back out. Integer operations are always 32 bit signed; the limit
checking happens only when the results are stored in a signal or
variable with a smaller range. So you can check to see if an addition
is greater than a limit before you actually store the result, and do
something about it (like limit it at the ceiling). The range
specifications of the signals/variables defines the datapath widths.

BTW, I agree wholeheartedly with using only types and conversions from
numerc_std or numeric_bit!

Andy Jones
 

Welcome to EDABoard.com

Sponsor

Back
Top