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, SREAD, SMOD, 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) function valid_char (x : std_logic_vector(7 downto 0)) return boolean is variable y : boolean; begin case x is -- 0 - 4 when x"30" | x"31" | x"32" | x"33" | x"34" => y := true; -- 5 - 9 when x"35" | x"36" | x"37" | x"38" | x"39" => y := true; -- *, +, -, / when x"2a" | x"2b" | x"2d" | x"2f" => y := true; when others => y := false; end case; return y; end function; begin state_next <= state_int; case state_int is when SIDLE => if new_data = '1' and finished = '0' and s_done = '0' then state_next <= SREAD; end if; when SREAD => case data is when x"e0" => state_next <= SMOD; when x"0e" => state_next <= SDEL; when x"1c" => state_next <= SENTER; when x"20" => state_next <= STAKE; when others => state_next <= SIDLE; end case; when SMOD => if new_data = '1' then if valid_char(data) then state_next <= STAKE; else state_next <= SIDLE; end if; 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) begin s_char_next <= (others => '0'); s_take_next <= '0'; s_backspace_next <= '0'; do_it_next <= '0'; case state_int is when SIDLE => null; when SREAD => null; when SMOD => null; when STAKE => s_take_next <= '1'; s_char_next <= 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;