Newbee in VHDL ... why is this not working?...

C

Christoph Linden

Guest
Hi all,
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;
 
Hello

On 2020-05-14 13:49, Christoph Linden wrote:
Hi all,
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.

[...]

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);
[...]

This won\'t work. You\'re treating signals as variables, which they are
not. Remember VHDL is NOT software.
A signal gets its value assigned at the end of the process. In the
snippet above, cp0 equal \'U\' because it\'s never been assigned anything
yet. Then you compute a value (i_p(0) and i_cin) to be assigned to cp0.
On the next line, though, cp0 is still equal to \'U\' because the computed
value will not be assigned until the end of the process.
Depending on what you want to do, you can either write a second process
that will compute o_cout(0) based on cp0, or make cp0 a variable (local
to the process) instead of a signal (local to the architecture)

Nicolas
 
Hello

On 2020-05-14 13:49, Christoph Linden wrote:
Hi all,
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.

[...]

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);
[...]

This won\'t work. You\'re treating signals as variables, which they are
not. Remember VHDL is NOT software.
A signal gets its value assigned at the end of the process. In the
snippet above, cp0 equal \'U\' because it\'s never been assigned anything
yet. Then you compute a value (i_p(0) and i_cin) to be assigned to cp0.
On the next line, though, cp0 is still equal to \'U\' because the computed
value will not be assigned until the end of the process.
Depending on what you want to do, you can either write a second process
that will compute o_cout(0) based on cp0, or make cp0 a variable (local
to the process) instead of a signal (local to the architecture)

Nicolas
 
Christoph Linden <christoph.linden@googlemail.com> writes:

Hi all,
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.

Doesn\'t seem like a great way to learn. Do you have a software
background? Anyways, a quick comment on the CLA4.

> architecture cal4 of CLA4 is

[...]

begin

process (i_p, i_g, i_cin) is

begin

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);

The nature of hardware is such that these three assignments happen in
parallel, hence your o_cout(1) ends up being U at time 0. Same for
o_cout(2). I don\'t remember off hand how to code such primitives in VHDL
but somehow you need to add delay between these assignments. Or do the
assignment all at once.
 
Christoph Linden <christoph.linden@googlemail.com> writes:

Hi all,
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.

Doesn\'t seem like a great way to learn. Do you have a software
background? Anyways, a quick comment on the CLA4.

> architecture cal4 of CLA4 is

[...]

begin

process (i_p, i_g, i_cin) is

begin

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);

The nature of hardware is such that these three assignments happen in
parallel, hence your o_cout(1) ends up being U at time 0. Same for
o_cout(2). I don\'t remember off hand how to code such primitives in VHDL
but somehow you need to add delay between these assignments. Or do the
assignment all at once.
 
Am Donnerstag, 14. Mai 2020 14:29:56 UTC+2 schrieb Nicolas Matringe:
This won\'t work. You\'re treating signals as variables, which they are
not. Remember VHDL is NOT software.
A signal gets its value assigned at the end of the process. In the
snippet above, cp0 equal \'U\' because it\'s never been assigned anything
yet. Then you compute a value (i_p(0) and i_cin) to be assigned to cp0.
On the next line, though, cp0 is still equal to \'U\' because the computed
value will not be assigned until the end of the process.
Depending on what you want to do, you can either write a second process
that will compute o_cout(0) based on cp0, or make cp0 a variable (local
to the process) instead of a signal (local to the architecture)

Nicolas

Hi Nicolas, thanks for the response.

Also Thanks Anssi.

Trying to add some additional information.

I just transferred it from the HDL of nand2tetris, so that might be a bad way of doing so.

What I want to create is a combinational logic (actually defining it at gate level), where those things propagate through.

Obiously I could write an adder in a much simpler way in VHDL, but that is not my goal.

I try to first implement it as close to the gate level as posible without writing gate (e.g. AND, NOT, XOR gates).

What I am looking for is something like a propagation delay as it will happen naturally.

If I would wire discrete AND/OR Chips and want to do a ( a AND b ) OR c I would simply wire the output of the AND chip to the one input of the or gate and then with propagation delay of both gates I will receive the output at OR.

This is what I assume that all the statements would automatically do.

Can you please explain quickly how I would achieve that without implementing real gates and \"wire\" them up in VHDL but using a similar construct? Or in other words, how would you create this and/or example from above.

