You are on page 1of 6

VHDL tutorial based on Xilinx Spartan 3 Starter kit board http://www.derepas.

com/fabrice/hard/

VHDL tutorial
based on Xilinx Spartan 3 starter kit
board
by Fabrice Derepas.
I do not know anything about hardware but it seems to be fun.
These few pages gives the opportunity for newbies (like me) to learn some stuff about
VHDL and hardware design. This tutorial is based on the very affordable ($99)
Spartan 3 starter kit board from Xilinx.
Example name Device used
FFFF 7 segment led
AnnE 7 segment led and clock
Squares VGA port and clock
Ram tester SRAM
Bouncing ball VGA port, clock and SRAM

FFFF
The goal of this first step is to write "FFFF" on the seven-segment LED display.
This example is simple since the only thing is to do, is to send a constant signal to the
right pins. Here is the code explained. First of all include standard declarations (do not
think too much, just copy this at the beginning of each VHDL file):
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

Then declare an entity named ffff with only an output vector of 7 (6 down to 0)
elements which are either '0' or '1':
entity ffff is
Port ( LED : out std_logic_vector(6 downto 0));
end ffff;

Then describes the actions of this entity, in an architecture (named for instance
Behavioral). Its job will be to write "0001110" (which represents the letter "F" on a
LED) to the outgoing vector. Comments starts with the -- characters and ends with
the end of line.

1 of 6 10/22/2006 11:30 PM
VHDL tutorial based on Xilinx Spartan 3 Starter kit board http://www.derepas.com/fabrice/hard/

architecture Behavioral of ffff is

begin
LED <= "0001110"; -- writes the 'F' pattern to the led.
end Behavioral;

The value "0001110" for letter comes from an arbitrary mapping I have chosen, shown
on the schema below: first digit is for segment a, 2nd for f, 3rd for e, 4th for d, ... and
7th for g.

This arbitrary mapping is described in a separate file, You just have to assign elements
of the LED vector to the right pins of the FPGA. I used the following mapping, in a
file named for instance constraints.ucf:
NET "LED<0>" LOC = "E14" ;
NET "LED<1>" LOC = "G13" ;
NET "LED<2>" LOC = "N15" ;
NET "LED<3>" LOC = "P15" ;
NET "LED<4>" LOC = "R16" ;
NET "LED<5>" LOC = "F13" ;
NET "LED<6>" LOC = "N16" ;

AnnE
The goal of this exercise is to write "AnnE" on the seven-segment LED display.

This task is similar to the previous one. Since seven-segment LED displays are timed
multiplexed, we will need "something" to tell us to write the first character, then
something which tells to write the second and so on. This will be given by a clock.
Here is our entity:

entity vhdlmodule is
Port ( CLKIN : in std_logic;
AN3 : inout std_logic;
AN2 : inout std_logic;
AN1 : inout std_logic;
AN0 : inout std_logic;
LED : out std_logic_vector(6 downto 0));

2 of 6 10/22/2006 11:30 PM
VHDL tutorial based on Xilinx Spartan 3 Starter kit board http://www.derepas.com/fabrice/hard/

end vhdlmodule;

First of all we have an input signal which is a clock. Then we have the AN0, ... , AN3
signals which tell the board which of the four digit to light up. And then we have the
LED signal as in previous example.

For the clock signal we use the 50Mhz clock provided on the board. Unfortunately this
is too quick to switch beteen digits on the led panel. So we will be using a counter
named CTR, each time the counter reaches 2^13 we change the digit to be displayed, an
we reset the counter. This whole computation is put in something called a "process".
Since this process will only be triggered by changes of CLKIN, process declaration is
process(CLKIN). We say that the sensitivity list of this process is CLKIN.

architecture Behavioral of vhdlmodule is

signal CTR : STD_LOGIC_VECTOR(12 downto 0);


begin
Process (CLKIN)
begin
if CLKIN'event and CLKIN = '1' then
if (CTR="0000000000000") then
if (AN0='0') then
AN0 <= '1';
LED <= "0101011"; -- the letter n
AN1 <= '0';
elsif (AN1='0') then
AN1 <= '1';
LED <= "0101011"; -- the letter n
AN2 <= '0';
elsif (AN2='0') then
AN2 <= '1';
LED <= "0001000"; -- the letter A
AN3 <= '0';
elsif (AN3='0') then
AN3 <= '1';
LED <= "0000110"; -- the letter E
AN0 <= '0';
end if;
end if;
CTR<=CTR+"0000000000001";
if (CTR > "1000000000000") then -- counter reaches 2^13
CTR<="0000000000000";
end if;
end if; -- CLK'event and CLK = '1'
End Process;
End Behavioral;

Here is the mapping of signals on the pins of the board:


NET "AN0" LOC = "D14" ;
NET "AN1" LOC = "G14" ;
NET "AN2" LOC = "F14" ;
NET "AN3" LOC = "E13" ;
NET "CLKIN" LOC = "T9" ;
NET "LED<0>" LOC = "E14" ;
NET "LED<1>" LOC = "G13" ;
NET "LED<2>" LOC = "N15" ;
NET "LED<3>" LOC = "P15" ;

