You have no items in your shopping cart.

Subtotal: 0.00

Abstract

This Project presents the design of a circuit of a playable video game: tetrix. The project requires a Spartan3 FPGA Image Processing kit which is connected to a keyboard (PS2 port) and a monitor (VGA port). The game is controlled from the keyboard and can be watched on the monitor, the screen is also showing a textbox in which is displayed the topscore, the player’s score and the keyboard keys which are used to play the game.

The project contains reusable components: 3 different type of keyboard scan code reader, vga signal generator and 2 different type of character generator.

The design is complete, meets all requirements, and it has been verified through component simulations and physical implementation. Here I must tell that the “gamecontrol” component is a little unstable, almost every changes in this component drives to bad compilation.

The circuit is defined in VHDL, and it targets a Xilinx Spartan-3E FPGA. Since all source files are VHDL, they can be used on other type of Xilinx FPGAs. The circuit was designed using the Xilinx 11.1i CAD tool.

Demonstration Video

 

Tool required

Software:

  • Xilinx ISE 11.1i

Language:

  • VHDL

Hardware:

Block Diagram for Tertix Game using Spartan3 FPGA Image Processing kit

Introduction

The design uses the PS2 port, a two-wire serial bus (including clock and data) to communicate with the keyboard and the VGA port, the five standard VGA signals Red(red), Green(grn), Blue(blu), Horizontal Sync (hs) and Vertical Sync(vs).

Design

The Tetrix was designed for Xilinx XC3S200 FPGA with 200K gates, but it should work with other Xilinx FPGAs.The design’s operating frequency is 50MHz.

To play the game push the F2 button, when the game is running you can’t use the F2 button, to begin a new game you must end it first or push the stop button(F1). The game is very similar with the Tetrix found on the internet: it has 5 different objects which you can rotate and move to left or right.

Signal Mode Description

mclk Input Main clock input
kc Input Keyboard clock
kd Input Keyboard data
blu Output VGA Blue signal
grn Output VGA Green signal
hs Output VGA Horizontal Sync
red Output VGA Red signal
vs Output VGA Vertical Sync

The game has 4 different speeds and the speed will be increased by the score: Pushing the S button will increase the speed until the block reaches the bottom.

Speed Score

1  
2 100<,<200
3 200<,
4 300<

The image below shows the actual game running on the screen





As you can see the screen contains 2 different type of objects: a textbox at the right and the tetrix at the left. I am using 2 Block RAMs in which I keep the dates. The textbox contains 32x16=512 characters and each character is kept in a 8 bit code, so here was necessary to use a BlockRAM.

I used another BlockRam at the tetrix part, this wasn’t necessary and the making of the “gamecontrol” become very complicated(you could access only 1 block once in a clock). The “tetrix“ is made by 10x20 blocks and each is memorized in 4 bits(first bit is telling if there is something or not and the other 3 is keeping the block’s color).

This means that we can draw only 8 different kind of colors(red, green, blue, yellow, black, white, aqua, fuchsia), but this is not true. If you look more carefully at the image you will see that I have more than 8 colors. To generate more colors you take the 50MHz and divide it to 25MHz,12.5MHz, 6.25MHz and make different kind of PWMs using this clocks. With this PWMs you can draw 4913 different colors or more.

On the next page you can see the RTL Schematic of the design. I am using dual-port BlockRAMs, the components from the left side of the rams are using the A ports to read and write, the components from the right side of the rams are using the B ports and they only read, they don’t write in it. The two sides are working independently from each other, the left side is the game control part and the right side is the vga control part.

The schematic can be divided horizontally too, the upper half is accessing the tetrix’s ram and they are controlling the game, while the lower half is controlling the textbox and the score of the game.

State diagram for Tetrix Game Implementation





Tertix Output Image

                                                                   Tertix Output Image


                                                         

                              Tertix Output Image     

                                   

                                   Tertix Output Image

     

                                                 Tertix Output Image

Source Code

