C

#### Christoph Linden

##### Guest

I am getting into VHDL right now and doing the first implementation of some architecutres. For me to learn I follow nand2tetris, that uses its own HDL and translating that for my learning into VHDL.

I am at the point of createing a 4bit adder with carry look ahead.

I have defined two entities CLA4 and Add4LAC.

CLA4 is supposed to calculate the look ahead carry

Add4LAC is a 4bit adder with carry that uses CLA4 to calculate the carries of every bit.

I also have written a testbench to check it with ModelSim. The result is weird and I do not understand it at all.

I have defined in my simulator the following signals:

a,b (3 downto 0) --operands

cin --carry in

sum (3 downto 0) -- output of the sum

carry -- carry output.

for testing purposes i also added the expected results as

csum and ccarry (compare sum and compare carry).

If I now run it, with the following input:

a <= \"0000\";

b <= \"0000\";

cin <= \'0\';

csum <= \"0000\";

ccarry <= \'0\';

The result is not as in csum and ccarry, but instead:

# a b cin sum coutcsum ccout

# 0000 0000 0 UUUU 0 0000 0

# ** Note: Result Mismatch!

# Time: 10 ns Iteration: 0 Instance: /add4lactb

# 1111 1111 0 UU00 0 1110 1

# ** Note: Result Mismatch!

# Time: 20 ns Iteration: 0 Instance: /add4lactb

Can someone please help me to understand what is wrong? I am getting undefined output ... ???

I must have made a generic mistake and have no idea what it is. Even stepping through the code with ModelSim does not give any hint.

Here is the code:

-- Full 16 bit adder for Hack Computer with look ahead carry

-- From the book nand2tetris, translated to vhdl

-- by Christoph Linden

-- Look ahead carry calculation for 4 bits.

-- length to be defined as constant c_WordWidth

library ieee;

use ieee.std_logic_1164.all;

entity CLA4 is

port(

-- inputs

i_g : in std_logic_vector (3 downto 0);

i_p : in std_logic_vector (3 downto 0);

i_cin : in std_logic;

-- outputs

o_cout : out std_logic_vector (3 downto 0) );

end entity;

architecture cal4 of CLA4 is

signal cp0 : std_logic;

signal cp0p1 : std_logic;

signal cp0p1p2 : std_logic;

signal cp0p1p2p3 : std_logic;

signal g0p1 : std_logic;

signal g0p1p2 : std_logic;

signal g0p1p2p3 : std_logic;

signal g1p2 : std_logic;

signal g1p2p3 : std_logic;

signal g2p3 : std_logic;

begin

process (i_p, i_g, i_cin) is

begin

-- caculate bit 1 preproduct and carry out 0

-- And(a=p[0],b=cin,out=p0c);

-- Or(a=p0c,b=g[0],out=cout[0]);

cp0 <= i_p(0) and i_cin;

o_cout(0) <= cp0 or i_g(0);

-- calculate bit 2 preproduct and carry out 1

-- And3Way(a=cin, b=p[0], c=p[1], out=cp0p1);

-- And(a=g[0],b=p[1],out=g0p1);

-- Or3Way(a=cp0p1,b=g0p1,c=g[1],out=cout[1]);

cp0p1 <= i_cin and i_p(0) and i_p(1);

g0p1 <= i_g(0) and i_p(1);

o_cout(1) <= cp0p1 or g0p1 or i_g(1);

--calculate bit 3 preproducts and carry out 2

-- And4Way(a=cin, b=p[0], c=p[1], d=p[2], out=cp0p1p2);

-- And3Way(a=g[0],b=p[1],c=p[2],out=g0p1p2);

-- And(a=g[1],b=p[2],out=g1p2);

-- Or4Way(a=cp0p1p2,b=g0p1p2,c=g1p2,d=g[2],out=cout[2]);

cp0p1p2 <= i_cin and i_p(0) and i_p(1) and i_p(2);

g0p1p2 <= i_g(0) and i_p(1) and i_p(2);

g1p2 <= i_g(1) and i_p(2);

o_cout(2) <= cp0p1p2 or g0p1p2 or g1p2 or i_g(2);

--calculate bit 4 preproducts and carry out 4

-- And5Way(a=cin, b=p[0], c=p[1], d=p[2], e=p[3], out=cp0p1p2p3);

-- And4Way(a=g[0], b=p[1], c=p[2], d=p[3], out=g0p1p2p3);

-- And3Way(a=g[1],b=p[2],c=p[3],out=g1p2p3);

-- And(a=g[2],b=p[3],out=g2p3);

-- Or5Way(a=cp0p1p2p3,b=g0p1p2p3,c=g1p2p3,d=g2p3, e=g[3],out=cout[3]);

cp0p1p2p3 <= i_cin and i_p(0) and i_p(1) and i_p(2) and i_p(3);

g0p1p2p3 <= i_g(0) and i_p(1) and i_p(2) and i_p(3);

g1p2p3 <= i_g(1) and i_p(2) and i_p(3);

g2p3 <= i_g(2) and i_p(3);

o_cout(3) <= cp0p1p2p3 and g0p1p2p3 and g1p2p3 and g2p3;

end process;

end architecture;

-- a 4 bit carry look ahead adder.

library ieee;

use ieee.std_logic_1164.all;

entity Add4LAC is

port(

-- inputs

i_a : in std_logic_vector (3 downto 0);

i_b : in std_logic_vector (3 downto 0);

i_cin : in std_logic;

-- outputs

o_sum : out std_logic_vector (3 downto 0);

o_carry : out std_logic );

end entity;

architecture add4lac of Add4LAC is

component CLA4

port(

-- inputs

i_g : in std_logic_vector (3 downto 0);

i_p : in std_logic_vector (3 downto 0);

i_cin : in std_logic := \'L\';

-- outputs

o_cout : out std_logic_vector (3 downto 0) );

end component;

signal g0,g1,g2,g3 : std_logic;

signal p0,p1,p2,p3 : std_logic;

signal c0,c1,c2 : std_logic;

begin

u1: CLA4

port map(

i_g(0) => g0,

i_g(1) => g1,

i_g(2) => g2,

i_g(3) => g3,

i_p(0) => p0,

i_p(1) => p1,

i_p(2) => p2,

i_p(3) => p3,

o_cout(0) => c0,

o_cout(1) => c1,

o_cout(2) => c2,

o_cout(3) => o_carry );

process (i_a,i_b,i_cin) is

begin

-- Bit 0

g0 <= i_a(0) and i_b(0);

p0 <= i_a(0) xor i_b(0);

o_sum(0) <= p0 xor i_cin;

-- Bit 1

g1 <= i_a(1) and i_b(1);

p1 <= i_a(1) xor i_b(1);

o_sum(1) <= p1 xor c0;

-- Bit 2

g2 <= i_a(2) and i_b(2);

p2 <= i_a(2) xor i_b(2);

o_sum(2) <= p2 xor c1;

-- Bit 3

g3 <= i_a(3) and i_b(3);

p3 <= i_a(3) xor i_b(3);

o_sum(3) <= p3 xor c2;

end process;

end architecture;

Here is the tb code:

library ieee;

use ieee.std_logic_1164.all;

use ieee.numeric_std.all;

use std.textio.all;

use ieee.std_logic_textio.all;

entity Add4LACTB is

end entity;

architecture sim of Add4LACTB is

signal a,b,sum,csum : std_logic_vector (3 downto 0);

signal cin,carry,ccarry : std_logic;

component Add4LAC

port(

-- inputs

i_a : in std_logic_vector (3 downto 0);

i_b : in std_logic_vector (3 downto 0);

i_cin : in std_logic;

-- outputs

o_sum : out std_logic_vector (3 downto 0);

o_carry : out std_logic );

end component;

begin

Adder1: Add4LAC

port map(

i_a => a,

i_b => b,

i_cin => cin,

o_sum => sum,

o_carry => carry );

process is

variable v_myline : line;

begin

write(v_myline, string\'(\" a\"), left, 5);

write(v_myline, string\'(\" b\"), left, 5);

write(v_myline, string\'(\" cin\"), left, 5);

write(v_myline, string\'(\" sum\"), left, 5);

write(v_myline, string\'(\" cout\"), left, 5);

write(v_myline, string\'(\"csum\"), left, 5);

write(v_myline, string\'(\"ccout\"), left, 5);

writeline(output, v_myline);

-- testscenarios

--set a %B0000000000000000,

--set b %B0000000000000000,

--set a %B0000000000000000,

--set b %B1111111111111111,

--set a %B1111111111111111,

--set b %B1111111111111111,

--set a %B1010101010101010,

--set b %B0101010101010101,

--set a %B0011110011000011,

--set b %B0000111111110000,

--set a %B0001001000110100,

--set b %B1001100001110110,

a <= \"0000\";

b <= \"0000\";

cin <= \'0\';

csum <= \"0000\";

ccarry <= \'0\';

wait for 10 ns;

write(v_myline, a, left, 5);

write(v_myline, b, left, 5);

write(v_myline, cin, left, 5);

write(v_myline, sum, left, 5);

write(v_myline, carry, left, 5);

write(v_myline, csum, left, 5);

write(v_myline, ccarry, left, 5);

writeline(output, v_myline);

if sum /= csum or carry /= ccarry then

report \"Result Mismatch!\";

-- wait ;

end if;

a <= \"1111\";

b <= \"1111\";

cin <= \'0\';

csum <= \"1110\";

ccarry <= \'1\';

wait for 10 ns;

write(v_myline, a, left, 5);

write(v_myline, b, left, 5);

write(v_myline, cin, left, 5);

write(v_myline, sum, left, 5);

write(v_myline, carry, left, 5);

write(v_myline, csum, left, 5);

write(v_myline, ccarry, left, 5);

writeline(output, v_myline);

if sum /= csum or carry /= ccarry then

report \"Result Mismatch!\";

wait ;

end if;

wait;

end process;

end architecture;