------------------------------------------------------------------
-- 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) --
-- Created: --
-- Last Updated on: 2/11/03 --
------------------------------------------------------------------
-- 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_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 n players
-- Inputs from the Player modules
PL_Hit: IN STD_LOGIC_VECTOR (n-1 downto 0); -- Player Hit Singals for n players
PL_Stand: IN STD_LOGIC_VECTOR (n-1 downto 0); -- Player Stand signals for n players
PL_Status: IN STD_LOGIC_VECTOR (n-1 downto 0) -- Player status - either in or out
--Debug
);
END Controller_SM;
architecture Control1er_SM_arch of Controller_SM is
signal Sequence:STD_LOGIC;-- Random or fixed sequence
--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_Reg: STD_LOGIC_VECTOR (n-1 downto 0);
signal Status_En: STD_LOGIC;
--Signals related to PL_Status_Mux
signal PL_Status_Sig : STD_LOGIC;
--Signals related to PL_Hit_Mux
signal PL_Hit_Sig : STD_LOGIC;
--Signals related to PL_Stand_Mux
signal PL_Stand_Sig : STD_LOGIC;
--Signals related to Counter Hands
-- Seven bits long since 100 in decimal needs 7 bits in Bin
signal Hands, Hands_Sig: STD_LOGIC_VECTOR(6 downto 0);
signal Hands_Inc, Hands_Clr: STD_LOGIC;
--Signals related to Counter_Cnt
-- Three bits long since n here is assumed 6
--n Dep
signal Cnt, Count: STD_LOGIC_VECTOR (3 downto 0);
signal Cnt_Inc, Cnt_Clr: STD_LOGIC;
--Signals related to Counter_Two
signal Two, Two_Cnt: STD_LOGIC_VECTOR(1 downto 0);
signal Two_Inc, Two_Clr: STD_LOGIC;
--Signals related to PL_Accept_Mux
-- Three bits long since n here is assumed 6
--n Dep
signal PL_Accept_Select: STD_LOGIC_VECTOR (3 downto 0);
-- 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;
--Component declaration of Player_Mux
--n Dep
COMPONENT Player_Mux
PORT(
PL_Value : OUT STD_LOGIC;
PL_Vector: IN STD_LOGIC_VECTOR (5 downto 0);
PL_Select: IN STD_LOGIC_VECTOR (3 downto 0)
);
END COMPONENT;
begin
--Player_Mux chooses the Status of the current player
--Component instantiation of Player_Mux
PL_Stat_Mux: Player_Mux
PORT MAP (
PL_Value => PL_Status_Sig,
PL_Vector => PL_Status_Reg,
PL_Select => Cnt
);
--PL_Hit_Mux chooses the Hit signal of the current player
--Component instantiation of Player_Mux
PL_Hit_Mux: Player_Mux
PORT MAP (
PL_Value => PL_Hit_Sig,
PL_Vector => PL_Hit,
PL_Select => Cnt
);
--PL_Hit_Mux chooses the Stand signal of the current player
--Component instantiation of Player_Mux
PL_Stand_Mux: Player_Mux
PORT MAP (
PL_Value => PL_Stand_Sig,
PL_Vector => PL_Stand,
PL_Select => Cnt
);
-- Debug
-- Controller FSM
State_machine: process(CurrentState, Hands, SK_Done, Cnt, PL_Status_Sig, Two_Cnt, SK_Status, Sequence, PL_Status_Sig, PL_Stand_Sig,
PL_Hit_Sig)
begin
-- Default all outputs to FALSE
CG_Start <= '0';Status_EN <= '0';
Cnt_Inc <= '0'; Cnt_Clr <= '0';
Two_Inc <= '0'; Two_Clr <= '0';
Hands_Inc <= '0'; Hands_Clr <= '0';
HP_Accept <= '0'; Status_Select <= '0';
case CurrentState is
when Idle =>
-- End of game if either 100 hands played or chips get over
if (Hands > X"64") then
NextState <= Idle;
elsif (Hands <= X"64") then
if (SK_Done = '1')then
Hands_Clr <= '1';
NextState <= Idle;
elsif (SK_Done = '0')then
Status_Select <= '0';
Status_En <= '1';
Hands_Inc <= '1';
NextState <= PL_Card_Init;
-- Decide of what sequence to start
if (Sequence = '0') then
CG_Start <= '0';
else
CG_Start <= '1';
end if;
end if;
end if;
when PL_Card_Init =>
if (Cnt <= X"6") then --n Dep
-- if player is in
if (PL_Status_Sig = '0') then
PL_Accept_Select <= X"7";
elsif (PL_Status_Sig = '1') then
-- Give card to player
PL_Accept_Select <= Cnt;
end if;
if (Cnt = X"6") then --n Dep
Cnt_Clr <= '1';
NextState <= HP_Card_Init;
else
Cnt_Inc <= '1';
NextState <= PL_Card_Init;
end if;
elsif (Cnt > X"6") then --n Dep
Cnt_Clr <= '1';
end if;
when HP_Card_Init =>
PL_Accept_Select <= X"7";
-- give cards to house
HP_Accept <= '1';
-- give two cards initially to both house and players
if (Two_Cnt >= "01") then
Two_clr <= '1';
NextState <= Black_Jack;
elsif (Two_Cnt < "01") then
Two_Inc <= '1';
NextState <= PL_Card_Init;
end if;
-- when black jack dont give cards to that player anymore
when Black_Jack =>
case (SK_Status) is
when '1' =>
Status_Select <= '1';
Status_En <= '1';
NextState <= PL_Play;
when '0'=>
NextState <= Black_Jack;
when others =>
NextState <= Idle;
end case;
when PL_Play =>
if (Cnt <= X"6") then --n Dep
-- 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 = '0') then
PL_Accept_Select <= X"7";
if (Cnt = X"6") then --n Dep
Cnt_Clr <= '1';
NextState <= HP_Play;
else
Cnt_Inc <= '1';
NextState <= PL_Play;
end if;
elsif (PL_Status_Sig = '1') then
-- if the player is not ready keep checking
if ((PL_Hit_Sig = '0') AND (PL_Stand_Sig = '0')) then
NextState <= PL_Play;
-- if the player hits then send him a card
elsif (PL_Hit_Sig = '1') then
PL_Accept_Select <= Cnt;
NextState <= PL_Play;
-- if the player stands, move on to the next player
elsif (PL_Stand_Sig = '1') then
PL_Accept_Select <= X"7";
if (Cnt = X"6") then --n Dep
Cnt_Clr <= '1';
NextState <= HP_Play;
else
Cnt_Inc <= '1';
NextState <= PL_Play;
end if;
end if;
end if;
elsif (Cnt > X"6") then --n Dep
Cnt_Clr <= '1';
NextState <= Idle;
end if;
when HP_Play =>
-- if the HP is not ready keep checking
if ((HP_Hit = '0') AND (HP_Stand = '0')) then
NextState <= HP_Play;
-- if he hits give him another card
elsif (HP_Hit = '1') then
HP_Accept <= '1';
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
Sequence <= '1';
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;
-- Counter for Hands
Counter_Hands:process (Clk, Reset)
begin
if (Reset='1') then
Hands_Sig <= "0000000";
elsif (Clk'event and Clk = '1') then
if (Hands_Clr = '1') then
Hands_Sig <= "0000000";
elsif (Hands_Inc = '1') then
Hands_Sig <= Hands_Sig + "0000001";
end if;
end if;
end process;
Hands <= Hands_Sig;
-- Counter for player's turn
Counter_Cnt:process (Clk, Reset)
begin
if (Reset='1') then
Count <= X"0";
elsif (Clk'event and Clk = '1') then
if (Cnt_Clr = '1') then
Count <= X"0";
elsif (Cnt_Inc = '1') then
Count <= Count + X"1";
end if;
end if;
end process;
Cnt <= Count;
--Counter for giving cards twice initially
Counter_Two:process (Clk, Reset)
begin
if (Reset='1') then
Two <= "00";
elsif (Clk'event and Clk = '1') then
if (Two_Clr = '1') then
Two <= "00";
elsif (Two_Inc = '1') then
Two <= Two + "01";
end if;
end if;
end process;
Two_Cnt <= Two;
-- 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, Status_En, PL_Status_Mux)
begin
if (Reset='1') then
PL_Status_Reg <= (others => '0');
elsif (CLK'event and CLK='1') then
if (Status_En = '1') then
PL_Status_Reg <= 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;
--PL_Accept_Mux
--This mux selects the given player's Accept signal
PL_Accept_Mux: process (PL_Accept_Select)
begin
--n Dep
case PL_Accept_Select is
when X"1" =>
PL_Accept <= "000001";
when X"2" =>
PL_Accept <= "000010";
when X"3" =>
PL_Accept <= "000100";
when X"4" =>
PL_Accept <= "001000";
when X"5" =>
PL_Accept <= "010000";
when X"6" =>
PL_Accept <= "100000";
when others =>
PL_Accept <= (others => '0'); -- Default value
end case;
end process;
end Control1er_SM_arch;