VHDL Code for Tetrix Game Implementation using Spartan3 FPGA Image Processing kit

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
Library UNISIM;
use UNISIM.vcomponents.all;
---- Uncomment the following library declaration if instantiating
---- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;
------------------------------------------------------------------------
-- Tetrix
--
------------------------------------------------------------------------
--  Port definitions
------------------------------------------------------------------------
-- mclk       Input      Main clock input
-- kc         Input      Keyboard clock
-- kd         Input      Keyboard data
-- blu        Output   VGA Blue signal
-- grn        Output   VGA Green signal
-- hs         Output   VGA Horizontal Sync
-- red        Output   VGA Red signal
-- vs         Output   VGA Vertical Sync

------------------------------------------------------------------------
entity tetrix is
Port (     mclk       : in std_logic;
            kd         : in std_logic;
           kc          : in std_logic;

          hs         : out std_logic;
           vs          : out std_logic;
            red, grn, blu : out std_logic);


end tetrix;


architecture Behavioral of tetrix is

------------------------------------------------------------------------
-- Component Declarations
------------------------------------------------------------------------
      component vga is
      Port(      mclk       : in std_logic;
                 pix        : in std_logic_vector(2 downto 0);
                 hs              : out std_logic;
                 vs              : out std_logic;
                 red, grn, blu   : out std_logic;
                 text,vid,clkd   : out std_logic);
      end component;

      component keyboardVhdl is
      Port (   CLK, RST, KD, KC   : in std_logic;
               an            : out std_logic;
               sseg          : out std_logic_vector (7 downto 0));
      end component;

      component kbfilter is
      Port( mclk     : in std_logic;
            an       : in std_logic;
            ssegin   : in std_logic_vector (7 downto 0);

            send       : out std_logic;
            ssegout    : out std_logic_vector (7 downto 0)
            );
      end component;

      component text_display is
      Port( clkd           : in std_logic;
            texton         : in std_logic;
            car            :in std_logic_vector(7 downto 0);

        crx            :out std_logic_vector(4 downto 0);
        cry            :out std_logic_vector(3 downto 0);
        pix            :out std_logic_vector(2 downto 0));
      end component;   
      
      component score is
      Port(   mclk        :in std_logic;
              ng          :in std_logic;
              cl          :in std_logic;
        speed         :out std_logic_vector(1 downto 0);
        wen           :out std_logic;
        car           :out std_logic_vector(7 downto 0);
        crx           :out std_logic_vector(4 downto 0);
        cry           :out std_logic_vector(3 downto 0)
        );
      end component;      

      component display is
      Port(     mclk             : in std_logic;   
                clkdiv           : in std_logic;
                vidon            : in std_logic;
                rect             : in std_logic_vector(3 downto 0);
        
                  pixel              :out std_logic_vector(2 downto 0);
                  crx                :out std_logic_vector(4 downto 0);
                  cry                :out std_logic_vector(4 downto 0)
        );
      end component;

      component gamecontrol is
      Port(    mclk       : in std_logic;
               an         : in std_logic;
               sseg       : in std_logic_vector (7 downto 0);
               rectin     : in std_logic_vector(3 downto 0);
               speed      : in std_logic_vector(1 downto 0);
              ng           :out std_logic;
              cl           :out std_logic;
              wen          :out std_logic;
              rectout      :out std_logic_vector(3 downto 0);
              crx          :out std_logic_vector(4 downto 0);
              cry          :out std_logic_vector(4 downto 0)
        );
      end component;

------------------------------------------------------------------------
-- Signal Declarations
------------------------------------------------------------------------
    
    signal pix            : std_logic_vector(2 downto 0):="000";
    signal pixtetrix      : std_logic_vector(2 downto 0):="000";
    signal pixtext        : std_logic_vector(2 downto 0):="000";
    signal spd            : std_logic_vector(1 downto 0):="00";
    signal texton         : std_logic:='0';
    signal clkdiv         : std_logic:='0';
    signal vidon          : std_logic:='0';
    signal newgame        : std_logic:='0';
    signal countline      : std_logic:='0';

   --memori signals
    signal DOB            : std_logic_vector(3 downto 0):="0000";
    signal DOA            : std_logic_vector(3 downto 0):="0000";
    signal DIA            : std_logic_vector(3 downto 0):="0000";
    signal ADDRB          : std_logic_vector(9 downto 0):="0000000000";
    signal ADDRA          : std_logic_vector(9 downto 0):="0000000000";
    signal WEA            : std_logic:='0';

    signal DOBt            : std_logic_vector(7 downto 0):="00000000";
    signal DOAt            : std_logic_vector(7 downto 0):="00000000";
    signal DIAt            : std_logic_vector(7 downto 0):="00000000";
    signal ADDRBt          : std_logic_vector(8 downto 0):="000000000";
    signal ADDRAt          : std_logic_vector(8 downto 0):="000000000";
    signal WEAt            : std_logic:='0';

    --keyboard signals
    signal ssegkb          : std_logic_vector(7 downto 0):="00000000";
    signal ankb            : std_logic:='0';
    signal ssegkbnext      : std_logic_vector(7 downto 0):="00000000";
    signal send            : std_logic:='0';

    
