# VHDL

VHDL - Style guide

# VHDL Design Flow


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
1
2

VHDL Design flow

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;
1
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;
1
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;
1
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;
1
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;
1
2
3
4
5
6
7
8
9
10
11
12
13
14

ModelSim Steps:

  1. File -> New project (quit -sim if you are already in a simulation)

ModelSim

  1. Add or create a new file and close the window. Remember to tick reference from current location.

ModelSim


ModelSim

  1. Compile -> Compile All
  2. Simulate -> Start Simulation -> Choose the VHDL file and click OK

ModelSim

  1. Run the simulation and see the result

ModelSim

# 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;
1
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.


ModelSim

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

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
1
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;
1
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 
1
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;
1
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
1
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
1
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;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

ModelSim


ModelSim


ModelSim

# Digital Electronics - A Practical Approach with VHDL

# APPENDIX E VHDL Language Reference 917


Language Reference


Language Reference


Language Reference


Language Reference


Language Reference