Now I try to split this into processes... I tried to avoid variables. Is variables a common thing to use in normal VHDL designs? I thougt it is more for use in loops, that in the end do not result in logic, but just in the behaviour description...
 
Am Donnerstag, 14. Mai 2020 14:29:56 UTC+2 schrieb Nicolas Matringe:
This won\'t work. You\'re treating signals as variables, which they are
not. Remember VHDL is NOT software.
A signal gets its value assigned at the end of the process. In the
snippet above, cp0 equal \'U\' because it\'s never been assigned anything
yet. Then you compute a value (i_p(0) and i_cin) to be assigned to cp0.
On the next line, though, cp0 is still equal to \'U\' because the computed
value will not be assigned until the end of the process.
Depending on what you want to do, you can either write a second process
that will compute o_cout(0) based on cp0, or make cp0 a variable (local
to the process) instead of a signal (local to the architecture)

Nicolas

Hi Nicolas, thanks for the response.

Also Thanks Anssi.

Trying to add some additional information.

I just transferred it from the HDL of nand2tetris, so that might be a bad way of doing so.

What I want to create is a combinational logic (actually defining it at gate level), where those things propagate through.

Obiously I could write an adder in a much simpler way in VHDL, but that is not my goal.

I try to first implement it as close to the gate level as posible without writing gate (e.g. AND, NOT, XOR gates).

What I am looking for is something like a propagation delay as it will happen naturally.

If I would wire discrete AND/OR Chips and want to do a ( a AND b ) OR c I would simply wire the output of the AND chip to the one input of the or gate and then with propagation delay of both gates I will receive the output at OR.

This is what I assume that all the statements would automatically do.

Can you please explain quickly how I would achieve that without implementing real gates and \"wire\" them up in VHDL but using a similar construct? Or in other words, how would you create this and/or example from above.

Now I try to split this into processes... I tried to avoid variables. Is variables a common thing to use in normal VHDL designs? I thougt it is more for use in loops, that in the end do not result in logic, but just in the behaviour description...
 
Okay reworked it and (besides a bug in there) it now does what it supposed to do.

However I am not sure if that is how you would do such things normally.

Should I use a fully

-- 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 cla4 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;

-- 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);

--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);


--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);
end process;

process (cp0,cp0p1,g0p1,cp0p1p2,g0p1p2,
g1p2,cp0p1p2p3,g0p1p2p3,g1p2p3,g2p3,i_g) is
begin
o_cout(0) <= cp0 or i_g(0);
o_cout(1) <= cp0p1 or g0p1 or i_g(1);
o_cout(2) <= cp0p1p2 or g0p1p2 or g1p2 or i_g(2);
o_cout(3) <= cp0p1p2p3 or g0p1p2p3 or g1p2p3 or g2p3 or i_g(3);
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);

-- Bit 1
g1 <= i_a(1) and i_b(1);
p1 <= i_a(1) xor i_b(1);

-- Bit 2
g2 <= i_a(2) and i_b(2);
p2 <= i_a(2) xor i_b(2);

-- Bit 3
g3 <= i_a(3) and i_b(3);
p3 <= i_a(3) xor i_b(3);

end process;

process(c0,c1,c2,p0,p1,p2,p3) is
begin
o_sum(0) <= p0 xor i_cin;
o_sum(1) <= p1 xor c0;
o_sum(2) <= p2 xor c1;
o_sum(3) <= p3 xor c2;
end process;


end architecture;
 
Okay reworked it and (besides a bug in there) it now does what it supposed to do.

However I am not sure if that is how you would do such things normally.

Should I use a fully

-- 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 cla4 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;

-- 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);

--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);


--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);
end process;

process (cp0,cp0p1,g0p1,cp0p1p2,g0p1p2,
g1p2,cp0p1p2p3,g0p1p2p3,g1p2p3,g2p3,i_g) is
begin
o_cout(0) <= cp0 or i_g(0);
o_cout(1) <= cp0p1 or g0p1 or i_g(1);
o_cout(2) <= cp0p1p2 or g0p1p2 or g1p2 or i_g(2);
o_cout(3) <= cp0p1p2p3 or g0p1p2p3 or g1p2p3 or g2p3 or i_g(3);
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);

-- Bit 1
g1 <= i_a(1) and i_b(1);
p1 <= i_a(1) xor i_b(1);

