Numeric variable type

B

Bibi69

Hi,
I've a question concerning variable types :
I want to add two 4 bits signed values and a one-bit value.
What seems to be the most efficient method to me is to use a 4-bit adder
with a carry-in bit.
If I write
i1 : in std_logic_vector(3 downto 0);
i2 : in std_logic_vector(3 downto 0);
ci : in std_logic;
o : out std_logic_vector(3 downto 0);

o <= i1+i2+ci;

the synthesis (with xilinx ise 8.1) is ok but people have said me it's
bad to add std_logic_vector and std_logic.

When I use signed and bit types, the synthesizer tells '+' isn't a
correct operator...

Does someone have a piece of advice on what I should do ?

Moreover I want to have three such adders making a tree structure.
If I write :
i1 : in std_logic_vector(3 downto 0);
i2 : in std_logic_vector(3 downto 0);
i3 : in std_logic_vector(3 downto 0);
i4 : in std_logic_vector(3 downto 0);
c1 : in std_logic;
c2 : in std_logic;
c3 : in std_logic;
o : out std_logic_vector(3 downto 0);

I tried o <= (i1+i2+c1)+(i3+i4+c2)+c3;
That doesn't give an efficient result, no adder tree.
To have a good tree structure I have to write :
signal t1 : std_logic_vector(3 downto 0);
signal t2 : std_logic_vector(3 downto 0);

t1 <= i1+i2+c1;
t2 <= i3+i4+c2;
o <= t1+t2+c3;

Does someone know why it's different.

Thx
 
J

Jonathan Bromley

Hi,
I've a question concerning variable types :
I want to add two 4 bits signed values and a one-bit value.
What seems to be the most efficient method to me is to use a 4-bit adder
with a carry-in bit.

Synthesis tools should do this automatically for you.
If I write
i1 : in std_logic_vector(3 downto 0);
i2 : in std_logic_vector(3 downto 0);
ci : in std_logic;
o : out std_logic_vector(3 downto 0);

o <= i1+i2+ci;

the synthesis (with xilinx ise 8.1) is ok but people have said me it's
bad to add std_logic_vector and std_logic.

I agree. Arithmetic on std_logic_vector is a really, really bad idea.
When I use signed and bit types, the synthesizer tells '+' isn't a
correct operator...
Does someone have a piece of advice on what I should do ?

Use numeric_std or std_logic_arith, make all your operands SIGNED,
and then be VERY careful; because a single-bit SIGNED vector has
only two values, 0 and -1 !!!!!!!

signal i1, i2: signed(3 downto 0);
signal t1: signed(3 downto 0); -- sum
signal c1: std_logic; -- carry in
....

t1 <= i1 + i2 + signed' ('0' & c1);

NOTE I've put a leading 0 on the carry, to ensure that its numeric
value is either 0 or +1.
Moreover I want to have three such adders making a tree structure.
If I write :
i1 : in std_logic_vector(3 downto 0);
i2 : in std_logic_vector(3 downto 0);
i3 : in std_logic_vector(3 downto 0);
i4 : in std_logic_vector(3 downto 0);
c1 : in std_logic;
c2 : in std_logic;
c3 : in std_logic;
o : out std_logic_vector(3 downto 0);

I tried o <= (i1+i2+c1)+(i3+i4+c2)+c3;
That doesn't give an efficient result, no adder tree.
To have a good tree structure I have to write :
signal t1 : std_logic_vector(3 downto 0);
signal t2 : std_logic_vector(3 downto 0);

t1 <= i1+i2+c1;
t2 <= i3+i4+c2;
o <= t1+t2+c3;

Does someone know why it's different.

I don't; it's a feature of your tool's optimisations.
I do know, though, that it's wrong; what happens to the
carry OUT from the most significant bits?

The result of i1+i2+c1 needs to be 5 bits, and the
result of the tree sum needs to be 6 bits. For this
to work, you need to resize one of the operands to
that same bit width. Here's how I'd do it:

signal t1,t2: signed(4 downto 0);
signal sum: signed(5 downto 0);
....
t1 <= i1 + i2 + (signed' ("0000") & c1);
t2 <= i3 + i4 + (signed' ("0000") & c2);
sum <= t1 + t2 + (signed' ("00000") & c3);

--
Jonathan Bromley, Consultant

DOULOS - Developing Design Know-how
VHDL * Verilog * SystemC * e * Perl * Tcl/Tk * Project Services

Doulos Ltd., 22 Market Place, Ringwood, BH24 1AW, UK
(e-mail address removed)
http://www.MYCOMPANY.com

The contents of this message may contain personal views which
are not the views of Doulos Ltd., unless specifically stated.
 
A

Andy

Hi,
I've a question concerning variable types :
I want to add two 4 bits signed values and a one-bit value.
What seems to be the most efficient method to me is to use a 4-bit adder
with a carry-in bit.
If I write
i1 : in std_logic_vector(3 downto 0);
i2 : in std_logic_vector(3 downto 0);
ci : in std_logic;
o : out std_logic_vector(3 downto 0);

o <= i1+i2+ci;

the synthesis (with xilinx ise 8.1) is ok but people have said me it's
bad to add std_logic_vector and std_logic.

When I use signed and bit types, the synthesizer tells '+' isn't a
correct operator...

Does someone have a piece of advice on what I should do ?

Moreover I want to have three such adders making a tree structure.
If I write :
i1 : in std_logic_vector(3 downto 0);
i2 : in std_logic_vector(3 downto 0);
i3 : in std_logic_vector(3 downto 0);
i4 : in std_logic_vector(3 downto 0);
c1 : in std_logic;
c2 : in std_logic;
c3 : in std_logic;
o : out std_logic_vector(3 downto 0);

I tried o <= (i1+i2+c1)+(i3+i4+c2)+c3;
That doesn't give an efficient result, no adder tree.
To have a good tree structure I have to write :
signal t1 : std_logic_vector(3 downto 0);
signal t2 : std_logic_vector(3 downto 0);

t1 <= i1+i2+c1;
t2 <= i3+i4+c2;
o <= t1+t2+c3;

Does someone know why it's different.

Thx

You can use integer subtypes for arithmetic as well.

subtype sum_type is integer range -8 to 7;
variable i1, i2, sum : sum_type;
variable ci : integer range 0 to 1;

Have you thought about what you want to happen if the sum rolls over?
Vector based arithmetic will silently roll over, which is usually fine
for counters, but not always what you wanted for adders, especially
signed ones. With vector based arithmetic, detecting signed rollovers
is a little more complicated.

With integer subtypes, all operations are assumed 32 bit signed, no
matter what the storage variable range is. Then the synthesis tool
figures out how many bits it really needs to keep. So you can do
something like:

if i1 + i2 + ci > sum_type'high then -- don't try this with vectors!
sum := sum_type'high; -- assuming 'high is 2**n - 1
elsif i1+ i2 + ci < sum_type'low then
sum := sum_type'low; -- assuming 'low is -(2**n)
else
sum := i1 + i2 + ci;
end if;

Since the results of the addition are 32 bit signed, they can be
checked against the limits of the sum variable type, before trying to
store the results there. The synthesis tool automatically recognizes
the three identical adders, and uses just one, with the extra bit (not
stored) for the rollover detection.

Or, if it is never supposed to roll over, don't do any checking, and
if it does by chance, the simulator will tell you about it.

And, integer arithmetic simulates much more quickly than vector based
arithmetic.

You can also use the new fixed point package, but the default size for
sum result is one bit larger than the largest addend, and you'd need
to resize & saturate if that's not what you want. And it simulates as
slow as any other vectors.

Andy
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top