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.
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);
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
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
Am Freitag, 15. Mai 2020 00:46:01 UTC+2 schrieb Rick C:doing the actual add of the four bits.
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
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:is doing the actual add of the four bits.
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
terrible.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
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 endsand 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 processstatement 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:is doing the actual add of the four bits.
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 terrible.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
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.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
process statement is concurrent code creating a process that runs in parallel with other processes including the concurrent logic. Hence the name concurrent.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
capable.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
does and why something within a process is not the same as a simple concurrent logic without any process.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
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.
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.
On 2020-05-15 13:06, Christoph Linden wrote:
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.
You don't have to put each line in a process, just write concurrent assignments (which are, actually, implicit processes without all the fuss)
Writing
a <= b and c;
outside of a process is strictly equivalent to
process (b, c)
begin
a <= b and c;
end process;
You can therefore write
a <= b and c;
d <= a or e;
and it will give you exactly d <= (b and c) or e;
as long as it's NOT in a process.
Nicolas
Am Sonntag, 17. Mai 2020 13:43:58 UTC+2 schrieb Nicolas Matringe:would be fine. But that was to easy :-)
On 2020-05-15 13:06, Christoph Linden wrote:
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.
You don't have to put each line in a process, just write concurrent assignments (which are, actually, implicit processes without all the fuss)
Writing
a <= b and c;
outside of a process is strictly equivalent to
process (b, c)
begin
a <= b and c;
end process;
You can therefore write
a <= b and c;
d <= a or e;
and it will give you exactly d <= (b and c) or e;
as long as it's NOT in a process.
Nicolas
Thanks for the explanation ... it comes together step by step. and that is why I am doing this as a learning experience based on an already existing design I did within the nand2tetris course with a very simplified HDL.
Actually the HDL has only structural design and also comes with nothing like processes... My journey goes on now with mixed design and then getting into a full behavioural implementation. As Rick mentioned ... obviously I could simply use sum=a+b; and
Sysop: | Keyop |
---|---|
Location: | Huddersfield, West Yorkshire, UK |
Users: | 286 |
Nodes: | 16 (2 / 14) |
Uptime: | 82:45:51 |
Calls: | 6,495 |
Calls today: | 6 |
Files: | 12,096 |
Messages: | 5,276,825 |