Controller_SM

--Hi,
-- Please look at the controller entity. It has the signals that are required for 
--communication between the controller and the respective modules. The state 
--machine part of the controller is attached with this mail and is called 
--Controller_SM.Vhd.
-- 
-- Kamesh Ramani
-- - Controller group
------------------------------------------------------------------
--                           Controller_SM						--
-- File Name: Controller_SM.Vhd									--
-- Author: Kamesh Ramani.										--
-- Function : This is the state machine part of the controller 
-- (The features are subject to change as the system evolves)	--
------------------------------------------------------------------

-- IEEE Library
LIBRARY ieee;
USE ieee.std_logic_1164.all;
use IEEE.std_logic_unsigned.all;

ENTITY Controller_SM IS
--Generic parameters
generic (n: integer := 6);		-- Number of players
PORT(

	-- Global System Inputs
	Clk: IN	STD_LOGIC;		-- Global Clk
	Reset: IN	STD_LOGIC;	-- Global Reset
		
	-- Inputs from Control_SK module
	SK_HP: IN STD_LOGIC;					-- Bust for House
	SK_PL: IN STD_LOGIC_VECTOR (n-1 downto 0);-- Bust for Players
	SK_Status: IN STD_LOGIC;	-- Status is ready
	SK_Game_Over: IN STD_LOGIC;	-- Current game over
	SK_Done: IN STD_LOGIC;		-- End of 100 games/player's chip gets over

	-- Outputs to the Card_Gen module
	CG_Start: OUT	STD_LOGIC;	-- Start Generating Cards in 
								-- Fixed sequence if 0
								-- Random Sequence if 1
		
	--Outputs to the House_Player module
	HP_Accept: out STD_LOGIC;		-- House Player Start

	-- Inputs from House_Player module
	HP_Hit: IN STD_LOGIC;			-- House Player Hit
	HP_Stand: IN STD_LOGIC;			-- House Player Stand

	--Outputs to the Player module
	PL_Accept: out STD_LOGIC_VECTOR (n-1 downto 0);	-- Start signals for 6 players
	
	-- Inputs from the Player modules
	PL_Hit: IN STD_LOGIC_VECTOR (n-1 downto 0);	-- Player Hit Singals for 6 players
	PL_Stand: IN STD_LOGIC_VECTOR (n-1 downto 0); -- Player Stand signals for 6 players
	PL_Status: IN STD_LOGIC_VECTOR (n-1 downto 0)	-- Player status - either in or out

	);
END Controller_SM;

architecture Control1er_SM_arch of Controller_SM is

--Signals related to Status_Mux
signal PL_Status_Mux: STD_LOGIC_VECTOR (n-1 downto 0);
signal Status_Select: STD_LOGIC;
--Signals related to Status_Reg
signal PL_Status_Sig: STD_LOGIC_VECTOR (n-1 downto 0);
signal Status_En: STD_LOGIC;

-- Controller FSM states
type STATE_TYPE is (Idle, PL_card_init, HP_Card_Init, Black_Jack, PL_Play, HP_Play, Game_Over);
signal CurrentState, NextState: STATE_TYPE;

begin

-- Continous assignments
-- Controller FSM

State_machine: process(CurrentState, Clk)
variable Cnt: integer range -1 to n-1;		-- Total number of players including idle players - a temp var
variable Two: integer range 0 to 2;		-- Counter for first two card iteration
variable Sequence: integer range 0 to 1;-- Random or fixed sequence
variable Hands : integer range -1 to 100;	-- Calcualte the total number of hands played
begin

-- Default all outputs to FALSE
Status_En <= '0'; Status_Select <= '0'; CG_Start <= '0';
CG_Start <= '0'; HP_Accept <= '0'; PL_Accept <= (others => '0');