------------------------------------------------------------------------
-- Module Implementation - 
------------------------------------------------------------------------

begin
        
    monitor: vga Port map( mclk=>mclk,
                     pix=>pix,
                   hs=>hs,
                   vs=>vs,
                   red=>red,
                   grn=>grn,
                   blu=>blu,
                    text=>texton,
                   vid=>vidon,
                   clkd=>clkdiv);

   keyboard:    keyboardVhdl port map(   CLK => mclk,
                        RST => '0',
                        KD => kd,
                        KC => kc,
                        an => ankb,
                        sseg => ssegkb);

   kbf:    kbfilter port map(   mclk => mclk,
                              an => ankb,
                              ssegin => ssegkb,
                              send => send,
                              ssegout => ssegkbnext   );



   tetrix_display:    display port map(   mclk => mclk,
                        clkdiv => clkdiv,
                        vidon => vidon,
                        rect => DOB,
                        crx => ADDRB(4 downto 0),
                        cry => ADDRB(9 downto 5),
                        pixel => pixtetrix);

   textdisplay:    text_display port map( clkd => clkdiv,
                        texton => texton,
                        car => DOBt,
                        crx => ADDRBt(4 downto 0),
                        cry => ADDRBt(8 downto 5),
                        pix => pixtext);

   score_controll:    score port map(   mclk => clkdiv,
                        ng => newgame,
                        cl => countline,
                        speed => spd,
                        wen => WEAt,
                        car => DIAt,
                        crx => ADDRAt(4 downto 0),
                        cry => ADDRAt(8 downto 5));

   tetrix_gamecontrol:    gamecontrol port map(   mclk => mclk,
                        an => send,
                        sseg => ssegkbnext,
                        rectin => DOA,
                        speed => spd,
                        ng => newgame,
                        cl => countline,
                        wen => WEA,
                        rectout => DIA,
                        crx => ADDRA(4 downto 0),
                        cry => ADDRA(9 downto 5)
                     );

   -- tetrix's BlockRAM
   RAMB4_S4_S4_inst : RAMB4_S4_S4
generic map (
          --                                1                               0
INIT_00 => X"0000000000000000000000000000000000000000000000000000000000000000",
          --                                3                               2
INIT_01 => X"0000000000000000000000000000000000000000000000000000000000000000",
          --                                5                               4
INIT_02 => X"0000000000000000000000000000000000000000000000000000000000000000",
          --                                7                               6
INIT_03 => X"00000000000000000000000000EEEC00000000000000000000000000000CCCCC",
          --                                9                               8
INIT_04 => X"0000000000000000000000000AEEEC0000000000000000000000000AAAAAEC00",
          --                               11                              10
INIT_05 => X"0000000000000000000000000AEEE0DD0000000000000000000000000A00EC00",
          --                               13                              12
INIT_06 => X"0000000000000000000000F0000F00DD0000000000000000000000000A000D0D",
          --                               15                              14
INIT_07 => X"00000000000000000000000F0F09D00D0000000000000000000000F000F90D0D",
          --                               17                              16
INIT_08 => X"00000000000000000000000F0F090000000000000000000000000000F0090000",
          --                               19                              18
INIT_09 => X"0000000000000000000000F0000F00000000000000000000000000F000F90000",

INIT_0A => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_0B => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_0C => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_0D => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_0E => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_0F => X"0000000000000000000000000000000000000000000000000000000000000000")
   port map (
      DOA => DOA,     -- Port A 4-bit data output
      DOB => DOB,     -- Port B 4-bit data output
      ADDRA => ADDRA, -- Port A 10-bit address input
      ADDRB => ADDRB, -- Port B 10-bit address input
      CLKA => mclk,   -- Port A clock input
      CLKB => mclk,   -- Port B clock input
      DIA => DIA,  -- Port A 4-bit data input
      DIB => "0000",     -- Port B 4-bit data input
      ENA => '1',     -- Port A RAM enable input
      ENB => '1',     -- Port B RAM enable input
      RSTA => '0',   -- Port A Synchronous reset input
      RSTB => '0',   -- Port B Synchronous reset input
      WEA => WEA,     -- Port A RAM write enable input
      WEB => '0'      -- Port B RAM write enable input
   );

    --------------------------------------------------------------------
    --textbox's BlockRAM
    RAMB4_S8_S8_inst : RAMB4_S8_S8
