library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; use work.gen_pkg.all; entity scanner is port ( sys_clk : in std_logic; sys_res_n : in std_logic; -- PS/2 new_data : in std_logic; data : in std_logic_vector(7 downto 0); -- History s_char : out hbyte; s_take : out std_logic; s_done : in std_logic; s_backspace : out std_logic; -- Parser do_it : out std_logic; finished : in std_logic ); end entity scanner; architecture beh of scanner is type SCANNER_STATE is (SIDLE, SIGNORE_NEXT, SREAD_NEXT, STAKE, SDEL, SENTER); signal state_int, state_next : SCANNER_STATE; signal s_char_int, s_char_next : hbyte; signal s_take_int, s_take_next : std_logic; signal s_backspace_int, s_backspace_next : std_logic; signal do_it_int, do_it_next : std_logic; begin s_char <= s_char_int; s_take <= s_take_int; s_backspace <= s_backspace_int; do_it <= do_it_int; process(sys_clk, sys_res_n) begin if sys_res_n = '0' then -- internal state_int <= SIDLE; -- out s_char_int <= (others => '0'); s_take_int <= '0'; s_backspace_int <= '0'; do_it_int <= '0'; elsif rising_edge(sys_clk) then -- internal state_int <= state_next; -- out s_char_int <= s_char_next; s_take_int <= s_take_next; s_backspace_int <= s_backspace_next; do_it_int <= do_it_next; end if; end process; -- next state process(state_int, new_data, data, finished, s_done) begin state_next <= state_int; case state_int is when SIDLE => if new_data = '1' then case data is when x"f0" => state_next <= SIGNORE_NEXT; when x"e0" => state_next <= SREAD_NEXT; when SC_BKSP => state_next <= SDEL; when SC_ENTER => state_next <= SENTER; when SC_KP_0 | SC_KP_1 | SC_KP_2 | SC_KP_3 | SC_KP_4 | SC_KP_5 | SC_KP_6 | SC_KP_7 | SC_KP_8 | SC_KP_9 | SC_0 | SC_1 | SC_2 | SC_3 | SC_4 | SC_5 | SC_6 | SC_7 | SC_8 | SC_9 | SC_PLUS | SC_KP_PLUS | SC_KP_MINUS | SC_KP_MUL | SC_SPACE => state_next <= STAKE; when others => state_next <= SIDLE; end case; end if; when SIGNORE_NEXT => if new_data = '1' then state_next <= SIDLE; end if; when SREAD_NEXT => if new_data = '1' then case data is when x"f0" => state_next <= SIGNORE_NEXT; when SC_ENTER => state_next <= SENTER; when SC_KP_DIV => state_next <= STAKE; when others => state_next <= SIDLE; end case; end if; when STAKE | SDEL=> if s_done = '1' then state_next <= SIDLE; end if; when SENTER => if finished = '1' then state_next <= SIDLE; end if; end case; end process; -- out process(state_int, data, s_char_int, new_data) function sc2ascii (x : hbyte) return hbyte is variable y : hbyte; begin case x is when SC_KP_0 | SC_0 => y := x"30"; when SC_KP_1 | SC_1 => y := x"31"; when SC_KP_2 | SC_2 => y := x"32"; when SC_KP_3 | SC_3 => y := x"33"; when SC_KP_4 | SC_4 => y := x"34"; when SC_KP_5 | SC_5 => y := x"35"; when SC_KP_6 | SC_6 => y := x"36"; when SC_KP_7 | SC_7 => y := x"37"; when SC_KP_8 | SC_8 => y := x"38"; when SC_KP_9 | SC_9 => y := x"39"; when SC_KP_PLUS | SC_PLUS => y := x"2b"; when SC_KP_MINUS => y := x"2d"; when SC_KP_MUL => y := x"2a"; when SC_KP_DIV => y := x"2f"; when SC_SPACE => y := x"20"; when others => y := x"41"; end case; return y; end function; begin s_char_next <= s_char_int; s_take_next <= '0'; s_backspace_next <= '0'; do_it_next <= '0'; case state_int is when SIDLE => null; when SIGNORE_NEXT => null; when SREAD_NEXT => null; when STAKE => s_take_next <= '1'; s_char_next <= sc2ascii(hbyte(data)); when SDEL => s_take_next <= '1'; s_backspace_next <= '1'; when SENTER => do_it_next <= '1'; end case; end process; end architecture beh;