EmbDev.net

Forum: FPGA, VHDL & Verilog 32-bit adder question


von DSP_Arch_Student (Guest)


Rate this post
useful
not useful
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:
1
LIBRARY ieee;
2
use ieee.std_logic_1164.all;
3
4
ENTITY hmk2_32bitAdder IS
5
  PORT(a, b : IN std_logic_vector(31 downto 0);
6
     c : IN std_logic;
7
     result : OUT std_logic_vector(31 downto 0);
8
     cout : OUT std_logic);
9
END ENTITY hmk2_32bitAdder;
10
11
ARCHITECTURE adder_32bit OF hmk2_32bitAdder IS
12
  SIGNAL c_internal : std_logic;
13
  
14
  BEGIN
15
    P1 : PROCESS (a, b, c, c_internal)
16
     BEGIN
17
       c_internal <= c;
18
      for i in 0 to 31 loop
19
        result(i) <= a(i) xor b(i) xor c_internal;
20
          c_internal <= (a(i) and b(i)) or (a(i) and c_internal) or (b(i) and c_internal);
21
      end loop;
22
      cout <= c_internal;
23
   END PROCESS P1;
24
END ARCHITECTURE adder_32bit;

:
von Lothar M. (Company: Titel) (lkmiller) (Moderator)


Rate this post
useful
not useful
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':
1
    P1 : PROCESS (a, b, c, c_internal)
2
     BEGIN
3
       c_internal <= c; -- c_internal gets a new value that will possibly be transferred at the end of the process              
4
      for i in 0 to 31 loop
5
        result(i) <= a(i) xor b(i) xor c_internal; -- c_internal IS '0' HERE
6
          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
7
      end loop;
8
      cout <= c_internal; -- c_internal IS '0' here, so cout is '0' also
9
   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':
1
ARCHITECTURE adder_32bit OF hmk2_32bitAdder IS
2
 
3
  BEGIN
4
    P1 : PROCESS (a, b, c, c_internal)
5
     variable c_internal : std_logic;
6
     BEGIN
7
       c_internal := c; -- always initialise the variable!
8
      for i in 0 to 31 loop -- surprise, surprise: now HERE c_internal IS '1'
9
        result(i) <= a(i) xor b(i) xor c_internal;
10
          c_internal := (a(i) and b(i)) or (a(i) and c_internal) or (b(i) and c_internal);
11
      end loop;
12
      cout <= c_internal;
13
   END PROCESS P1;
14
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
von Sym (Guest)


Rate this post
useful
not useful
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.

von Sigi (Guest)


Rate this post
useful
not useful
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]);

von Sigi (Guest)


Rate this post
useful
not useful
sorry mistake, incl cout you need 33 carries:
cout <= cy[32]

von DSP_Arch_Student (Guest)


Rate this post
useful
not useful
@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!!!

Please log in before posting. Registration is free and takes only a minute.
Existing account
Do you have a Google/GoogleMail account? No registration required!
Log in with Google account
No account? Register here.