--
--
-- Keyboard module (provides exteranl inputs through PS2 Keyboard)
-- 

Library altera,IEEE,lpm;
use altera.maxplus2.all;
use IEEE.STD_LOGIC_1164.all;
USE lpm.lpm_components.ALL;
use IEEE.STD_LOGIC_ARITH.all;
use IEEE.STD_LOGIC_signed.all;


entity Keyboard is

  Generic(DATA_LENGTH : integer := 9);

       port( reset : in std_Logic; 
             Keyboard_DATA, Keyboard_CLOCK : in std_logic;
			 clock : in std_Logic;
             parity_D,stopbit_D : out std_logic;
			 key_stroke : out std_logic;
             k_data_D : out std_logic_vector(7 downto 0);
  			 key_ascii_D : out std_logic_vector(7 downto 0));
end Keyboard;



--
-- Keyboard architecture
--

architecture behavioral of Keyboard is

	signal k_data : std_logic_vector(DATA_LENGTH downto 0);
    signal key_ascii : std_logic_vector(5 downto 0);
    signal receive_key : std_logic := '0';
	signal start,stop_getkey : std_logic := '0';
    signal cnt : std_logic_vector(3 downto 0) := "0000";
    signal filter : std_logic_vector(7 downto 0);
    signal keyboard_clk_filt : std_logic; 
    signal parityok : std_logic := '0';
    signal shift_key : std_logic := '0';

  -- Function Defined to Check the parity of the input signal.
  -- If the parity is correct, a '1' is returned else it is a '0';	       
    function paritycheck(p_data : in std_logic_vector(8 downto 0)) return std_logic is
          variable Result: std_logic :='0'; 
    begin
 
      xor_loop:
      FOR N IN p_data'range LOOP
         Result := Result xor p_data(N);
      END LOOP xor_loop;
      return Result;
    end function paritycheck;       



begin

process (start, clock, cnt)
variable cntclk : std_logic_vector(14 downto 0);
begin
wait until clock'event and clock = '1';
if start = '0' or cnt = "0000" then 
   cntclk := "000000000000000";
   stop_getkey <= '0';
else
   cntclk := cntclk + 1;
   if cntclk = "100111010000100" then
      stop_getkey <= '1';
   end if;
end if;


end process;



process
begin
  wait until clock'event and clock='0';
  filter(6 downto 0) <= filter(7 downto 1);
  filter(7) <= keyboard_clock;
  if filter = "00000000" then keyboard_clk_filt <= '0';
  else keyboard_clk_filt <= '1';
  end if;
end process;


process
variable cnter : std_logic_vector(3 downto 0) := "0000";

begin
  wait until keyboard_clk_filt'event and keyboard_clk_filt = '0';
  
  if keyboard_data ='0' and start = '0' then --(start = '0' or stop_getkey = '1') then
    start <= '1';
    cnter := "0000";
    k_data <= "0000000000";
  else 
    if start = '1' then
        cnter := cnter + 1;

    case cnter(3 downto 0) is
     when "0001" => k_data(0) <= Keyboard_DATA;
     when "0010" => k_data(1) <= Keyboard_DATA;
     when "0011" => k_data(2) <= Keyboard_DATA;
     when "0100" => k_data(3) <= Keyboard_DATA;
     when "0101" => k_data(4) <= Keyboard_DATA;
     when "0110" => k_data(5) <= Keyboard_DATA;
     when "0111" => k_data(6) <= Keyboard_DATA;
     when "1000" => k_data(7) <= Keyboard_DATA;
     when "1001" => k_data(8) <= Keyboard_DATA;
     when others => k_data(9) <= Keyboard_DATA;
           start <= '0';
           receive_key <= not receive_key;	  
    end case;
   
  end if;
  end if;		
  cnt <= cnter;
end process;  -- keyboard clock process

scancode_rom: lpm_rom
      GENERIC MAP ( lpm_widthad => 8,
        lpm_numwords => "256",
        lpm_outdata => "UNREGISTERED",
        lpm_address_control => "UNREGISTERED",
-- Reads in mif file for character generator data 
         lpm_file => "scancode.mif",
         lpm_width => 6)
      PORT MAP ( --inclock => clock,
				 address => k_data(7 downto 0), 
                 q => key_ascii);


parityok <= paritycheck(k_data(8 downto 0));

process
  variable tmp_stroke, cur_key, break_code : std_logic := '0';
begin
  wait until clock'event and clock ='1';
  if reset = '1' then
    key_ascii_D <= "00100000";
  else

    k_data_d <= k_data(7 downto 0);

	if cur_key /= receive_key then
	    cur_key := receive_key;
		parity_D <= parityok;
        stopbit_D <= k_data(9);
    	
           if break_code = '0' then
			if k_data(7 downto 0) = "11110000" then
				break_code := '1';
			else
				--do we have a valid key?
				--if k_data(9) = '1' and parityok = '1' then
				-- stop bit and parity check out ok

			    -- the return, backspace, and shift keys all return key_ascii value
                -- of "111111" since these characters are not mapped directly to the
 			    -- tiny character generator ROM.  Therefore, we assume (by default) that
			    -- any key_ascii value not "111111" is a valid mapped key.
                   if key_ascii /= "111111" then
      				 key_ascii_D(7 downto 0) <= "00" & key_ascii(5 downto 0);
				     tmp_stroke := not tmp_stroke;
   				     key_stroke <= tmp_stroke; 
   		           elsif k_data(7 downto 0) = "01011010" or  -- return
                         k_data(7 downto 0) = "01100110" then  --backspace
                       key_ascii_D(7 downto 0) <= k_data(6 downto 5) & "000000"; 
				       tmp_stroke := not tmp_stroke;
   				       key_stroke <= tmp_stroke;
                   end if;
  

                   if k_data(7 downto 0) = "00010010" or --Left Shift
		              k_data(7 downto 0) = "01011001" then  -- Right Shift
                     shift_key <= '1';
                   end if;

    			--end if; -- if k_data(9)
  			end if; -- if k_data(7 downto 0)
	  else
			break_code := '0';

		    -- turn off shift during the break portion
			 if --k_data(9) = '1' and parityok = '1' and
		       (k_data(7 downto 0) = "00010010" or
		        k_data(7 downto 0) = "01011001") then
               shift_key <= '0';
            end if;

  end if; -- if break_code
  end if; -- if cur_key
end if; -- if reset
end process;

end behavioral;

<div align="center"><br /><script type="text/javascript"><!--
google_ad_client = "pub-7293844627074885";
//468x60, Created at 07. 11. 25
google_ad_slot = "8619794253";
google_ad_width = 468;
google_ad_height = 60;
//--></script>
<script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script><br />&nbsp;</div>