# VHDL
# VHDL Design Flow
# VHDL Program Structure
Main libraries IEEE which specifies multilevel logic systems, STD which is a source library to HDL design and the work library to save files as vhd
.
LIBRARY ieee
USE ieee.std_logic_1164.all
2
Ports are pins, they can be:
in: input port. A variable or a signal can read a value from a port of mode in, but is not allowed to assign a value to it.
out: output port. It is allowed to make signal assignments to a port of the mode out, but it is not legal to read from it.
inout: bi-directional port. Both assignments to such a port and reading from it are allowed.
buffer: output port with read capability. It differs from inout in that it can be updated by at most one source, whereas inout can be updated by zero or more sources.
linkage: The value of the port may be read or updated, but only by appearing as an actual corresponding to an interface object of mode linkage.
ENTITY and_gate IS
PORT (a, b: IN BIT;
Y: OUT BIT);
END and_gate;
ENTITY half_adder IS
PORT (a, b: IN BIT;
sum, carry: OUT BIT);
END half_adder;
2
3
4
5
6
7
8
9
Style guide for entities
entity GRP_DEBOUNCER is
generic (
N : positive := 8; -- input bus width
CNT_VAL : positive := 10000 -- clock counts for debounce period
);
port (
CLK_I : in std_logic := 'X'; -- system clock
DATA_I : in std_logic_vector(1 downto 0) -- noisy input data
DATA_O : out std_logic_vector(1 downto 0); -- registered stable output data
STRB_O : out std_logic -- strobe for new data available
);
end entity GRP_DEBOUNCER;
2
3
4
5
6
7
8
9
10
11
12
The architecture declares the functionalities of the digital circuits and gives internal details of an entity which means how input and output are interconnected.
ARCHITECTURE and_gate_arch OF and_gate IS
BEGIN
y <= a and b;
END and_gate_arch;
ARCHITECTURE half_adder_arch OF half_adder IS
BEGIN
sum <= a xor b;
carry <= a and b;
END and_gate_arch;
2
3
4
5
6
7
8
9
10
VHDL architecture body can have 3 different modeling styles, dataflow style, behavioral style, or structural style.
Dataflow is described using concurrent statements, while the behavior and modeling style, where the circuit is described using sequential statements.
Style guide for architectures
architecture BEHAVIORAL of PIC is
type state_type is (
reset_s, get_commands, jump_int_method, start_polling,
ack_txinfo_rxd, start_priority_check, tx_int_info_priority
);
signal next_s : state_type :=reset_s;
signal int_type : unsigned(1 downto 0):="01";
signal int_index, count_cmd : integer := 0;
type prior_table is array (0 to 7) of unsigned(2 downto 0);
signal pt : prior_table := (others => (others => '0'));
signal int_pt : unsigned(2 downto 0):="000";
signal flag, flag1 : std_logic := '0';
begin
end architecture BEHAVIORAL;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# The first program and ModelSim simulation
entity TB1_hello_world is
end entity;
architecture arch of TB1_hello_world is
begin
process is
begin
report "Hello World";
wait;
end process;
end architecture;
2
3
4
5
6
7
8
9
10
11
12
13
14
ModelSim Steps:
- File -> New project (
quit -sim
if you are already in a simulation)
- Add or create a new file and close the window. Remember to tick reference from current location.
- Compile -> Compile All
- Simulate -> Start Simulation -> Choose the VHDL file and click OK
- Run the simulation and see the result
# Time delay in VHDL
entity TB1_wait_for is
end entity;
architecture arch of TB1_wait_for is
begin
process is
begin
-- This is the start pf the process "thread"
report "We will wait";
wait for 20 ns;
-- The process will loop back to the start
end process;
end architecture;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
TO add a new file to the project, go to view->project to see the project tab, right-click on the project and add existing file
, compile all and start the simulation.
output:
run
# ** Note: We will wait
# Time: 20 ns Iteration: 0 Instance: /tb1_wait_for
# ** Note: We will wait
# Time: 40 ns Iteration: 0 Instance: /tb1_wait_for
# ** Note: We will wait
# Time: 60 ns Iteration: 0 Instance: /tb1_wait_for
# ** Note: We will wait
# Time: 80 ns Iteration: 0 Instance: /tb1_wait_for
# ** Note: We will wait
# Time: 100 ns Iteration: 0 Instance: /tb1_wait_for
2
3
4
5
6
7
8
9
10
11
# Loop and Exit in VHDL
entity TB1_loop_exit is
end entity;
architecture arch of TB1_loop_exit is
begin
process is
begin
-- This is the start pf the process "thread"
loop
report "Inside loop";
wait for 10 ns;
end loop;
-- The process will loop back to the start
end process;
end architecture;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
entity TB1_loop_exit is
end entity;
architecture arch of TB1_loop_exit is
begin
process is
begin
-- This is the start pf the process "thread"
report "Hello";
loop
report "Inside loop";
exit;
end loop;
report "Bye";
-- The process will loop back to the start
wait;
end process;
end architecture;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
output:
run
# ** Note: Hello
# Time: 0 ps Iteration: 0 Instance: /tb1_loop_exit
# ** Note: Inside loop
# Time: 0 ps Iteration: 0 Instance: /tb1_loop_exit
# ** Note: Bye
# Time: 0 ps Iteration: 0 Instance: /tb1_loop_exit
2
3
4
5
6
7
# For-Loop in VHDL
entity TB1_For_loop is
end entity;
architecture arch of TB1_For_loop is
begin
process is
begin
for i in 0 to 10 loop
report "i = " & integer'image(i); -- i = 1, i = 2 etc...
end loop;
wait;
end process;
end architecture;
2
3
4
5
6
7
8
9
10
11
12
13
14
output:
run
# ** Note: i = 0
# Time: 0 ps Iteration: 0 Instance: /tb1_for_loop
# ** Note: i = 1
# Time: 0 ps Iteration: 0 Instance: /tb1_for_loop
# ** Note: i = 2
# Time: 0 ps Iteration: 0 Instance: /tb1_for_loop
# ** Note: i = 3
# Time: 0 ps Iteration: 0 Instance: /tb1_for_loop
# ** Note: i = 4
# Time: 0 ps Iteration: 0 Instance: /tb1_for_loop
# ** Note: i = 5
# Time: 0 ps Iteration: 0 Instance: /tb1_for_loop
# ** Note: i = 6
# Time: 0 ps Iteration: 0 Instance: /tb1_for_loop
# ** Note: i = 7
# Time: 0 ps Iteration: 0 Instance: /tb1_for_loop
# ** Note: i = 8
# Time: 0 ps Iteration: 0 Instance: /tb1_for_loop
# ** Note: i = 9
# Time: 0 ps Iteration: 0 Instance: /tb1_for_loop
# ** Note: i = 10
# Time: 0 ps Iteration: 0 Instance: /tb1_for_loop
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# While Loop in VHDL
entity TB1_While_loop is
end entity;
architecture arch of TB1_While_loop is
begin
process is
variable i : integer := 0;
begin
while i < 10 loop
report "i = " & integer'image(i); -- i = 1, i = 2 etc...
i := i + 1;
end loop;
wait;
end process;
end architecture;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
output:
run
# ** Note: i = 0
# Time: 0 ps Iteration: 0 Instance: /tb1_while_loop
# ** Note: i = 1
# Time: 0 ps Iteration: 0 Instance: /tb1_while_loop
# ** Note: i = 2
# Time: 0 ps Iteration: 0 Instance: /tb1_while_loop
# ** Note: i = 3
# Time: 0 ps Iteration: 0 Instance: /tb1_while_loop
# ** Note: i = 4
# Time: 0 ps Iteration: 0 Instance: /tb1_while_loop
# ** Note: i = 5
# Time: 0 ps Iteration: 0 Instance: /tb1_while_loop
# ** Note: i = 6
# Time: 0 ps Iteration: 0 Instance: /tb1_while_loop
# ** Note: i = 7
# Time: 0 ps Iteration: 0 Instance: /tb1_while_loop
# ** Note: i = 8
# Time: 0 ps Iteration: 0 Instance: /tb1_while_loop
# ** Note: i = 9
# Time: 0 ps Iteration: 0 Instance: /tb1_while_loop
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# Difference between Signals and Variables in VHDL
Variables are to be declared within the process
and cannot be used outside it.
Signals are declared inside the architecture and are visible to all processes.
entity TB1_Variables_signals is
end entity;
architecture arch of TB1_Variables_signals is
signal MySignal : integer := 0;
begin
process is
variable MyVariable : integer := 0;
begin
end process;
end architecture;
2
3
4
5
6
7
8
9
10
11
12
The first increment of the signal seems not to have any effect. The signal takes its value only after the wait to update the value.
A signal is updated only when a process is paused.
When assigning to a signal in a process the last assignment wins.
In this case, the assignment of the signal with <=
only takes place after the wait
, so the one that counts is the second one.
entity TB1_Variables_signals is
end entity;
architecture arch of TB1_Variables_signals is
signal MySignal : integer := 0;
begin
process is
variable MyVariable : integer := 0;
begin
MyVariable := MyVariable + 1;
MySignal <= MySignal + 1; -- <= instead of := for signals
report "MyVariable = " & integer'image(MyVariable) & " MySignal = " & integer'image(MySignal);
MyVariable := MyVariable + 1;
MySignal <= MySignal + 1; -- <= instead of := for signals
report "MyVariable = " & integer'image(MyVariable) & " MySignal = " & integer'image(MySignal);
wait for 10 ns;
report "MyVariable = " & integer'image(MyVariable) & " MySignal = " & integer'image(MySignal);
end process;
end architecture;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
output:
run
# ** Note: MyVariable = 1 MySignal = 0
# Time: 0 ps Iteration: 0 Instance: /tb1_variables_signals
# ** Note: MyVariable = 2 MySignal = 0
# Time: 0 ps Iteration: 0 Instance: /tb1_variables_signals
# ** Note: MyVariable = 2 MySignal = 1
# Time: 10 ns Iteration: 0 Instance: /tb1_variables_signals
# ** Note: MyVariable = 3 MySignal = 1
# Time: 10 ns Iteration: 0 Instance: /tb1_variables_signals
# ** Note: MyVariable = 4 MySignal = 1
# Time: 10 ns Iteration: 0 Instance: /tb1_variables_signals
# ** Note: MyVariable = 4 MySignal = 2
# Time: 20 ns Iteration: 0 Instance: /tb1_variables_signals
# ** Note: MyVariable = 5 MySignal = 2
# Time: 20 ns Iteration: 0 Instance: /tb1_variables_signals
# ** Note: MyVariable = 6 MySignal = 2
# Time: 20 ns Iteration: 0 Instance: /tb1_variables_signals
# ** Note: MyVariable = 6 MySignal = 3
# Time: 30 ns Iteration: 0 Instance: /tb1_variables_signals
# ** Note: MyVariable = 7 MySignal = 3
# Time: 30 ns Iteration: 0 Instance: /tb1_variables_signals
# ** Note: MyVariable = 8 MySignal = 3
# Time: 30 ns Iteration: 0 Instance: /tb1_variables_signals
# ** Note: MyVariable = 8 MySignal = 4
# Time: 40 ns Iteration: 0 Instance: /tb1_variables_signals
# ** Note: MyVariable = 9 MySignal = 4
# Time: 40 ns Iteration: 0 Instance: /tb1_variables_signals
# ** Note: MyVariable = 10 MySignal = 4
# Time: 40 ns Iteration: 0 Instance: /tb1_variables_signals
# ** Note: MyVariable = 10 MySignal = 5
# Time: 50 ns Iteration: 0 Instance: /tb1_variables_signals
# ** Note: MyVariable = 11 MySignal = 5
# Time: 50 ns Iteration: 0 Instance: /tb1_variables_signals
# ** Note: MyVariable = 12 MySignal = 5
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# Wait on and Wait Until in VHDL
entity TB1_Wait_on_wait_until is
end entity;
architecture arch of TB1_Wait_on_wait_until is
signal CountUp : integer := 0;
signal CountDown : integer := 10;
begin
process is
begin
CountUp <= CountUp + 1;
CountDown <= CountDown - 1;
wait for 10 ns;
end process;
process is
begin
wait on CountUP, CountDown;
report "CountUp = " & integer'image(CountUp) & " CountDown = " & integer'image(CountDown);
end process;
process is
begin
wait until CountUP = CountDown;
report "Equal";
end process;
end architecture;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
or we can combine all the waits
.
wait on CountDown until CountDown = CountUp for 10 ns;
output:
run
# ** Note: CountUp = 1 CountDown = 9
# Time: 0 ps Iteration: 1 Instance: /tb1_wait_on_wait_until
# ** Note: CountUp = 2 CountDown = 8
# Time: 10 ns Iteration: 1 Instance: /tb1_wait_on_wait_until
# ** Note: CountUp = 3 CountDown = 7
# Time: 20 ns Iteration: 1 Instance: /tb1_wait_on_wait_until
# ** Note: CountUp = 4 CountDown = 6
# Time: 30 ns Iteration: 1 Instance: /tb1_wait_on_wait_until
# ** Note: CountUp = 5 CountDown = 5
# Time: 40 ns Iteration: 1 Instance: /tb1_wait_on_wait_until
# ** Note: Equal
# Time: 40 ns Iteration: 1 Instance: /tb1_wait_on_wait_until
# ** Note: CountUp = 6 CountDown = 4
# Time: 50 ns Iteration: 1 Instance: /tb1_wait_on_wait_until
# ** Note: CountUp = 7 CountDown = 3
# Time: 60 ns Iteration: 1 Instance: /tb1_wait_on_wait_until
# ** Note: CountUp = 8 CountDown = 2
# Time: 70 ns Iteration: 1 Instance: /tb1_wait_on_wait_until
# ** Note: CountUp = 9 CountDown = 1
# Time: 80 ns Iteration: 1 Instance: /tb1_wait_on_wait_until
# ** Note: CountUp = 10 CountDown = 0
# Time: 90 ns Iteration: 1 Instance: /tb1_wait_on_wait_until
# ** Note: CountUp = 11 CountDown = -1
# Time: 100 ns Iteration: 1 Instance: /tb1_wait_on_wait_until
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# Conditional Statements In VHDL IF THEN ELSIF ELSE
entity TB1_Wait_on_wait_until is
end entity;
architecture arch of TB1_Wait_on_wait_until is
signal CountUp : integer := 0;
signal CountDown : integer := 10;
begin
process is
begin
CountUp <= CountUp + 1;
CountDown <= CountDown - 1;
wait for 10 ns;
end process;
process is
begin
if CountUp > CountDown then
report "CountUp is greater than CountDown";
elsif CountUp < CountDown then
report "CountUp is less than CountDown";
else --elsif CountDown = CountUp
report "CountUp is equal to CountDown";
end if;
wait on CountUp, CountDown;
end process;
end architecture;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
output:
run
# ** Note: CountUp is less than CountDown
# Time: 0 ps Iteration: 0 Instance: /tb1_if_elsif_else
# ** Note: CountUp is less than CountDown
# Time: 0 ps Iteration: 1 Instance: /tb1_if_elsif_else
# ** Note: CountUp is less than CountDown
# Time: 10 ns Iteration: 1 Instance: /tb1_if_elsif_else
# ** Note: CountUp is less than CountDown
# Time: 20 ns Iteration: 1 Instance: /tb1_if_elsif_else
# ** Note: CountUp is less than CountDown
# Time: 30 ns Iteration: 1 Instance: /tb1_if_elsif_else
# ** Note: CountUp is equal to CountDown
# Time: 40 ns Iteration: 1 Instance: /tb1_if_elsif_else
# ** Note: CountUp is greater than CountDown
# Time: 50 ns Iteration: 1 Instance: /tb1_if_elsif_else
# ** Note: CountUp is greater than CountDown
# Time: 60 ns Iteration: 1 Instance: /tb1_if_elsif_else
# ** Note: CountUp is greater than CountDown
# Time: 70 ns Iteration: 1 Instance: /tb1_if_elsif_else
# ** Note: CountUp is greater than CountDown
# Time: 80 ns Iteration: 1 Instance: /tb1_if_elsif_else
# ** Note: CountUp is greater than CountDown
# Time: 90 ns Iteration: 1 Instance: /tb1_if_elsif_else
# ** Note: CountUp is greater than CountDown
# Time: 100 ns Iteration: 1 Instance: /tb1_if_elsif_else
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# Relational operators
Value | Meaning |
---|---|
= | equal |
/= | not equal |
< | less than |
<= | less than or equal |
> | greater than |
>= | greater than or equal |
# Logical operators
Value | Meaning |
---|---|
not a | true if a is false |
a and b | true if a and b are true |
a or b | true if a or b are true |
a nand b | true if a or b are false - NAND gate is the same as the AND gate except that its output is inverted. |
a nor b | true if a or b are false - NOR gate is the same as that of the OR gate except that its output is inverted |
a xor b | true if exactly one of a or b are true - A gate that produces a HIGH output for one or the other input HIGH, but not both. |
a xnor b | true if a and b are equal - A gate that produces a HIGH output for both inputs HIGH or both inputs LOW. |
# Sensitivity List in VHDL
You should always use a sensitivity list to trigger process and production modules.
Sensitivity lists are parameters to a process that lists all the signals that the process is sensitive to. If any of the signals changes, the process will wake up and the code within it is executed.
entity TB1_Sensitivity_list is
end entity;
architecture arch of TB1_Sensitivity_list is
signal CountUp : integer := 0;
signal CountDown : integer := 10;
begin
process is
begin
CountUp <= CountUp + 1;
CountDown <= CountDown - 1;
wait for 10 ns;
end process;
-- Process triggered using wait statement
process is
begin
if CountUp = CountDown then
report "Process action 1";
end if;
wait on CountUp, CountDown;
end process;
-- Process triggered using sensitivity list
process(CountDown, CountUp) is
begin
if CountUp = CountDown then
report "Process action 2";
end if;
end process;
end architecture;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
These 2 processes are equivalent.
run
# ** Note: Process action 1
# Time: 40 ns Iteration: 1 Instance: /tb1_sensitivity_list
# ** Note: Process action 2
# Time: 40 ns Iteration: 1 Instance: /tb1_sensitivity_list
2
3
4
5
# Std_logic Datatype
Think of this type as a single bit, that digital information is carried by a single physical wire.
Value | Meaning |
---|---|
1 | Logic 1 |
0 | Logic 0 |
Z | High impedance |
W | Week signal, can't tell if 0 or 1 |
L | Week 0, pulldown |
H | Week 1, pullup |
- | Don't care |
U | Uninitialized |
X | Unknown, multiple drivers |
X 0 1 Z W L H -
X X X X X X X X X
0 X 0 X 0 0 0 0 X
1 X X 1 1 1 1 1 X
Z X 0 1 Z W L H X
W X 0 1 W W W W X
L X 0 1 L W L W X
H X 0 1 H W W H X
- X X X X X X X X
2
3
4
5
6
7
8
9
library ieee;
use ieee.std_logic_1164.all;
entity TB1_Sensitivity_list is
end entity;
architecture arch of TB1_Sensitivity_list is
signal Signal1 : std_logic := '0';
signal Signal2 : std_logic;
signal Signal3 : std_logic;
begin
process is
begin
wait for 10 ns;
Signal1 <= not Signal1;
end process;
end architecture;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19