VHDL first contacts
Now we're going to see some samples in order to get familiar with VHDL language.
Entity
The entity keyword is used to define a VHDL module top view that defines the ports of our circuit. And the direction of each port. In VHDL you can only have 1 entity in the same file (This differs a little from Verilog)
entity Componente is Port ( i1 : in STD_LOGIC; i2 : in STD_LOGIC; i3 : in STD_LOGIC; o : out STD_LOGIC ); end Componente;
What we're defining here is some circuit with 3 input ports (i1,i2,i3) and 1 output port (o), all of these ports are of the STD_LOGIC type
In VHDL we can have these possible directions:
- in
- out
- inout
- buffer
In VHDL we have these common types:
- bit, bit_vector
- boolean
- integer
- std_ulogic, std_logic, std_logic_vector
- real
The most used datatype is the std_logic and std_logic_vector wich have these possible values.
- 'U' Unitialized
- 'X' Unknown
- 'W' Weak X
- 'Z' Floating
- '-' Don't care
Ports in a VHDL module are signals that provides access to the external world.
Another important point is that our circuit might have a port that is actually a "bus" signal, that is a multiple-bit port size, for example we set the input i1 to 6 bits in size.
entity Componente is Port ( a : in STD_LOGIC_VECTOR(5 downto 0); o : out STD_LOGIC ); end Componente;
Numbers Syntax
In VHDL numbers are represented without any special characters, what differs is the base representation, let's see first how we define bit's and bit arrays.
- '<binary value>' ('0', '1', 'X','Z')
- "<binary array>" ("0000", "01100")
One important point is that you can represent a hexadecimal value using the "x" word, for example we can use this command to pass the value "FF" to some variable.
D <= x"FC";
Description Level
Like other description languages VHDL can be used in the following levels:
- structural
- RTL level
- behavioral level
We're going to learn each of these types of description.
Hardware description of a simple combinational circuit
We're going to see how to describe a circuit in the lowest level in VHDL, using gate logic, like the verilog tutorial we're going to describe the following circuit.
library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_ARITH.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity comb_sample is Port ( a : in STD_LOGIC; b : in STD_LOGIC; c : in STD_LOGIC; y : out STD_LOGIC); end comb_sample;
architecture Behavioral of comb_sample is begin -- Concurrent statement it will be executed every time that a signal on the -- left side changes. y <= (a and b) or (b and c) or (a and c); end Behavioral;
Let's explain the first new keyword "architecture" this command indicates that we're going to start the implementation part of our circuit, after that we can clearly see how the output "y" port will "receive" a value from the logical expression of the circuit.
Observe that all line begining with a "--" will be a comment and will be ignored by the VHDL synthesizer(compiler).
Other new command is the "library" and "use" those commands are like the C "#include", they force the module to use some library containing constant, function or types declarations.
Another important point is the "<=" operator it indicates an assign operation to some signal or port, in this case the "y" port. All assign operations are concurrent, it means that no matter the order that they appear in our source code, they can execute, for that it needs only that some signal on the right part of the expression, change it's value.
Basically from this sample we can observe the basic file structure of a VHDL module

Bits concatenation
In VHDL we use the "&" operator to concatenate bits forming bit vectors. In the sample bellow we're going to assign a 16 bits port with a bunch of signals concatenated.
signal MYBUS : std_logic_vector (15 downto 0); signal STATUS :std_logic_vector (2 downto 0); signal RW, CS1, CS2 :std_logic; signal MDATA :std_logic_vector ( 0 to 9);
MYBUS <= STATUS & RW & CS1 & SC2 & MDATA;
This sample create a 16 bit signal formed by STATUS + RW + CS1 + SC2 + MDATA and assign to the MYBUS signal.
Other sample:
MYARRAY (15 downto 0) <= “111101111” & MDATA (2 to 9);
This sample assign the bit vector formed by "111101111" and the MDATA bits from position 2 to 9 to the MYARRAY signal.
Concurrency
As we said earlier a different point in HDL languages is that things can run in parallel, for instance, every assing operation will be executed if any signal from the right side of the statement change it's value, no matter the order that it appears in the source code. In VHDL all assign operations are concurrent.
Structural description
In VHDL we can use different modules arranged in a hierarquical form, so in bigger projects you can build each module at time and then arrange all the project with sub modules. In the sample bellow we're going to create the same combinational circuit using structural description. In this sample I will include the description of each module.
First the and module
entity and_2 is Port ( A : in STD_LOGIC; B : in STD_LOGIC; C : out STD_LOGIC); end and_2;
architecture Behavioral of and_2 is begin C <= A and B; end Behavioral;
Now the or module
entity or_3 is Port ( A : in STD_LOGIC; B : in STD_LOGIC; C : in STD_LOGIC; D : out STD_LOGIC); end or_3;
architecture Behavioral of or_3 is begin D <= A or B or C; end Behavioral;
Now the top module including all of the sub modules.
entity comb_struct is Port ( a : in STD_LOGIC; b : in STD_LOGIC; c : in STD_LOGIC; y : out STD_LOGIC); end comb_struct;
architecture Behavioral of comb_struct is -- Sub modules declaration component and_2 port (a,b : in std_logic; c : out std_logic); end component;
component or_3 port (a,b,c : in std_logic; d : out std_logic); end component; -- Signal declaration signal IM1, IM2, IM3 : std_logic; begin U0: and_2 port map (a, b,IM1); U1: and_2 port map (b, c,IM2); U2: and_2 port map (a, c,IM3); U3: or_3 port map (IM1,IM2,IM3,y); end Behavioral;
In this code we see 2 new keywords, the "component" and the "port map". The "component" keyword used in the arqchitecture part is used to declare a new module that will be instantiated in the current module it's syntax is the same of entity. Now the "port map" is used to instantiate the module and make the proper connections between the current module and the instantiated module.
sub_mod_label: sub_module_name port map (ports)
Behavioral description
Now we will learn how to describe circuits using statements(if,while,for,case)looking more like a normal computer language like python or C, also the coding will be sequential, rather than paralel. In order to create behavior code we must use the "process" keyword. All code inside the process code can be considered to run in serial.
process_label: process (sensivity list) begin end process;
The sensivity list store all signals that will trigger the process, once the process is triggered, all commands between begin .. end will work serially. Behavior description can be used to model all kind of digital circuit (Combinational, Sequential), we're going to model the same combinational circuit using behavioral description.
entity behav_mod is Port ( a : in STD_LOGIC; b : in STD_LOGIC; c : in STD_LOGIC; y : out STD_LOGIC); end behav_mod;
architecture Behavioral of behav_mod is begin behav : process (a,b,c) begin y <= (a and b) or (b and c) or (a and c); end process; end Behavioral;
One important point to observe when modeling combinational circuit is to include all of it's inputs on the sensivity list, this is done to avoid the synthesizer to infer a memory element.
Other important feature of behavior description is to describe sequential circuits in this sample we're going to learn the most simple sequential circuit the flip-flop D.
entity mod_ffd is Port ( RESET : in STD_LOGIC; CLK : in STD_LOGIC; Q : out STD_LOGIC; NQ : out STD_LOGIC; D : in STD_LOGIC); end mod_ffd;
architecture Behavioral of mod_ffd is begin -- FlipFlop D sample (By the way that's a comment) process(RESET, CLK, D) begin if RESET = '1' then Q <= '0'; NQ <= '1'; elsif rising_edge(CLK) then Q <= D; NQ <= not D; end if; end process; end Behavioral;
One point to remember, always that one condition in the behavior code is not defined a memory element will be infered, in the previous example we have the rising_edge function that will return true when we have a rising edge pulse in the CLK signal, in this case nothing is defined when we got different edges, so in this case a memory element will be defined.
Generic command
The generic command is used to define generic parameters that can chage watheaver we instantiate in a top module, for example we're going to define a generic register of n bits and use it in some top module.
entity gen_reg is generic(n: natural := 16); -- 16 is default value Port ( I : in std_logic_vector(n-1 downto 0); CLK : in std_logic; load : in std_logic; clear : in std_logic; O : out std_logic_vector(n-1 downto 0) ); end gen_reg;
architecture Behavioral of gen_reg is -- Signal to hold register value. signal reg_o : std_logic_vector(n-1 downto 0); begin register_behavioral : process (I,CLK,load,clear) begin if clear = '1' then reg_o <= (others => '0'); -- Turn zero all the bits of reg_o elsif rising_edge(CLK) then if load = '1' then reg_o <= I; end if; end if; end process; -- Concurrent statement O <= reg_o; end Behavioral;
The generic statement is used to create a parameter "n" that will define the size of the register, in order to use this generic register we must instatiate it in a top module.
entity top_mem_mod is Port ( CLK : in STD_LOGIC; I : in STD_LOGIC_VECTOR (15 downto 0); load : in STD_LOGIC; O : out STD_LOGIC_VECTOR (15 downto 0)); end top_mem_mod;
architecture Behavioral of top_mem_mod is constant size_reg : natural := 16; begin U0 : entity WORK.gen_reg generic map (n => size_reg) port map(I,CLK,load,'0',O); end Behavioral;
When using the "generic map" statement we can change the generic parameter before doing the port map. Other detail shown here is the instatiation without the component declaration.
Finite State machines

State machine is a general sequential circuit composed of (states, transitions and actions) The current state is based on the past states of the system and/or some input. A transition indicates a state change and is described by a condition that would need to be fulfilled to enable the transition. An action is a description of an activity that is to be performed at a given moment. For example if we are on state "opened" and the close_door condition is true we go to the "closed" state and the first action that we make is the "close door" action. There are two types of State machines
- Moore (Output depends only on the state)
- Mealy (Output depends on the state and the input)
Mealy description
This will show how to describe a mealy state machine, first we will present the state machine diagram. This state machine will detect the 101 binary value.
entity mealy_test is Port ( clk : in STD_LOGIC; x : in STD_LOGIC; clear : in STD_LOGIC; z : out STD_LOGIC); end mealy_test;
architecture Behavioral of mealy_test is -- Define a new type type tStates is (reset, got1, got10); signal next_state, current_state : tStates; begin process (clk,x,clear) begin if clear = '1' then next_state <= reset; else if rising_edge(clk) then case next_state is when reset => if x = '1' then next_state <= got1; elsif x = '0' then next_state <= reset; end if; when got1 => if x = '1' then next_state <= got1; elsif x = '0' then next_state <= got10; end if; when got10 => if x = '1' then next_state <= got1; elsif x = '0' then next_state <= reset; end if; end case; end if; end if; end process; -- This will run in parallel, observe that the output depends on the input and the state z <= '1' when (next_state = got10 and x='1') else '0'; end Behavioral;
Moore machine description
A Moore has outputs dependent on the current state, a good example is a counter, in this sample we will show a simple 2 bit counter, wich response should look like this....
