Intel® Quartus® Prime Software
Intel® Quartus® Prime Design Software, Design Entry, Synthesis, Simulation, Verification, Timing Analysis, System Design (Platform Designer, formerly Qsys)
17245 Discussions

Simple Signed Adder is complex to understand

Altera_Forum
Honored Contributor II
3,475 Views

Hi guys, still asking beginner questions, sorry. I have this code and cant figure out what the '0' in ('0' & cin) is doing. This is what I think: 

Lets say we we need to do add two to negative four: 

(2)0010 + (-4)1101 where the answer is (-2)11110 (last bit '1' indicates the negative sign) so, 

 

(a_sig(n-1) & a_sig) 00010 

+ (b_sig(n-1) & b_sig) 11101 

+ ('0' & cin) 00 

ans 11111 (which is incorrect) 

 

What am I getting wrong?http://www.alteraforum.com/forum//images/icons/icon8.png  

 

Also is this signed adder actually efficient cause lots of examples suggest loads of other ways to do it and I can't figure out which one to stick to or it depends on the application?  

 

library ieee; 

use ieee.std_logic_1164.all; 

use ieee.numeric_std.all; 

 

entity examples is  

generic(n : integer := 4); -- number of input bits 

port(a, b: in std_logic_vector(n-1 downto 0); 

cin: in std_LOGIC := '0'; 

sum: out std_LOGIC_VECTOR(n downto 0)); 

end examples; 

 

architecture add_sub of examples is 

signal a_sig, b_sig: signed(n-1 downto 0); 

signal sum_sig: signed(n downto 0); 

begin 

--convert to signed 

a_sig <= signed(a); 

b_sig <= signed(b); 

 

--add  

sum_sig <= (a_sig(n-1) & a_sig) + (b_sig(n-1) & b_sig) + ('0' & cin); 

 

sum <= std_logic_vector(sum_sig); 

 

end add_sub;
0 Kudos
18 Replies
Altera_Forum
Honored Contributor II
2,759 Views

1101 is not -4 

1100 is = -2^3 + 2^2 + 0 +0 = -8 + 4 = -4 (follow the weights of index with negative sign bit
0 Kudos
Altera_Forum
Honored Contributor II
2,759 Views

Oppps, thanks kaz. it's late and I'm a bit tired. So actually it is working correctly. So why is the '0' in ('0' & cin) needed for? And can any one give me some explanation on the various adders out there, which one suits the best application and translation efficiency? Thanks. And a Happy New Year too.

0 Kudos
Altera_Forum
Honored Contributor II
2,759 Views

that '0' makes the cin signed positive to match its brothers and sisters. 

 

The code is ok and you can alternatively use function resize which will sign extend if applied to signed value as done above manually. 

I normally don't need cin as I will add in one go 

 

and happy new year to you and all
0 Kudos
Altera_Forum
Honored Contributor II
2,759 Views

Thanks kaz. How do you mean "don't need cin as I add in one go"? Also, again with that '0', does it concatenate to sum_sig(4) or sum_sig(1). I believe its the sum_sig(1), but I'm asking just to make sure.

0 Kudos
Altera_Forum
Honored Contributor II
2,759 Views

that cin is the carry input in your case and is single bit and so I think it should be extended as 4 bits not 2 bits (so it could be wrong if it is other than 0 because it will have higher weight). 

I am assuming cin has weight of zero index to the adder. I don't use it at all so not that sure. If I have A & B I just add A+B and get result (no carry bit, no nothing?). The carry in bit is used for cascading small adders usually by students instructed by their professor who learns with them and goes by the book.
0 Kudos
Altera_Forum
Honored Contributor II
2,759 Views

Oh I see. Well, in fact I got this example from a book. I'll try it without the carry and see what happens. Thanks for that.

0 Kudos
Altera_Forum
Honored Contributor II
2,759 Views

Books try teaching from basics and are many times distant from practice. 

 

if A & B are 4 bits each then their sum needs 5 bits (it is this extra magnitude MSB that can be passed to another adder to complete the job) but all you need is: 

 

sum <= std_logic_vector(resize(signed(A),5) + resize(signed(B ) ,5));
0 Kudos
Altera_Forum
Honored Contributor II
2,759 Views

Well I'm learning VHDL by my self and the only resources I have are books, forums and internet. I have to admit its not easy this way but I practice a lot to better understand how every thing works. Also thanks for this suggestion. I'll see how it performs. One more question if I may, when declaring something 'signed', the MSB always indicates the sign bit when code is compiled? So lets say that A is signed with a value 1100, will the compiler know that it means -4? I mean, how are std_logic_vector, unsigned, signed and integer synthesized?

0 Kudos
Altera_Forum
Honored Contributor II
2,759 Views

The std_logic_vector itself just means a bus of bits and so has no sign meaning.  

The libraries like numeric_std then understands your intention. If you declared std_logic_vector then you can cast it (between brackets) as signed as I did and then it is treated as signed. If you don't it will issue error when adding as it does not understand your intention of bus (but this depends on libraries...) 

Basically signed and unsigned are similar at addition/subtraction and it is only their interpretation by user is different. But for multiplication/division they differ in result. 

And this why two's complement has been invented as addition/subtraction is same as unsigned.
0 Kudos
Altera_Forum
Honored Contributor II
2,759 Views

I see, so libraries play a vital roll in the way every thing works together. I'll try different codes and see what happens and how it works. Thanks for the tips and explanations. Much appreciated. Feel free to input more thoughts...

0 Kudos
Altera_Forum
Honored Contributor II
2,759 Views

I should say that actually all operations (add/subtract/mult/div) are basically similar for signed and unsigned (using two's complement) but some care is needed with carry bits and result width. 

 

But all these details are not relevant to me as the functions in libraries look after it. I will add one bit to result of +/- and for multiplying 5 bits x 5 bits the result should be 10 bits.  

The compiler tells you but not always.
0 Kudos
Altera_Forum
Honored Contributor II
2,759 Views

Great tip. Thanks. Is there a way I can improve and get better with VHDL other than books? There's so many interesting projects done with FPGAs but not much information when things start to get complex.

0 Kudos
Altera_Forum
Honored Contributor II
2,759 Views

 

--- Quote Start ---  

Great tip. Thanks. Is there a way I can improve and get better with VHDL other than books? There's so many interesting projects done with FPGAs but not much information when things start to get complex. 

--- Quote End ---  

 

 

practice then practice. and use higher level design than lower level, don't read too much into books examples. 

By the way I should correct my thoughts on that cin: 

it does not need 4 bits but two is enough since the addition always gives it weight as lsb, and that zero is just to pretend it is signed positive.
0 Kudos
Altera_Forum
Honored Contributor II
2,759 Views

well I'm on the right track then I guess cause I try something new every day, so thanks for that and for the correction too. :)

0 Kudos
Altera_Forum
Honored Contributor II
2,759 Views

Hii guys,good work.I'm quite new to FPGA and vhdl,So I created a forum on (help..FPGA based led lighting using de2 board where d LEDs come on at night and goes off during d day using ldr as sensor.pls I need u guys to put me try.im kind of confused how to convert the analog signal from d ldr into digital form for the fpga

0 Kudos
Altera_Forum
Honored Contributor II
2,759 Views

 

--- Quote Start ---  

Oppps, thanks kaz. it's late and I'm a bit tired. So actually it is working correctly. So why is the '0' in ('0' & cin) needed for? 

--- Quote End ---  

 

 

It's a sign extension. (Actually, it is zero-extension if the word is unsigned.) You need it because:  

 

a) adding two n-bit vectors gives you an n+1-bit sum (a carry is generated), 

b) VHDL requires that assignments have the same length vectors on both sides of the <= (or := ), and 

c) VHDL neither auto-extends operands nor truncates results to make the vector lengths match (unlike Verilog). 

 

As noted in this thread, it is better to use the resize() function (from numeric_std) on signed or unsigned types than to explicitly use the '0' & foo.
0 Kudos
Altera_Forum
Honored Contributor II
2,759 Views

 

--- Quote Start ---  

It's a sign extension. (Actually, it is zero-extension if the word is unsigned.) You need it because:  

 

b) VHDL requires that assignments have the same length vectors on both sides of the <= (or := ), and 

c) VHDL neither auto-extends operands nor truncates results to make the vector lengths match (unlike Verilog). 

 

 

--- Quote End ---  

 

 

are you sure? try multiply 8 bits value by 8 bits value onto 16 bits result 

 

 

--- Quote Start ---  

 

 

As noted in this thread, it is better to use the resize() function (from numeric_std) on signed or unsigned types than to explicitly use the '0' & foo. 

--- Quote End ---  

 

why? what is the resize doing anyway?
0 Kudos
Altera_Forum
Honored Contributor II
2,759 Views

 

--- Quote Start ---  

are you sure? try multiply 8 bits value by 8 bits value onto 16 bits result 

--- Quote End ---  

 

 

The multiply and divide functions in numeric_std return a result that is N+M bits long. But addition/subtraction returns a result that is as long as the largest operand. 

 

 

--- Quote Start ---  

why? what is the resize doing anyway? 

--- Quote End ---  

 

 

The resize function does 0 extension for unsigned and sign extension for signed. It extends (or shrinks) the value the specified length.
0 Kudos
Reply