-- Bit 2
g2 <= i_a(2) and i_b(2);
p2 <= i_a(2) xor i_b(2);

-- Bit 3
g3 <= i_a(3) and i_b(3);
p3 <= i_a(3) xor i_b(3);

end process;

process(c0,c1,c2,p0,p1,p2,p3) is
begin
o_sum(0) <= p0 xor i_cin;
o_sum(1) <= p1 xor c0;
o_sum(2) <= p2 xor c1;
o_sum(3) <= p3 xor c2;
end process;


end architecture;
 
On Thursday, May 14, 2020 at 10:59:41 AM UTC-4, Christoph Linden wrote:
Okay reworked it and (besides a bug in there) it now does what it supposed to do.

However I am not sure if that is how you would do such things normally.

Should I use a fully

-- 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 cla4 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;

-- 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);

--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);


--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);
end process;

process (cp0,cp0p1,g0p1,cp0p1p2,g0p1p2,
g1p2,cp0p1p2p3,g0p1p2p3,g1p2p3,g2p3,i_g) is
begin
o_cout(0) <= cp0 or i_g(0);
o_cout(1) <= cp0p1 or g0p1 or i_g(1);
o_cout(2) <= cp0p1p2 or g0p1p2 or g1p2 or i_g(2);
o_cout(3) <= cp0p1p2p3 or g0p1p2p3 or g1p2p3 or g2p3 or i_g(3);
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);

-- Bit 1
g1 <= i_a(1) and i_b(1);
p1 <= i_a(1) xor i_b(1);

-- Bit 2
g2 <= i_a(2) and i_b(2);
p2 <= i_a(2) xor i_b(2);

-- Bit 3
g3 <= i_a(3) and i_b(3);
p3 <= i_a(3) xor i_b(3);

end process;

process(c0,c1,c2,p0,p1,p2,p3) is
begin
o_sum(0) <= p0 xor i_cin;
o_sum(1) <= p1 xor c0;
o_sum(2) <= p2 xor c1;
o_sum(3) <= p3 xor c2;
end process;


end architecture;

You seem to like processes for everything. There is no reason to put this particular code into processes. It can all be concurrent logic outside of processes. Then to test your code you would normally create a test fixture to instantiate your adder code, supply inputs and check outputs. Processes are useful for combinational logic to group signals when they share the same inputs. When assignments don\'t share the same inputs related assignments can be grouped using white space with a lot less typing.

process (cp0,cp0p1,g0p1,cp0p1p2,g0p1p2,
g1p2,cp0p1p2p3,g0p1p2p3,g1p2p3,g2p3,i_g) is
begin
...
end process;

Way too much typing for me.

Just my 2000 millicents worth.

BTW, the question in your post seems to have been cut off.

--

Rick C.

- Get 1,000 miles of free Supercharging
- Tesla referral code - https://ts.la/richard11209
 
On Thursday, May 14, 2020 at 10:59:41 AM UTC-4, Christoph Linden wrote:
Okay reworked it and (besides a bug in there) it now does what it supposed to do.

However I am not sure if that is how you would do such things normally.

Should I use a fully

-- 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 cla4 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;

-- 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);

--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);


--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);
end process;

process (cp0,cp0p1,g0p1,cp0p1p2,g0p1p2,
g1p2,cp0p1p2p3,g0p1p2p3,g1p2p3,g2p3,i_g) is
begin
o_cout(0) <= cp0 or i_g(0);
o_cout(1) <= cp0p1 or g0p1 or i_g(1);
o_cout(2) <= cp0p1p2 or g0p1p2 or g1p2 or i_g(2);
o_cout(3) <= cp0p1p2p3 or g0p1p2p3 or g1p2p3 or g2p3 or i_g(3);
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);

-- Bit 1
g1 <= i_a(1) and i_b(1);
p1 <= i_a(1) xor i_b(1);

-- Bit 2
g2 <= i_a(2) and i_b(2);
p2 <= i_a(2) xor i_b(2);

-- Bit 3
g3 <= i_a(3) and i_b(3);
p3 <= i_a(3) xor i_b(3);

end process;

process(c0,c1,c2,p0,p1,p2,p3) is
begin
o_sum(0) <= p0 xor i_cin;
o_sum(1) <= p1 xor c0;
o_sum(2) <= p2 xor c1;
o_sum(3) <= p3 xor c2;
end process;


end architecture;

You seem to like processes for everything. There is no reason to put this particular code into processes. It can all be concurrent logic outside of processes. Then to test your code you would normally create a test fixture to instantiate your adder code, supply inputs and check outputs. Processes are useful for combinational logic to group signals when they share the same inputs. When assignments don\'t share the same inputs related assignments can be grouped using white space with a lot less typing.

process (cp0,cp0p1,g0p1,cp0p1p2,g0p1p2,
g1p2,cp0p1p2p3,g0p1p2p3,g1p2p3,g2p3,i_g) is
begin
...
end process;

Way too much typing for me.

Just my 2000 millicents worth.

BTW, the question in your post seems to have been cut off.

--

Rick C.

- Get 1,000 miles of free Supercharging
- Tesla referral code - https://ts.la/richard11209
 
On Thursday, May 14, 2020 at 10:59:41 AM UTC-4, Christoph Linden wrote:
Okay reworked it and (besides a bug in there) it now does what it supposed to do.

However I am not sure if that is how you would do such things normally.

Should I use a fully

I don\'t know, you didn\'t finish the question.

You might look at the regularity in the calculations and use looping constructs to evaluate them. Then you would need either processes or generate statements.

For example, just as you use a vector for o_sum (which you never declare either internally or as an output) you can define your intermediate terms as vectors letting the index point to the right one at the right time.

You will need to give this a bit of thought and a nice diagram of the arrangement of the logical entities would help to see the regularity of the problem being solved.

Here is your code without the processes.


-- 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 cla4 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

cp0 <= i_p(0) and i_cin;

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

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);

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(0) <= cp0 or i_g(0);
o_cout(1) <= cp0p1 or g0p1 or i_g(1);
o_cout(2) <= cp0p1p2 or g0p1p2 or g1p2 or i_g(2);
o_cout(3) <= cp0p1p2p3 or g0p1p2p3 or g1p2p3 or g2p3 or i_g(3);

-- Bit 1
g1 <= i_a(1) and i_b(1);
p1 <= i_a(1) xor i_b(1);

-- Bit 2
g2 <= i_a(2) and i_b(2);
p2 <= i_a(2) xor i_b(2);

-- Bit 3
g3 <= i_a(3) and i_b(3);
p3 <= i_a(3) xor i_b(3);

o_sum(0) <= p0 xor i_cin;
o_sum(1) <= p1 xor c0;
o_sum(2) <= p2 xor c1;
o_sum(3) <= p3 xor c2;

end architecture;

--

Rick C.

+ Get 1,000 miles of free Supercharging
+ Tesla referral code - https://ts.la/richard11209
 
On Thursday, May 14, 2020 at 10:59:41 AM UTC-4, Christoph Linden wrote:
Okay reworked it and (besides a bug in there) it now does what it supposed to do.

However I am not sure if that is how you would do such things normally.

Should I use a fully

I don\'t know, you didn\'t finish the question.

You might look at the regularity in the calculations and use looping constructs to evaluate them. Then you would need either processes or generate statements.

For example, just as you use a vector for o_sum (which you never declare either internally or as an output) you can define your intermediate terms as vectors letting the index point to the right one at the right time.

You will need to give this a bit of thought and a nice diagram of the arrangement of the logical entities would help to see the regularity of the problem being solved.

Here is your code without the processes.


-- 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 cla4 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

cp0 <= i_p(0) and i_cin;

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

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);

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(0) <= cp0 or i_g(0);
o_cout(1) <= cp0p1 or g0p1 or i_g(1);
o_cout(2) <= cp0p1p2 or g0p1p2 or g1p2 or i_g(2);
o_cout(3) <= cp0p1p2p3 or g0p1p2p3 or g1p2p3 or g2p3 or i_g(3);

-- Bit 1
g1 <= i_a(1) and i_b(1);
p1 <= i_a(1) xor i_b(1);

-- Bit 2
g2 <= i_a(2) and i_b(2);
p2 <= i_a(2) xor i_b(2);

-- Bit 3
g3 <= i_a(3) and i_b(3);
p3 <= i_a(3) xor i_b(3);

o_sum(0) <= p0 xor i_cin;
o_sum(1) <= p1 xor c0;
o_sum(2) <= p2 xor c1;
o_sum(3) <= p3 xor c2;

end architecture;

--

Rick C.

+ Get 1,000 miles of free Supercharging
+ Tesla referral code - https://ts.la/richard11209
 
