From acb693ce9970719ccc98b7368598d592491609ee Mon Sep 17 00:00:00 2001 From: Bernhard Urban Date: Sat, 15 May 2010 18:22:26 +0200 Subject: [PATCH] scanner: hoffentlich passen meinen annahmen ueber das ps/2 modul --- spec/speck.tex | 3 + src/Makefile | 2 +- src/beh_scanner_tb.do | 14 +++ src/beh_scanner_tb.vhd | 232 +++++++++++++++++++++++++++++++++++++++++ src/scanner.test | 29 ++++++ src/scanner.vhd | 135 ++++++++++++++++++++++++ 6 files changed, 414 insertions(+), 1 deletion(-) create mode 100644 src/beh_scanner_tb.do create mode 100644 src/beh_scanner_tb.vhd create mode 100644 src/scanner.test create mode 100644 src/scanner.vhd diff --git a/spec/speck.tex b/spec/speck.tex index c2e715f..07878be 100644 --- a/spec/speck.tex +++ b/spec/speck.tex @@ -620,6 +620,9 @@ behandelt??) \item aussagekr\"aftigere Fehlermeldungen. \item ALU: signal \emph{opM} fuer restberechnung \item Parser: Signale der ALU bleiben intern. +\item Scanner: fehler in der state-maschine: ein extriger uebergang von +\emph{read} auf \emph{\"ubernehmen} ist n\"otig um leerzeichen \"ubernehmen zu +k\"oennen. \end{itemize} \end{document} diff --git a/src/Makefile b/src/Makefile index 47e4fb1..19d3e36 100644 --- a/src/Makefile +++ b/src/Makefile @@ -23,7 +23,7 @@ WORK := work # o source files der module # o reihenfolge ist wichtig # o keine testbechnes hier angeben -SRCFILES := alu parser +SRCFILES := alu parser scanner # o files der packages # o keine testbechnes hier angeben diff --git a/src/beh_scanner_tb.do b/src/beh_scanner_tb.do new file mode 100644 index 0000000..2f52a4c --- /dev/null +++ b/src/beh_scanner_tb.do @@ -0,0 +1,14 @@ +#alias fuer simulation neustarten +alias rr "restart -f" + +#signale hinzufuegen +add wave inst/* + +#rauszoomen +wave zoomout 500.0 + +#simulation starten und 100ms lang laufen lassen (wird durch assert abgebrochen) +run -all + +#ganz nach links scrollen +wave seetime 0 diff --git a/src/beh_scanner_tb.vhd b/src/beh_scanner_tb.vhd new file mode 100644 index 0000000..71007f1 --- /dev/null +++ b/src/beh_scanner_tb.vhd @@ -0,0 +1,232 @@ +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; diff --git a/src/scanner.test b/src/scanner.test new file mode 100644 index 0000000..8a5035a --- /dev/null +++ b/src/scanner.test @@ -0,0 +1,29 @@ +# readme: folgende spezialzeichen werden zum testen verwendet +# $ ... Enter +# ! ... Backspace +# . ... 0xe0 (modifier fuer Numpad) +# +# testfall 1: +asdf.2.1.3$ +213 +# t2: +.2.1.4.+.5$ +214+5 +# t3: +.2 .* .2.4.5.6$ +2 * 2456 +# t4: +.2 ./ .2.4.+ $ +2 / 24+ +# t5: +.2.3.4.5 !!.1$ +2341 +# t6: +.+.-.*./$ ++-*/ +# t7: +.2.3.4!!$ +2 +# t8: (beachte dass der . vor den operatoren fehlt) +.2+-*/!! !! !!!!!.1$ +1 diff --git a/src/scanner.vhd b/src/scanner.vhd new file mode 100644 index 0000000..b4fd57a --- /dev/null +++ b/src/scanner.vhd @@ -0,0 +1,135 @@ +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; -- 2.25.1