generic map (
INIT_00 => X"0007040404040404040404040404040404040404040404040404040404040401",
--   F1 - STOP GAME
INIT_01 => X"0007000000000000000000000000000000243A1C34004D442C1B004E00162B07",
-- F2 - NEW GAME   
INIT_02 => X"000700000000000000000000000000000000243A1C34001D2431004E001E2B07",   
-- A - MOVE LEFT
INIT_03 => X"0007000000000000000000000000000000002C2B244B00242A443A004E001C07",   
-- D - MOVE RIGHT
INIT_04 => X"00070000000000000000000000000000002C3334432D00242A443A004E002307",   
-- SPACE - ROTATE
INIT_05 => X"0007000000000000000000000000000000242C1C2C442D004E0024211C4D1B07",
--  S - SPEED  
INIT_06 => X"000700000000000000000000000000000000000000002324244D1B004E001B07",
-- TOP SCORE
INIT_07 => X"00070000000000000000000000000000000000000000242D44211B004D442C07",
-- YOUR SCORE   
INIT_08 => X"000700000000000000000000000000000000000000242D44211B002D3C443507",   
INIT_09 => X"0007000000000000000000000000000000000000000000000000000000000007",
INIT_0A => X"0007000000000000000000000000000000000000000000000000000000000007",
INIT_0B => X"0007000000000000000000000000000000000000000000000000000000000007",
INIT_0C => X"0007000000000000000000000000000000000000000000000000000000000007",
INIT_0D => X"0007000000000000000000000000000000000000000000000000000000000007",
INIT_0E => X"0007000000000000000000000000000000000000000000000000000000000007",
INIT_0F => X"0007050505050505050505050505050505050505050505050505050505050503")
   port map (
      DOA => DOAt,     -- Port A 8-bit data output
      DOB => DOBt,     -- Port B 8-bit data output
      ADDRA => ADDRAt, -- Port A 9-bit address input
      ADDRB => ADDRBt, -- Port B 9-bit address input
      CLKA => mclk,   -- Port A clock input
      CLKB => clkdiv,   -- Port B clock input
      DIA => DIAt, -- Port A 8-bit data input
      DIB => "00000000",     -- Port B 8-bit data input
      ENA => '1',     -- Port A RAM enable input
      ENB => '1',     -- Port B RAM enable input
      RSTA => '0',   -- Port A Synchronous reset input
      RSTB => '0',   -- Port B Synchronous reset input
      WEA => WEAt,     -- Port A RAM write enable input
      WEB => '0'      -- Port B RAM write enable input
   );
    
   -- Selecting from which component to read the pixel:
   -- tetrix or text display
   pix<= pixtetrix when vidon='1' else pixtext;
 
end Behavioral;

User Constraint File for Tetrix Game VHDL Code

NET "mclk" LOC = "P55"; 
NET red LOC=P95;
 NET grn LOC=P96;
 NET blu LOC=P97; 
NET hs LOC=P93; 
NET vs LOC=P92;
NET kc LOC=P74; 
NET kd LOC=P73; 

Conclusion

FPGA based Tetrix Game controller designed and implemented in Spartan3 FPGA Image Processing kit and game played with keyboard and monitor interfacing.