--- /dev/null
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+use work.gen_pkg.all;
+
+entity beh_scanner_tb is
+end entity beh_scanner_tb;
+
+architecture sim of beh_scanner_tb is
+ -- system
+ signal sys_clk, sys_res_n : std_logic;
+ -- ps/2
+ signal new_data : std_logic;
+ signal data : std_logic_vector(7 downto 0);
+ -- history
+ signal s_char : hbyte;
+ signal s_take, s_done, s_backspace : std_logic;
+ -- parser
+ signal do_it : std_logic;
+ signal finished : std_logic;
+
+ signal stop : boolean := false;
+begin
+ inst : entity work.scanner(beh)
+ port map
+ (
+ sys_clk => sys_clk,
+ sys_res_n => sys_res_n,
+ -- ps/2
+ new_data => new_data,
+ data => data,
+ -- history
+ s_char => s_char,
+ s_take => s_take,
+ s_done => s_done,
+ s_backspace => s_backspace,
+ -- Parser
+ do_it => do_it,
+ finished => finished
+ );
+
+ process
+ begin
+ sys_clk <= '0';
+ wait for 15 ns;
+ sys_clk <= '1';
+ wait for 15 ns;
+ if stop = true then
+ wait;
+ end if;
+ end process;
+
+ process
+ function valid_char (x : std_logic_vector(7 downto 0); last : std_logic_vector(7 downto 0)) return boolean is
+ variable y : boolean;
+ begin
+ case x is
+ -- nur gueltig wenn davor ein numpad-mod byte gekommen ist
+ -- 0 - 4
+ when x"30" | x"31" | x"32" | x"33" | x"34" => y := last = x"e0";
+ -- 5 - 9
+ when x"35" | x"36" | x"37" | x"38" | x"39" => y := last = x"e0";
+ -- *, +, -, /
+ when x"2a" | x"2b" | x"2d" | x"2f" => y := last = x"e0";
+
+ -- immer gueltig
+ when x"20" => y := true; -- ' '
+ when x"1c" => y := true; -- enter
+ when x"0e" => y := true; -- backspace
+
+ -- alle anderen zeichen sind immer ungueltig
+ when others => y := false;
+ end case;
+ -- assert(false) report "x: " & integer'image(to_integer(unsigned(x))) & ", last: " & integer'image(to_integer(unsigned(last))) & ", result: " & boolean'image(y);
+ return y;
+ end function;
+
+ -- textio stuff
+ use std.textio.all;
+ file f : text open read_mode is "../../src/scanner.test";
+ variable l : line;
+
+ variable input : hstring;
+ variable expectedresult : hstring;
+ variable realresult : hstring;
+
+ variable checkall : boolean := true;
+ variable run_tc, run_inner : boolean := true;
+ variable i, j, k, y : natural;
+ variable last : std_logic_vector(7 downto 0);
+ begin
+ -- init & reset
+ sys_res_n <= '0';
+ new_data <= '0';
+ data <= (others => '0');
+ s_done <= '0';
+ finished <= '0';
+
+ icwait(sys_clk, 5);
+ sys_res_n <= '1';
+
+ i := 1;
+ f_loop : while not endfile(f) loop
+ data <= (others => '0');
+ realresult := (others => nul);
+
+ f1_loop : while not endfile(f) loop
+ readline (f, l);
+ input := (others => nul);
+ if (l'length <= 71) then
+ input(1 to l'length) := l.all;
+ if (input(1) = '#') then
+ next f1_loop;
+ else
+ exit f1_loop;
+ end if;
+ else
+ report "fehler in scanner.test: eingabe zu lange in testfall " & natural'image(i);
+ next f_loop;
+ end if;
+ end loop f1_loop;
+
+ f2_loop : while not endfile(f) loop
+ readline (f, l);
+ expectedresult := (others => nul);
+ if (l'length <= 71) then
+ expectedresult(1 to l'length) := l.all;
+ if (expectedresult(1) = '#') then
+ next f2_loop;
+ else
+ y := l'length;
+ exit f2_loop;
+ end if;
+ else
+ report "fehler in scanner.test: eingabe zu lange in testfall " & natural'image(i);
+ next f_loop;
+ end if;
+ end loop f2_loop;
+
+
+
+ report "testcase(" & natural'image(i) & ").input: " & input;
+ report "testcase(" & natural'image(i) & ").expectedresult: " & expectedresult;
+ i := i + 1;
+
+ icwait(sys_clk, 5);
+ run_tc := true;
+ j := 0; k := 1;
+
+ mainl : while run_tc loop
+ last := data;
+ icwait(sys_clk, 1);
+ j := j + 1;
+
+ new_data <= '1';
+ case input(j) is
+ when '$' => data <= x"1c"; -- $ (enter)
+ when '!' => data <= x"0e"; -- ! (backspace)
+ when '.' => data <= x"e0"; -- . (modifier fuer Numpad)
+ when others => data <= std_logic_vector(to_unsigned(character'pos(input(j)),8));
+ end case;
+ icwait(sys_clk, 1);
+ new_data <= '0';
+
+ -- ack'en skippen, falls es ein "spezielles" zeichen ist (steht
+ -- in abhaengigkeit zum vorherigen zeichen)
+ if(not valid_char(data, last)) then
+ next mainl;
+ end if;
+
+ -- wuenschswert waere das hier:
+ -- > wait on s_backspace, s_take, do_it;
+ -- geht aber leider nicht, weil sich die signale vllt schon
+ -- geaendert haben
+ run_inner := true;
+ main_inner : while run_inner loop
+ icwait(sys_clk, 1);
+
+ run_inner := false;
+ if s_backspace = '1' then
+ if k > 1 then
+ realresult(k) := nul;
+ k := k - 1;
+ realresult(k) := nul;
+ end if;
+ icwait(sys_clk, 1);
+ s_done <= '1';
+ wait on s_take; -- = '0'
+ icwait(sys_clk, 1);
+ s_done <= '0';
+ elsif do_it = '1' then
+ -- dauert normalweiser noch laenger (parser braucht
+ -- relativ lange)
+ icwait(sys_clk, 7);
+ finished <= '1';
+ wait on do_it; -- = '0'
+ icwait(sys_clk, 1);
+ finished <= '0';
+
+ run_tc := false;
+ elsif s_take = '1' then
+ realresult(k) := character'val(to_integer(unsigned(s_char)));
+ k := k + 1;
+
+ icwait(sys_clk, 1);
+ s_done <= '1';
+ wait on s_take; -- = '0'
+ icwait(sys_clk, 1);
+ s_done <= '0';
+ else
+ -- assert(false) report "scanner_tb: kann passieren. wenn tb haengt, dann hier auskommentieren";
+ run_inner := true;
+ end if;
+ end loop;
+ end loop;
+
+ report "realresult : " & realresult;
+ if realresult /= expectedresult then
+ checkall := false;
+ end if;
+ report "==================";
+ end loop f_loop;
+
+ if checkall then
+ report "alle testfaelle des Scanners waren erfolgreich!";
+ else
+ report "nicht alle testfaelle des Scanners waren erfolgreich!";
+ end if;
+ stop <= true;
+ wait;
+ end process;
+end architecture sim;
--- /dev/null
+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)
+ 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;