case CurrentState is

	when Idle =>
		-- End of game if either 100 hands played or chips get over
		if ((SK_Done = '1') OR (Hands = 100))then
			NextState <= Idle;
		else
			Hands := Hands + 1;
			Status_Select <= '0';
			Status_En <= '1';
			-- Decide of what sequence to start
			if (Sequence = 0) then
				CG_Start <= '0';
				Sequence := 1;
				NextState <= PL_Card_Init;
			elsif (Sequence = 1) then
				CG_Start <= '1';
				NextState <= PL_Card_Init;
			end if;
    	end if;
	
	when PL_Card_Init =>
		-- if all players have been given cards give to house player
		if (Cnt < 0) then
			Cnt := n-1;
			NextState <= HP_Card_Init;
		elsif (Cnt < n) then
			-- if player is in
			if (PL_Status_Sig(Cnt) = '0') then
				PL_Accept(Cnt) <= '0';
				NextState <= PL_Card_Init;
			elsif (PL_Status_Sig(Cnt) = '1') then
				PL_Accept(Cnt) <= '1';
				Cnt := Cnt - 1;
				NextState <= PL_Card_Init;
			end if;
		end if;

	when HP_Card_Init =>
		-- give cards to house
		HP_Accept <= '1';
		-- give two cards initially to both house and players
		if (Two = 0) then
			NextState <= Black_Jack;
		else
			Two := Two -1;
			NextState <= PL_Card_Init;
		end if;
	
	-- when black jack dont give cards to him anymore
	when Black_Jack =>
		if (SK_Status = '1') then
			Status_Select <= '1';
			Status_En <= '1';
			NextState <= PL_Play;
		elsif (SK_Status = '0') then
			NextState <= Black_Jack;
		end if;
	
	when PL_Play =>
		-- if all players are done playing(Stand/Bust) then let HP play
		if (Cnt < 0) then
			Cnt := n-1;
			NextState <= HP_Play;
		elsif (Cnt < n) then
			-- if SK is not done with calculating status keep checking
			if (SK_Status = '0') then
				NextState <= PL_Play;
			--if the current player is out
			elsif (PL_Status_Sig(Cnt) = '0') then
				PL_Accept(Cnt) <= '0';
				Cnt := Cnt - 1;
				NextState <= PL_Play;
			elsif (PL_Status_Sig(Cnt) = '1') then
					-- if the player is not ready keep checking
					if (PL_Hit(Cnt) = '0') then
						NextState <= PL_Play;
					-- if the player hits then send him a card
					elsif (PL_Hit(Cnt) = '1') then
						PL_Accept(Cnt) <= '1';
						NextState <= PL_Play;
					end if;
					-- if the player is not yet decided then keep checking
					if (PL_Stand(Cnt) = '0') then
						NextState <= PL_Play;
					-- if the player stands move on to the next player
					elsif (PL_Stand(Cnt) = '1') then	
						PL_Accept(Cnt) <= '0';
						Cnt := Cnt - 1;
						NextState <= PL_Play;
					end if;
			end if;
		end if;
	
	when HP_Play =>
		-- if the HP is not ready keep checking
		if (HP_Hit = '0') then
			NextState <= HP_Play;
		-- if he hits give him another card
		elsif (HP_Hit = '1') then
			HP_Accept <= '1';
			NextState <= HP_Play;
		end if;
		-- if the HP stands the game is over
		if (HP_Stand = '0') then
			NextState <= HP_Play;
		elsif (HP_Stand = '1') then
			HP_Accept <= '0';
			NextState <= Game_over;
		end if;

	when Game_Over =>
		-- if the SK says game over go to the next game
		if (SK_Game_Over = '1') then
			NextState <= Idle;
		elsif (SK_Game_Over = '0') then
			NextState <= Game_Over;
		end if;

	when others =>
		NextState <= Idle;

end case;

end process;

-- To synchorinize the statemachine with Global Clk
State_Sync:process (Clk, Reset)
begin
    if (Reset='1') then
        CurrentState <= Idle;
    elsif (Clk'event and Clk = '1') then
        CurrentState <= NextState;
    end if;
end process;

-- Status Register
-- This register stores the status of the players
-- Initially the status is loaded when the palyers
-- say they are in or out
-- The status is changed again when the skore keeper
-- says they are bust or black jack.
Status_Reg: process (Clk, Reset)
begin
	if (Reset='1') then
		PL_Status_Sig <= (others => '0');
	elsif (CLK'event and CLK='1') then
		if (Status_En = '1') then
			PL_Status_Sig <= PL_Status_Mux;
		elsif (Status_En = '0') then
			NULL;
		end if;
	end if;
end process;

--Status_Mux
--This mux selects between the status signals from
-- either the Player or the Score_Keeper.
Status_Mux: process (Status_Select, PL_Status, SK_PL)
begin
	case Status_Select is
	when '0' =>
		PL_Status_Mux <= PL_Status;	--Select status from player
	when '1' =>
		PL_Status_Mux <= SK_PL;		--Select status from SK
	when others =>
		PL_Status_Mux <= (others => '0'); -- Default value
	end case;
end process;

end Control1er_SM_arch;