3 of 6 10/22/2006 11:30 PM
VHDL tutorial based on Xilinx Spartan 3 Starter kit board http://www.derepas.com/fabrice/hard/

NET "LED<4>" LOC = "R16" ;


NET "LED<5>" LOC = "F13" ;
NET "LED<6>" LOC = "N16" ;

Whole vhdl file

Squares
The goal of this exercise is to draw on a VGA screen squares with a side of 8 pixels as
represented in the above picture (click to enlarge).

This exercise is very similar to the previous one. We need a time input to know when
to display a pixel on the VGA screen. We will be using the 50Mhz clock clk50_in.
We will write on the red, green and blue signal. We will have to provide vertical and
horizontal sync information. So our entity declaration looks like:

entity clockmodule is
port(clk50_in : in std_logic;
red_out : out std_logic;
green_out : out std_logic;
blue_out : out std_logic;
hs_out : out std_logic;
vs_out : out std_logic);
end clockmodule;

For the architecture part we will need three signals:


a 25Mhz clock, because the Spartan-3 Starter Kit Board User Guide gives VGA
timing for a 25Mhz pixel frequency
an horizontal_counter to count the number of pixels per line
a vertical_counter to count the number of lines to dislay on the screen.
So the architecture declaration starts with:
architecture Behavioral of clockmodule is

signal clk25 : std_logic; -- the 25Mhz clock


signal horizontal_counter : std_logic_vector (9 downto 0);
signal vertical_counter : std_logic_vector (9 downto 0);

This time in the body of the architecture we will find two processes:
one to compute the clk25 signal, using clk50_in,
one to compute all out signals from clk25.
begin

-- generate a 25Mhz clock


process (clk50_in)
begin

4 of 6 10/22/2006 11:30 PM
VHDL tutorial based on Xilinx Spartan 3 Starter kit board http://www.derepas.com/fabrice/hard/

if clk50_in'event and clk50_in='1' then


if (clk25 = '0') then
clk25 <= '1';
else
clk25 <= '0';
end if;
end if;
end process;

process (clk25)
begin
if clk25'event and clk25 = '1' then
if (horizontal_counter >= "0010010000" ) -- 144
and (horizontal_counter < "1100010000" ) -- 784
and (vertical_counter >= "0000100111" ) -- 39
and (vertical_counter < "1000000111" ) -- 519
then
red_out <= horizontal_counter(3)
and vertical_counter(3);
green_out <= horizontal_counter(4)
and vertical_counter(4);
blue_out <= horizontal_counter(5)
and vertical_counter(5);
else
red_out <= '0';
green_out <= '0';
blue_out <= '0';
end if;
if (horizontal_counter > "0000000000" )
and (horizontal_counter < "0001100001" ) -- 96+1
then
hs_out <= '0';
else
hs_out <= '1';
end if;
if (vertical_counter > "0000000000" )
and (vertical_counter < "0000000011" ) -- 2+1
then
vs_out <= '0';
else
vs_out <= '1';
end if;
horizontal_counter <= horizontal_counter+"0000000001";
if (horizontal_counter="1100100000") then
vertical_counter <= vertical_counter+"0000000001";
horizontal_counter <= "0000000000";
end if;
if (vertical_counter="1000001001") then
vertical_counter <= "0000000000";
end if;
end if;
end process;

end Behavioral;

Whole VHDL file

Ram tester
This exercice is just to test the SRAM. The idea is to display some values read in the
ram on the leds.
I read the ISSI 61LV25616AL Data sheet. I did not managed to get the data in 10ns
but in only 20ns. I guess I missed something. If you have the correct way to do it just

5 of 6 10/22/2006 11:30 PM
VHDL tutorial based on Xilinx Spartan 3 Starter kit board http://www.derepas.com/fabrice/hard/

tell me :)
The global clock used is the default 50 Mhz clock with a DLL. We use a single
process which has 4 states given by the value of counter ctr:
1: send read information on the SRAM, go to state 2,
2: display read information on the led, go to state 3,
3: send write information, go to state 4,
4: erase values and go to state 1.

Vhdl Placement

Bouncing ball
Ok, now we would like to draw something on the screen which is read from the
SRAM memory. This enables us more freedom, because we design separate blocks
with a given role:
there will be a block named vga_ctrl in charge of displaying SRAM data on the
VGA port.
the role of another block named graphic_gen will be to write in the SRAM the
patterns we want to display.
Of course we will need a dedicated block to write to the memory, let us name it
ram_ctrl, and clocks will be managed in a fourth block named clk_gen. This gives the
following picture:

The pattern written in the SRAM by the graphic_gen module will be a ball bouncing
on the borders of the screen. To make it simpe the ball will be represented by a single
pixel (in the style of the pong game).
Back to my home page

6 of 6 10/22/2006 11:30 PM

You might also like