Since FPGA are becoming more accessible to the hobbyist, learning how to use them can be really useful for certain applications; moreover, engineers that are able to code in VHDL/Verilog are always requested on the job market.
In this tutorial I'll cover the basics of Xilinx ISE and VHDL.
I'll base my code on the Basys2 board from Digilent: it is really cheap (especially for students) and has a lot of features on board.
However, in this tutorial we'll only simulate our code with ISim, for the real applications check back soon!
|Digilent's Basys2 board|
So, let's start this thing. First I'll explain our test code, then I'll show you how to compile and simulate it in ISE Webpack.
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:
- ENTITY description: we state how the block is seen from outside (ports, buses, configurations...)
- ARCHITECTURE description: we describe how the block works internally.
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 # character.
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 may 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 <= keyword.
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.
I hope this tutorial is clear as we'll deal with more complex topics; if not, don't hesitate to ask!