-------------------------------------------------------------------------- -- joystick_pkg.vhd 03-02-21 -- by Brian Eley -- Gamecore Classic Group -- -- Joystick controller VHDL. Given a clock and a 1MHz enable signal -- the controller samples the x/y axes and buttons for two standard -- PC joysticks. The buttons and axes are sampled at roughly 30.5 HZ. -- When a sampling period starts, the button states are latched, and -- the trigger output is pulsed low. The trigger causes the monostable -- multivibrator outputs to go low for a period of time proportional -- to the joystick axes resistance (position). When the multivibrator's -- output returns to high, the value from a 1MHz counter is latched. -- -- The buttons are wired in the standard way with pull-up resistors -- and the switch contacts pulling the button signals low. The axes -- are wired up to use monostable multivibrators to create a variable -- width negative going pulse when triggered that is proportional to -- the joystick axis resistance (position). -- -- To use this package, instantiate the joystick component and connect -- all inputs (as described in the joystick appnote), making sure to -- provide the 1MHz enable signal. Then the output button states can -- be connected to LEDs, and the 8 (or less) most significant bits for -- each axis can be connected to LEDs. -- -------------------------------------------------------------------------- library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_ARITH.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; package joystick_pkg is component joystick is Generic( COUNT_WIDTH : positive := 15 -- Most likely use only upper 8 bits ); Port( clk : in std_logic; -- Clock in (>= 1MHz) enable_1MHz : in std_logic; -- Enable for effective 1Mhz clk axesIn : in std_logic_vector(3 downto 0); -- Input from monostables buttonsIn : in std_logic_vector(3 downto 0); -- Input from buttons trigger : out std_logic; -- Trigger to monostables buttonStatus : out std_logic_vector(3 downto 0); -- to CPU axis0_count : out std_logic_vector(COUNT_WIDTH - 1 downto 0); -- to CPU axis1_count : out std_logic_vector(COUNT_WIDTH - 1 downto 0); -- to CPU axis2_count : out std_logic_vector(COUNT_WIDTH - 1 downto 0); -- to CPU axis3_count : out std_logic_vector(COUNT_WIDTH - 1 downto 0) -- to CPU ); end component joystick; end package joystick_pkg; ---------------------------------------------- library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_ARITH.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; library work; use work.joystick_pkg.all; entity joystick is Generic( COUNT_WIDTH : positive := 15 -- Most likely use only upper 8 bits ); Port( clk : in std_logic; -- Clock >= 1 MHz enable_1Mhz : in std_logic; -- Enable for effective 1MHz clk axesIn : in std_logic_vector(3 downto 0); -- Input from monostables buttonsIn : in std_logic_vector(3 downto 0); -- Input from buttons trigger : out std_logic; -- Trigger to monostables buttonStatus : out std_logic_vector(3 downto 0); -- to CPU axis0_count : out std_logic_vector(COUNT_WIDTH - 1 downto 0); -- to CPU axis1_count : out std_logic_vector(COUNT_WIDTH - 1 downto 0); -- to CPU axis2_count : out std_logic_vector(COUNT_WIDTH - 1 downto 0); -- to CPU axis3_count : out std_logic_vector(COUNT_WIDTH - 1 downto 0) -- to CPU ); end joystick; architecture Behavioral of joystick is signal count : std_logic_vector (COUNT_WIDTH - 1 downto 0); signal axesLatched : std_logic_vector (3 downto 0); -- Flag bits begin -- Free running counter (no reset). Wraps at about 30.5 Hz -- Latch button states and trigger the monostables every time -- counter wraps. Latch count value when monostables return high. process (clk) begin if clk='1' and clk'event and enable_1Mhz='1' then count <= count + 1; if count=conv_std_logic_vector(0, COUNT_WIDTH) then axesLatched <= "0000"; -- Clear flags buttonStatus <= buttonsIn; -- Sample 'buttonsIn' inputs trigger <= '0'; -- Trigger monostables else trigger <= '1'; if axesLatched(0)='0' and axesIn(0)='1' then axesLatched(0) <= '1'; axis0_count <= count; end if; if axesLatched(1)='0' and axesIn(1)='1' then axesLatched(1) <= '1'; axis1_count <= count; end if; if axesLatched(2)='0' and axesIn(2)='1' then axesLatched(2) <= '1'; axis2_count <= count; end if; if axesLatched(3)='0' and axesIn(3)='1' then axesLatched(3) <= '1'; axis3_count <= count; end if; end if; end if; end process; end Behavioral;