Implementing Ping Pong game on an FPGA in VHDL

Background

Pong - a timeless and iconic classic. Code in VHDL.




VHDL Implementation on an Altera DE1 FPGA:

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity ERSPrac3 is
 port (
   CLOCK_50 : IN std_logic;
   SW : in std_logic_vector(9 DOWNTO 0);
   LEDR : out std_logic_vector(9 DOWNTO 0);
   LEDG : out std_logic_vector(7 DOWNTO 0);
   KEY : in std_logic_vector(3 DOWNTO 0);
   
   HEX0 : OUT std_logic_vector(6 DOWNTO 0);
   HEX1 : OUT std_logic_vector(6 DOWNTO 0);
   HEX2 : OUT std_logic_vector(6 DOWNTO 0);
   HEX3 : OUT std_logic_vector(6 DOWNTO 0)
   
   
   ) ;
end ERSPrac3;

architecture behaviour of ERSPrac3 is
 type stateType is (S_HoldR, S_HoldL, RL1, RL2, RL3, RL4, RL5, RL6, RL7 , RR1,RR2,RR3,RR4,RR5,RR6, RR7, WINL, WINR);
 signal currentState : stateType; 
 signal nextState: stateType;
 
 signal clk_1 : std_logic;
 
 signal scoreL : unsigned(3 DOWNTO 0) := "0000";
 
 signal scoreR : unsigned(3 DOWNTO 0) := "0000";
 
 signal outvector : std_logic_vector(7 DOWNTO 0);
 
begin

clock_gen : process(CLOCK_50)
 variable count : natural;
begin

 if rising_edge(CLOCK_50) then
  clk_1 <= '0';
  count := count + 1;
  if count = 12500000 then
   clk_1 <= '1';
   count := 0;
  end if;
 end if;

end process;

statereg : process(clk_1) -- state:
begin
 -- state register logic stuff
 
 if (SW(9) = '1') then
  currentState <= S_HoldR;
 elsif (rising_edge(clk_1) and SW(9) = '0') then
  currentState <= nextState;
 end if;

end process;

next_statelogic: process (currentState)
begin

 case currentState is
  when S_HoldL =>
   if (KEY(3) = '1') then
    nextState <= RR1;
   else
    nextState <= S_HoldL;
   end if;
   
  when S_HoldR =>
   if (KEY(0) = '1') then
    nextState <= RL1;
   else
    nextState <= S_HoldR;
   end if;
   
  when RL1 =>
   nextState <= RL2;
  
  when RL2 =>
   nextState <= RL3;
   
  when RL3 =>
   nextState <= RL4;
  
  when RL4 =>
   nextState <= RL5;
   
  when RL5 =>
   nextState <= RL6;
   
  when RL6 =>
   nextState <= RL7;
   
  when RL7 =>
   if (KEY(3) = '0') then
    nextState <= S_HoldL;
   else
    -- SCORE INCREASE, SERVE FROM RIGHT AGAIN, RIGHT PLAYER WINS A POINT
    nextState <= WINR;

   end if;
   
  when RR1 =>
   nextState <= RR2;
  
  when RR2 =>
   nextState <= RR3;
   
  when RR3 =>
   nextState <= RR4;
  
  when RR4 =>
   nextState <= RR5;
   
  when RR5 =>
   nextState <= RR6;
   
  when RR6 =>
   nextState <= RR7;
   
  when RR7 =>
   if (KEY(0) = '0') then
    nextState <= S_HoldR;
   else
    -- SCORE INCREASE LEFT PLAYER, SERVE FROM RIGHT AGAIN
    nextState <= WINL;
    
   end if;
   
  when WINL =>
    nextState <= S_HoldR;
   
  when WINR =>
    nextState <= S_HoldR;
    scoreR <= scoreR + 1;
  
 end case;
   
end process;
 
out_logic : process (currentState)
begin

 LEDR(9 DOWNTO 0) <= (others => '0');
 case currentState is
  when S_HoldR =>
   outvector <= "00000001";
   
  when S_HoldL =>
   outvector <= "10000000";
  
  when RL1 =>
   outvector <= "00000010";
  when RL2 =>
   outvector <= "00000100";
  when RL3 =>
   outvector <= "00001000";
  when RL4 =>
   outvector <= "00010000";
  when RL5 =>
   outvector <= "00100000";
  when RL6 =>
   outvector <= "01000000";
  when RL7 =>
   outvector <= "10000000";
   
  when RR1 =>
   outvector <= "01000000";
  when RR2 =>
   outvector <= "00100000";
  when RR3 =>
   outvector <= "00010000";
  when RR4 =>
   outvector <= "00001000";
  when RR5 =>
   outvector <= "00000100";
  when RR6 =>
   outvector <= "00000010";
  when RR7 =>
   outvector <= "00000001";
  when WINL =>
   outvector <= "11111111";
   LEDR(9 DOWNTO 0) <= (others => '1');
  when WINR =>
   outvector <= "11111111";
   LEDR(9 DOWNTO 0) <= (others => '1');

   
 end case;

 LEDG(7 DOWNTO 0) <= outvector(7 DOWNTO 0);
 
end process;

score_disp : process(clk_1)
begin

 if (rising_edge(clk_1)) then
  CASE scoreL IS
    WHEN "0000"=>HEX3<="1000000";
    WHEN "0001"=>HEX3<="1111001";
    WHEN "0010"=>HEX3<="0100100";
    WHEN "0011"=>HEX3<="0110000";
    WHEN "0100"=>HEX3<="0011001";
    WHEN "0101"=>HEX3<="0010010";
    WHEN "0110"=>HEX3<="0000010";
    WHEN "0111"=>HEX3<="1111000";
    WHEN "1000"=>HEX3<="0000000";
    WHEN "1001"=>HEX3<="0011000";
    WHEN OTHERS=>HEX3<="1111111";
  END CASE;
  
  CASE scoreR IS
    WHEN "0000"=>HEX0<="1000000";
    WHEN "0001"=>HEX0<="1111001";
    WHEN "0010"=>HEX0<="0100100";
    WHEN "0011"=>HEX0<="0110000";
    WHEN "0100"=>HEX0<="0011001";
    WHEN "0101"=>HEX0<="0010010";
    WHEN "0110"=>HEX0<="0000010";
    WHEN "0111"=>HEX0<="1111000";
    WHEN "1000"=>HEX0<="0000000";
    WHEN "1001"=>HEX0<="0011000";
    WHEN OTHERS=>HEX0<="1111111";
  END CASE;
  

  HEX1 <= (others => '1');
  HEX2 <= (others => '1');
  
  end if;
end process;
end behaviour;

1 comment:

Content brought to you by RAPAX