Am Freitag, 15. Mai 2020 00:46:01 UTC+2 schrieb Rick C:
Thank you Rick, very helpful.

1. Unfortunately I do not know anymore what the questions should have been. I believe it was in the ballpark how I can do this similar to a structural design but without defining single and gates.

2. The o_sum part. The problem is, that for whatever reason google.groups interpreted part of the code as \"quote\". So if you click on the quote you see, that it is actually two entities. One entity is calculating the carry look ahead and the other is doing the actual add of the four bits.

That is why it looks so weird if you do not unfold the quote.

But anyhow I understood what you was saying and yes, I just used the process, because I did not understood that I do not need to use process all the time.

I will give it a try.

Is the following understanding correct:

Process for sequential (a must to react on the clock and the edge of the signal)

no process for combinatory circuits (such as ALU designs)
 
Am Freitag, 15. Mai 2020 00:46:01 UTC+2 schrieb Rick C:
Thank you Rick, very helpful.

1. Unfortunately I do not know anymore what the questions should have been. I believe it was in the ballpark how I can do this similar to a structural design but without defining single and gates.

2. The o_sum part. The problem is, that for whatever reason google.groups interpreted part of the code as \"quote\". So if you click on the quote you see, that it is actually two entities. One entity is calculating the carry look ahead and the other is doing the actual add of the four bits.

That is why it looks so weird if you do not unfold the quote.

But anyhow I understood what you was saying and yes, I just used the process, because I did not understood that I do not need to use process all the time.

I will give it a try.

Is the following understanding correct:

Process for sequential (a must to react on the clock and the edge of the signal)

no process for combinatory circuits (such as ALU designs)
 
On Friday, May 15, 2020 at 2:00:27 AM UTC-4, Christoph Linden wrote:
Am Freitag, 15. Mai 2020 00:46:01 UTC+2 schrieb Rick C:
Thank you Rick, very helpful.

1. Unfortunately I do not know anymore what the questions should have been. I believe it was in the ballpark how I can do this similar to a structural design but without defining single and gates.

2. The o_sum part. The problem is, that for whatever reason google.groups interpreted part of the code as \"quote\". So if you click on the quote you see, that it is actually two entities. One entity is calculating the carry look ahead and the other is doing the actual add of the four bits.

That is why it looks so weird if you do not unfold the quote.

But anyhow I understood what you was saying and yes, I just used the process, because I did not understood that I do not need to use process all the time.

I will give it a try.

Is the following understanding correct:

Process for sequential (a must to react on the clock and the edge of the signal)

no process for combinatory circuits (such as ALU designs)

It is obvious you are just getting started, so I understand. I had no one to ask when I learned to use VHDL. I took a week course and the instructor sucked so badly he answered questions wrong. It\'s one thing not to know, but giving out bad info is terrible.

I won\'t say you should not use a process for combinational circuits. A process is of no value for simple assignments to signals. Processes also have variables which are updated immediately, unlike signals which are not updated until the process ends and the simulation proceeds to the next time step which is a delta time step. That\'s a bit complicated and I\'m happy to explain it if you want. Most people consider that signals are updated at the end of the process which is essentially correct.

Concurrent code does not use variables. Every concurrent assignment is actually a process. It runs whenever any of the inputs change state, just like a process. Essentially all concurrent code produces logic that runs in parallel. Even the process statement is concurrent code creating a process that runs in parallel with other processes including the concurrent logic. Hence the name concurrent.

Variables can used in sequential code such as processes, functions and procedures. They allow code to be written in a similar manner to code written for CPUs which are executed sequentially. For example you can write

a := b + c;
a := a + d;

This would add b, c and d and assign it to a in the order shown. If a were a signal, the last assignment in the process would be the only one taking effect. Notice a different assignment operator is used for signals <= and variables :=

Often beginners confuse processes with subroutines like sequential programming languages use. You don\'t seem to have that confusion.

So there are many ways to do the job. It also makes a difference if you are working with VHDL 2008 or an older version. There are many improvements in 2008 that makes coding easier. Often you must enable VHDL 2008 in your tool even if it is capable.

I hope this helps.

--

Rick C.

-- Get 1,000 miles of free Supercharging
-- Tesla referral code - https://ts.la/richard11209
 
