Hello, I am trying to write a code for a 32-bit adder. I am having trouble where the carry in signal is not be registered at all. Here is my code, can you guys give me some insight as what is wrong, I think I might not be understanding some fundamental concepts associated with VHDL. I am new to VHDL, so I welcome all sort of critiques. Thanks, D_A_S Code:

LIBRARY ieee; use ieee.std_logic_1164.all; ENTITY hmk2_32bitAdder IS PORT(a, b : IN std_logic_vector(31 downto 0); c : IN std_logic; result : OUT std_logic_vector(31 downto 0); cout : OUT std_logic); END ENTITY hmk2_32bitAdder; ARCHITECTURE adder_32bit OF hmk2_32bitAdder IS SIGNAL c_internal : std_logic; BEGIN P1 : PROCESS (a, b, c, c_internal) BEGIN c_internal <= c; for i in 0 to 31 loop result(i) <= a(i) xor b(i) xor c_internal; c_internal <= (a(i) and b(i)) or (a(i) and c_internal) or (b(i) and c_internal); end loop; cout <= c_internal; END PROCESS P1; END ARCHITECTURE adder_32bit; |

:
Edited by Moderator

DSP_Arch_Student wrote: > where the carry in signal is not be registered at all. An adder is a completly registerless, combinatorial design. So is yours: no clock, no registers. And now: what do you mean with "not registered"? One major flaw in your design ist, that you don't know about how signals behave in a process. They keep(!!) their value throughout(!!) the whole process. And at the end of the process they get the last assigned value. Think about that. Lets start here with c_internal='0' and c='1'. On the right side of all the assginments througout the process c_internal is '0':

P1 : PROCESS (a, b, c, c_internal) BEGIN c_internal <= c; -- c_internal gets a new value that will possibly be transferred at the end of the process for i in 0 to 31 loop result(i) <= a(i) xor b(i) xor c_internal; -- c_internal IS '0' HERE c_internal <= (a(i) and b(i)) or (a(i) and c_internal) or (b(i) and c_internal); -- c_internal IS '0' HERE, it may get a new value at the end of the process end loop; cout <= c_internal; -- c_internal IS '0' here, so cout is '0' also END PROCESS P1; -- And finally c_internal here gets the last assigned value from three lines above |

In this case here c_internal must be a variable. Variables virtually take over the assigned value "immediately". Lets start again with c_internal='0' and c='1':

ARCHITECTURE adder_32bit OF hmk2_32bitAdder IS BEGIN P1 : PROCESS (a, b, c, c_internal) variable c_internal : std_logic; BEGIN c_internal := c; -- always initialise the variable! for i in 0 to 31 loop -- surprise, surprise: now HERE c_internal IS '1' result(i) <= a(i) xor b(i) xor c_internal; c_internal := (a(i) and b(i)) or (a(i) and c_internal) or (b(i) and c_internal); end loop; cout <= c_internal; END PROCESS P1; END ARCHITECTURE adder_32bit; |

But be aware that variables in processes are not like variables in C programs (as VHDL is not a programming language, but a description language. just keep it in mind, you will find out further on)...

:
Edited by Moderator

Apart from this 'educational' implementation, one would normally use ieee.numeric_std, and the '+' operator. Simply because it is much more readable, and - this is the main reason - the compiler can map it to arithmetic hardware which is faster and smaller.

DSP_Arch_Student wrote: > the carry in signal is not be registered at all Registering all carries (+clock) would imply a pipeline design, but I guess that's not your aim. The problem is, that you only use ONE! signal for all carries, but incl. input Carry you have 32 carries. Declare a new vector cy and assign "cy[0] <= c" and in each stage "cy[i+1] <= (a(i) and b(i)) or (a(i) and cy[i]) or (b(i) and cy[i]);

@Sigi, @lkmiller, I know this is a little late on the reply, but thanks you guys for the help! I know what I did wrong now, a semester after the class is over! :D As long as I know what I did wrong, I'm happy. So, thanks for the help again!!!