VHDL Component Tutorial
This tutorial will explain how to incorperate components into your VHDL code. Components are useful because they allow reuse of VHDL. Similar to how you currently may use "AND" over and over in your code, you can create more complex creations that can be easily duplicated.
In fact, for this example, what will be created is an AND gate. The system we are looking to model is as follows:
This system has three inputs (a, b, c) and one output (d). It has two internal lines, which I have called temp1 and temp2. Finally, there are the three AND gates.
If we were just creating the AND gate, we know how to do the VHDL code for that:
library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_ARITH.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; entity and_gate is Port ( a : in std_logic; b : in std_logic; c : out std_logic); end and_gate; architecture Structural of and_gate is begin c <= a AND b; end Structural;
Note: instead of writing the architecture as a structural definition, one could have done it behaviorally instead:
architecture Behavioral of and_gate is begin process(a, b) begin if (a = '1' and b = '1') then c <= '1'; else c <= '0'; end if; end process; end Behavioral;
Now that we have defined our AND gate, we can refer to it within our code. There are two ways to do this. One is by putting it into a package, and including the package. The second is to include it directly in our code.
A package definition (in its own file) is useful if you are including several components at once. It would look something like this:
library IEEE; use IEEE.STD_LOGIC_1164.ALL; package and_gate_package is component and_gate Port ( a,b: in std_logic; c: out std_logic); end component; -- additional component definitions go here end and_gate_package;
Then, back in your original file, you would say the following to include it:
library IEEE; use IEEE.STD_LOGIC_1164.ALL; use WORK.and_gate_package.ALL;
Since I am just including one AND gate component, I will not use this method but rather include the component declaration directly. By the name of the component, VHDL looks in the same directory for that file and includes it directly.
library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_ARITH.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; entity top is Port ( a : in std_logic; b : in std_logic; c : in std_logic; d : out std_logic); end top; architecture Structural of top is component and_gate IS PORT ( a, b: in std_logic; c: out std_logic); end component; -- additional component definitions go here begin -- code goes here... end Structural;
So, now we have access to that component within our code. We still need to setup the two wires temp1 and temp2. These are called "Signals" in VHDL and are internal information to our entity top. Their definition goes directly after the component definition:
architecture Structural of top is component and_gate IS PORT ( a, b: in std_logic; c: out std_logic); end component; Signal temp1, temp2: std_logic; begin -- code goes here... end Structural;
Finally, we have to define how our circuit is put together. To do this, we use the PORT MAP command. This is code that tells VHDL how the wires are connected together:
architecture Structural of top is component and_gate IS PORT ( a, b: in std_logic; c: out std_logic); end component; Signal temp1, temp2: std_logic; begin and1: and_gate PORT MAP(a, b, temp1); and2: and_gate PORT MAP(a, c, temp2); and3: and_gate PORT MAP(temp1, temp2, d); end Structural;
In this example, you first give each component in your diagram a different name (here and1, and2, and3). Then you tell VHDL which component it refers to (in this example, they all refer to and_gate). Then you use the PORT MAP command to say which wires/signals are the inputs/outputs to the gate. The order has to match your previous component declaration (here the first two in the list are inputs, the third is an output).
Now you have defined your diagram within VHDL. This is also advantageous because you can change around the functionality of and_gate without needing to change this original code. All you have to do it recompile.
Within Xilinx, it looks as follows:
Note that when you compile it, Xilinx even recognizes the heirarchy of your code and displays this within the Source window:
Here is the code from explained above entered into the Project Navigator: