Getting VGA output using VHDL and a Spartan-3AN board
Hi there! Have been busy busy and busy! And you know what that means! New Code!
We were given a homework to write a game for the Spartan-3AN board. Our team decided to write a Simon Says game.(http://en.wikipedia.org/wiki/Simon_(game)) I was responsible for writing the VGA output of the program. I must say it was fun! ( I split the post as there a lot of images in this post )
So there are a few things you must know first about the Spartan-3AN board. The VGA output actually looks like as below;
The top 510 Ohms is where you want your connections. You must also follow the standard connection guidelines for your UCF file. Your VGA connections must be as below;
The other thing you must know is that the output does not have to be a std_logic_vector
type unless you want lots of colors. Since the Simon Says game uses only a few colors ( 4 main colors ) I decided to go easy on the board and instead of std_logic_vector for color outputs I simply used std_logic.
You must always keep in mind that the CRT screen acts like as below;
Below you will find a sample code that simply paints the screen… red! Why red you may ask? Because it’s my girlfriend's favorite color!
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
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;
architecture Behavioral of clockmodule is
signal clk25 : std_logic;
signal horizontal_counter : std_logic_vector (9 downto 0);
signal vertical_counter : std_logic_vector (9 downto 0);
begin
-- generate a 25Mhz clock
process (clk50_in)
begin
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
--here you paint!!
red_out <= '1';
green_out <= '0';
blue_out <= '0';
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;
Everything else is straight forward after this actually. All you have to do is to follow which point you are on. If you are good enough you can draw a simple Simon Says interface like below;