On Friday, May 15, 2020 at 2:00:27 AM UTC-4, Christoph Linden wrote:
Am Freitag, 15. Mai 2020 00:46:01 UTC+2 schrieb Rick C:
Thank you Rick, very helpful.

1. Unfortunately I do not know anymore what the questions should have been. I believe it was in the ballpark how I can do this similar to a structural design but without defining single and gates.

2. The o_sum part. The problem is, that for whatever reason google.groups interpreted part of the code as \"quote\". So if you click on the quote you see, that it is actually two entities. One entity is calculating the carry look ahead and the other is doing the actual add of the four bits.

That is why it looks so weird if you do not unfold the quote.

But anyhow I understood what you was saying and yes, I just used the process, because I did not understood that I do not need to use process all the time.

I will give it a try.

Is the following understanding correct:

Process for sequential (a must to react on the clock and the edge of the signal)

no process for combinatory circuits (such as ALU designs)

It is obvious you are just getting started, so I understand. I had no one to ask when I learned to use VHDL. I took a week course and the instructor sucked so badly he answered questions wrong. It\'s one thing not to know, but giving out bad info is terrible.

I won\'t say you should not use a process for combinational circuits. A process is of no value for simple assignments to signals. Processes also have variables which are updated immediately, unlike signals which are not updated until the process ends and the simulation proceeds to the next time step which is a delta time step. That\'s a bit complicated and I\'m happy to explain it if you want. Most people consider that signals are updated at the end of the process which is essentially correct.

Concurrent code does not use variables. Every concurrent assignment is actually a process. It runs whenever any of the inputs change state, just like a process. Essentially all concurrent code produces logic that runs in parallel. Even the process statement is concurrent code creating a process that runs in parallel with other processes including the concurrent logic. Hence the name concurrent.

Variables can used in sequential code such as processes, functions and procedures. They allow code to be written in a similar manner to code written for CPUs which are executed sequentially. For example you can write

a := b + c;
a := a + d;

This would add b, c and d and assign it to a in the order shown. If a were a signal, the last assignment in the process would be the only one taking effect. Notice a different assignment operator is used for signals <= and variables :=

Often beginners confuse processes with subroutines like sequential programming languages use. You don\'t seem to have that confusion.

So there are many ways to do the job. It also makes a difference if you are working with VHDL 2008 or an older version. There are many improvements in 2008 that makes coding easier. Often you must enable VHDL 2008 in your tool even if it is capable.

I hope this helps.

--

Rick C.

-- Get 1,000 miles of free Supercharging
-- Tesla referral code - https://ts.la/richard11209
 
Am Freitag, 15. Mai 2020 09:02:59 UTC+2 schrieb Rick C:
On Friday, May 15, 2020 at 2:00:27 AM UTC-4, Christoph Linden wrote:
Am Freitag, 15. Mai 2020 00:46:01 UTC+2 schrieb Rick C:
Thank you Rick, very helpful.

1. Unfortunately I do not know anymore what the questions should have been. I believe it was in the ballpark how I can do this similar to a structural design but without defining single and gates.

2. The o_sum part. The problem is, that for whatever reason google.groups interpreted part of the code as \"quote\". So if you click on the quote you see, that it is actually two entities. One entity is calculating the carry look ahead and the other is doing the actual add of the four bits.

That is why it looks so weird if you do not unfold the quote.

But anyhow I understood what you was saying and yes, I just used the process, because I did not understood that I do not need to use process all the time.

I will give it a try.

Is the following understanding correct:

Process for sequential (a must to react on the clock and the edge of the signal)

no process for combinatory circuits (such as ALU designs)

It is obvious you are just getting started, so I understand. I had no one to ask when I learned to use VHDL. I took a week course and the instructor sucked so badly he answered questions wrong. It\'s one thing not to know, but giving out bad info is terrible.

I won\'t say you should not use a process for combinational circuits. A process is of no value for simple assignments to signals. Processes also have variables which are updated immediately, unlike signals which are not updated until the process ends and the simulation proceeds to the next time step which is a delta time step. That\'s a bit complicated and I\'m happy to explain it if you want. Most people consider that signals are updated at the end of the process which is essentially correct.

Concurrent code does not use variables. Every concurrent assignment is actually a process. It runs whenever any of the inputs change state, just like a process. Essentially all concurrent code produces logic that runs in parallel. Even the process statement is concurrent code creating a process that runs in parallel with other processes including the concurrent logic.. Hence the name concurrent.

