library IEEE; use IEEE.std_logic_1164.all; use IEEE.STD_LOGIC_ARITH.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; entity PS2Manager is port( clk,clk12khz,reset:in std_logic; --one clk for the internal operation of the device and another to output on PS2C out_message,finished:in std_logic; --if a new message needs to be sent to the host then out_message='1' in_message:out std_logic; --flag the new recieved message data_out:in std_logic_vector(7 downto 0); --data to be sent to Host data_in:out std_logic_vector(7 downto 0); -- data to recieve by device PS2D,PS2C:inout std_logic ); end entity PS2Manager; architecture Behavioral of PS2Manager is type state_type is(Start,Idle,CommInhib,Check50Clk,Give11clk,Request_to_Recieve, Give12clk,Acknowledge); signal state:state_type; signal ps2_clk_h, --controlls the state of the bidirectional clock line ps2_data_h, --controlls the state of the bidirectional data line data_parity, --extracts from the ROM the parity correspondig to the data to be sent count_ack, --Counter for the acknowledge bit; ack, --flag to start the count_ack counter byte_sent, --flag that the byte was sent to the device output_clk, --flag to enable clock outputing on the ps2 port load_data, --flag to load the data in the data i/o register shift_byte, --flag when data is coming in and needs to be shifted download_data --flag to enable data extraction from the recieved byte :std_logic; signal PS2data:std_logic_vector(11 downto 0); signal count50us:std_logic_vector(4 downto 0); signal Byte:std_logic_vector(10 downto 0); signal count_eleven:std_logic_vector(3 downto 0); signal byte_count:std_logic_vector(1 downto 0); constant const50us:std_logic_vector(9 downto 0):="1001110001"; constant const_eleven:std_logic_vector(3 downto 0):="1011"; type ROM is array(0 to 255) of std_logic; constant parityrom : ROM := ( '1','0','0','1','0','1','1','0', '0','1','1','0','1','0','0','1', '0','1','1','0','1','0','0','1', '1','0','0','1','0','1','1','0', '0','1','1','0','1','0','0','1', '1','0','0','1','0','1','1','0', '1','0','0','1','0','1','1','0', '0','1','1','0','1','0','0','1', '0','1','1','0','1','0','0','1', '1','0','0','1','0','1','1','0', '1','0','0','1','0','1','1','0', '0','1','1','0','1','0','0','1', '1','0','0','1','0','1','1','0', '0','1','1','0','1','0','0','1', '0','1','1','0','1','0','0','1', '1','0','0','1','0','1','1','0', '0','1','1','0','1','0','0','1', '1','0','0','1','0','1','1','0', '1','0','0','1','0','1','1','0', '0','1','1','0','1','0','0','1', '1','0','0','1','0','1','1','0', '0','1','1','0','1','0','0','1', '0','1','1','0','1','0','0','1', '1','0','0','1','0','1','1','0', '1','0','0','1','0','1','1','0', '0','1','1','0','1','0','0','1', '0','1','1','0','1','0','0','1', '1','0','0','1','0','1','1','0', '0','1','1','0','1','0','0','1', '1','0','0','1','0','1','1','0', '1','0','0','1','0','1','1','0', '0','1','1','0','1','0','0','1' ); begin PS2C<= 'Z' when (clk12khz='1' and output_clk='1') else'0'; PS2D <= 'Z' when ps2_data_h = '1' else '0'; ps2_clk_h<=clk12khz when output_clk='1' else'0'; data_parity <= parityrom(conv_integer(data_out)); manage_fsm: process(clk,PS2C,PS2D,reset,state) begin if (reset='1') then state<=Start; elsif (rising_edge(clk)) then case state is when Start=> ps2_clk_h<='1'; ps2_data_h<='1'; if (PS2D='1' and PS2C='1') then state<=Idle; elsif(PS2D='0' and PS2C='1')then state<=Request_to_Recieve; else state<=Start; end if; when Idle=> if(out_message='1') then load_data<='1'; state<=Give11clk; else load_data<='0'; state<=Start; end if; when Give11clk=> if(count_eleven=const_eleven) then output_clk<='0'; byte_sent<='1'; state<=Idle; else byte_sent<='0'; output_clk<='1'; ps2_data_h<=Byte(0); state<=Give11clk; end if; when Request_to_Recieve=> if(PS2D='0' and PS2C='1') then state<=Give12clk; else state<=Request_to_Recieve; end if; when Give12clk=>if(count_eleven=const_eleven) then output_clk<='0'; download_data<='1'; shift_byte<='0'; state<=Acknowledge; else download_data<='0'; output_clk<='1'; shift_byte<='1'; state<=Give12clk; end if; when Acknowledge=> if(count_ack='1') then ack<='0'; state<=Start; else output_clk<='1'; ack<='1'; ps2_data_h<='0'; state<=Acknowledge; end if; when others=> state<=Start; end case; end if; end process manage_fsm; upload_download:process(data_out,clk,Byte,finished) begin -- shifts frame with one bit to right when shift_frame is acitve -- and loads data into frame from tx_data then load_tx_data is high if(rising_edge(clk)) then if(load_data = '1') then Byte(8 downto 1) <= data_out; -- byte to send Byte(0) <= '0'; -- start bit Byte(10) <= '1'; -- stop bit Byte(9) <= data_parity; elsif(shift_byte='1')then Byte(9 downto 0) <= Byte(10 downto 1); -- shift in from the ps2_data line Byte(10) <= PS2D; end if; if(download_data='1')then data_in<=Byte(8 downto 1); in_message<='1'; end if; if (finished='1') then data_in<=(others=>'0'); in_message<='1'; else in_message<='0'; end if;end if; end process upload_download; delay_counters:process(clk12khz) begin if rising_edge(clk12khz)then if ( output_clk='1') then count_eleven<=count_eleven+1; else count_eleven<=(others=>'0'); end if; if ack='1' then count_ack<='1'; end if; end if; end process delay_counters; end architecture Behavioral;