Would you like to be notified by email when Enrico Garante publishes a new blog?
Since FPGA are becoming more accessible to the hobbyist, learning how to use them can be really useful for certain applications, like DSP and video generation; moreover, engineers that are able to code in VHDL/Verilog are always requested on the job market.
In this tutorial I will cover the basics of Xilinx ISE and VHDL. I willl base my code on the Basys2 board from Digilent: it is really cheap (especially for students) and has a lot of features on board, as you can see from the picture below.
VHDL is the acronym for VHSIC Hardware Description Language (where VHSIC stands for Very High Speed Integrated Circuits). It becomes an IEEE standard in 1987 and it is the most used language (along with Verilog) to describe digital electronic systems.
VHDL seems just like any other computer language, as it uses many common construct like if, then, else. But the main difference is that it is a dataflow language: this means that it describes how several blocks of code are connected and executed at the same time. Each block of code describes a digital subsystem, with inputs and outputs.
VHDL programming consists of two phases:
Enough theory already, let's see some code...
We start referencing the main VHDL library and using the STD_LOGIC_1164.ALL package, that contains several datatypes, logic operations and functions. This should probably be included in every entity you create.
Note that every instruction is terminated with the semicolon. To create a comment just use the -- (double minus characters).
library IEEE; use IEEE.STD_LOGIC_1164.ALL; -- This is a comment.
Then we define our "black box" with the "entity" statement followed by its name and the keyword "is".
The next statement "Port" describes how many "wires" are exposed to the outside; the list is composed this way:
name : direction type;
The last element of the list isn't terminated with the semicolon, but we need to terminate the Port statement.
The STD_LOGIC type is used to represent a digital value. It can assume several values like 0, 1, X (undefined), Z (high impedance) and many others.
Finally we end the definition of our entity with the "end" keyword.
entity AndPort is Port ( a : in STD_LOGIC; b : in STD_LOGIC; y : out STD_LOGIC); end AndPort;
Now we describe how our component works using the "architecture" statement, followed by its name and specifying to which entity it refers with the keyword "of".
The keyword begin and end will border our architecture statement.
architecture Behavioral of AndPort is begin
The "process" statement is what actually describes the behavior of our component: it resembles functions from software programming languages.
We declare it this way:
name : process (sensitivity list)
and is delimited by the usual begin and end keywords.
The sensitivity list is a list of signals that are constantly polled: every change in one of it causes the process to execute.
Inside our process there are our instructions: we assign to the output signal y the result of the logic AND operation between a and b. This is achieved with the
func:process(a,b) begin y<=(a and b); end process; end Behavioral;
And that's it! Here's the complete code for reference.
library IEEE; use IEEE.STD_LOGIC_1164.ALL; entity AndPort is Port ( a : in STD_LOGIC; b : in STD_LOGIC; y : out STD_LOGIC); end AndPort; architecture Behavioral of AndPort is begin func:process(a,b) begin y<=(a and b); end process; end Behavioral;
In the video below I show how to create a new project in ISE Webpack and simulate it with ISim.
Watch it in HD and fullscreen: http://www.youtube.com/watch?v=rMKXHDL982U
Add a Comment