Variables can used in sequential code such as processes, functions and procedures. They allow code to be written in a similar manner to code written for CPUs which are executed sequentially. For example you can write

a := b + c;
a := a + d;

This would add b, c and d and assign it to a in the order shown. If a were a signal, the last assignment in the process would be the only one taking effect. Notice a different assignment operator is used for signals <= and variables :=

Often beginners confuse processes with subroutines like sequential programming languages use. You don\'t seem to have that confusion.

So there are many ways to do the job. It also makes a difference if you are working with VHDL 2008 or an older version. There are many improvements in 2008 that makes coding easier. Often you must enable VHDL 2008 in your tool even if it is capable.

I hope this helps.

--

Rick C.

-- Get 1,000 miles of free Supercharging
-- Tesla referral code - https://ts.la/richard11209

Thank you so much Rick, that really helps and is highly appreciated.

I was aware of the parallelity of execution, but actually the process is only update one time... So you are right, what I would need to do would be putting each line in a process, which is pretty much pointless.

I came from nand2tetris, which has a much more simplified HDL to get the principles of chip design transported/tought. I now wanted to get into a real HDL to implement this chip (a very simple 16bit processor) into an FPGA.

So i learned some of the tutorials from https://vhdlwhiz.com/, which helped alot - for instance all the basic gates and muxers and stuff I could implement easily. But at that point I struggled because of simply not really understanding what a process does and why something within a process is not the same as a simple concurrent logic without any process.

You helped me on that alot and it is now much clearer. I am pretty sure I will stumble accross it again in the future, as things are getting more complicated, but for now.

THANKS A MILLION, really appreciated.
 
Am Freitag, 15. Mai 2020 09:02:59 UTC+2 schrieb Rick C:
On Friday, May 15, 2020 at 2:00:27 AM UTC-4, Christoph Linden wrote:
Am Freitag, 15. Mai 2020 00:46:01 UTC+2 schrieb Rick C:
Thank you Rick, very helpful.

1. Unfortunately I do not know anymore what the questions should have been. I believe it was in the ballpark how I can do this similar to a structural design but without defining single and gates.

2. The o_sum part. The problem is, that for whatever reason google.groups interpreted part of the code as \"quote\". So if you click on the quote you see, that it is actually two entities. One entity is calculating the carry look ahead and the other is doing the actual add of the four bits.

That is why it looks so weird if you do not unfold the quote.

But anyhow I understood what you was saying and yes, I just used the process, because I did not understood that I do not need to use process all the time.

I will give it a try.

Is the following understanding correct:

Process for sequential (a must to react on the clock and the edge of the signal)

no process for combinatory circuits (such as ALU designs)

It is obvious you are just getting started, so I understand. I had no one to ask when I learned to use VHDL. I took a week course and the instructor sucked so badly he answered questions wrong. It\'s one thing not to know, but giving out bad info is terrible.

I won\'t say you should not use a process for combinational circuits. A process is of no value for simple assignments to signals. Processes also have variables which are updated immediately, unlike signals which are not updated until the process ends and the simulation proceeds to the next time step which is a delta time step. That\'s a bit complicated and I\'m happy to explain it if you want. Most people consider that signals are updated at the end of the process which is essentially correct.

Concurrent code does not use variables. Every concurrent assignment is actually a process. It runs whenever any of the inputs change state, just like a process. Essentially all concurrent code produces logic that runs in parallel. Even the process statement is concurrent code creating a process that runs in parallel with other processes including the concurrent logic.. Hence the name concurrent.

Variables can used in sequential code such as processes, functions and procedures. They allow code to be written in a similar manner to code written for CPUs which are executed sequentially. For example you can write

a := b + c;
a := a + d;

This would add b, c and d and assign it to a in the order shown. If a were a signal, the last assignment in the process would be the only one taking effect. Notice a different assignment operator is used for signals <= and variables :=

Often beginners confuse processes with subroutines like sequential programming languages use. You don\'t seem to have that confusion.

So there are many ways to do the job. It also makes a difference if you are working with VHDL 2008 or an older version. There are many improvements in 2008 that makes coding easier. Often you must enable VHDL 2008 in your tool even if it is capable.

I hope this helps.

--

Rick C.

-- Get 1,000 miles of free Supercharging
-- Tesla referral code - https://ts.la/richard11209

Thank you so much Rick, that really helps and is highly appreciated.

I was aware of the parallelity of execution, but actually the process is only update one time... So you are right, what I would need to do would be putting each line in a process, which is pretty much pointless.

I came from nand2tetris, which has a much more simplified HDL to get the principles of chip design transported/tought. I now wanted to get into a real HDL to implement this chip (a very simple 16bit processor) into an FPGA.

So i learned some of the tutorials from https://vhdlwhiz.com/, which helped alot - for instance all the basic gates and muxers and stuff I could implement easily. But at that point I struggled because of simply not really understanding what a process does and why something within a process is not the same as a simple concurrent logic without any process.

You helped me on that alot and it is now much clearer. I am pretty sure I will stumble accross it again in the future, as things are getting more complicated, but for now.

THANKS A MILLION, really appreciated.
 
Am Freitag, 15. Mai 2020 09:02:59 UTC+2 schrieb Rick C:
On Friday, May 15, 2020 at 2:00:27 AM UTC-4, Christoph Linden wrote:
Am Freitag, 15. Mai 2020 00:46:01 UTC+2 schrieb Rick C:
Thank you Rick, very helpful.

1. Unfortunately I do not know anymore what the questions should have been. I believe it was in the ballpark how I can do this similar to a structural design but without defining single and gates.

2. The o_sum part. The problem is, that for whatever reason google.groups interpreted part of the code as \"quote\". So if you click on the quote you see, that it is actually two entities. One entity is calculating the carry look ahead and the other is doing the actual add of the four bits.

That is why it looks so weird if you do not unfold the quote.

But anyhow I understood what you was saying and yes, I just used the process, because I did not understood that I do not need to use process all the time.

I will give it a try.

Is the following understanding correct:

Process for sequential (a must to react on the clock and the edge of the signal)

no process for combinatory circuits (such as ALU designs)

It is obvious you are just getting started, so I understand. I had no one to ask when I learned to use VHDL. I took a week course and the instructor sucked so badly he answered questions wrong. It\'s one thing not to know, but giving out bad info is terrible.

I won\'t say you should not use a process for combinational circuits. A process is of no value for simple assignments to signals. Processes also have variables which are updated immediately, unlike signals which are not updated until the process ends and the simulation proceeds to the next time step which is a delta time step. That\'s a bit complicated and I\'m happy to explain it if you want. Most people consider that signals are updated at the end of the process which is essentially correct.

Concurrent code does not use variables. Every concurrent assignment is actually a process. It runs whenever any of the inputs change state, just like a process. Essentially all concurrent code produces logic that runs in parallel. Even the process statement is concurrent code creating a process that runs in parallel with other processes including the concurrent logic.. Hence the name concurrent.

Variables can used in sequential code such as processes, functions and procedures. They allow code to be written in a similar manner to code written for CPUs which are executed sequentially. For example you can write

a := b + c;
a := a + d;

This would add b, c and d and assign it to a in the order shown. If a were a signal, the last assignment in the process would be the only one taking effect. Notice a different assignment operator is used for signals <= and variables :=

Often beginners confuse processes with subroutines like sequential programming languages use. You don\'t seem to have that confusion.

So there are many ways to do the job. It also makes a difference if you are working with VHDL 2008 or an older version. There are many improvements in 2008 that makes coding easier. Often you must enable VHDL 2008 in your tool even if it is capable.

I hope this helps.

--

Rick C.

-- Get 1,000 miles of free Supercharging
-- Tesla referral code - https://ts.la/richard11209

Thank you so much Rick, that really helps and is highly appreciated.

I was aware of the parallelity of execution, but actually the process is only update one time... So you are right, what I would need to do would be putting each line in a process, which is pretty much pointless.

I came from nand2tetris, which has a much more simplified HDL to get the principles of chip design transported/tought. I now wanted to get into a real HDL to implement this chip (a very simple 16bit processor) into an FPGA.

So i learned some of the tutorials from https://vhdlwhiz.com/, which helped alot - for instance all the basic gates and muxers and stuff I could implement easily. But at that point I struggled because of simply not really understanding what a process does and why something within a process is not the same as a simple concurrent logic without any process.

You helped me on that alot and it is now much clearer. I am pretty sure I will stumble accross it again in the future, as things are getting more complicated, but for now.

THANKS A MILLION, really appreciated.
 

Welcome to EDABoard.com

Sponsor

Back
Top