From 6744ad83ff2e2715a4775ee08594f47cf1633c2e Mon Sep 17 00:00:00 2001 From: Bernhard Urban Date: Sun, 9 May 2010 21:14:50 +0200 Subject: [PATCH] parser: erste gehversuche. im moment wird die eingabe einfach zurueckgegeben zur testbench --- quartus/project_tilab.tcl | 3 +- quartus/project_web.tcl | 3 +- spec/speck.tex | 11 +++ src/Makefile | 2 +- src/alu.vhd | 2 +- src/beh_alu_tb.vhd | 16 +--- src/beh_parser_tb.do | 14 +++ src/beh_parser_tb.vhd | 191 ++++++++++++++++++++++++++++++++++++++ src/gen_pkg.vhd | 6 ++ src/parser.test | 8 ++ src/parser.vhd | 139 +++++++++++++++++++++++++++ src/post_alu_tb.vhd | 1 + 12 files changed, 377 insertions(+), 19 deletions(-) create mode 100644 src/beh_parser_tb.do create mode 100644 src/beh_parser_tb.vhd create mode 100644 src/parser.test create mode 100644 src/parser.vhd diff --git a/quartus/project_tilab.tcl b/quartus/project_tilab.tcl index e303aa4..256fe65 100755 --- a/quartus/project_tilab.tcl +++ b/quartus/project_tilab.tcl @@ -32,10 +32,11 @@ if {$make_assignments} { set_global_assignment -name RESERVE_ASDO_AFTER_CONFIGURATION "AS INPUT TRI-STATED" #set_global_assignment -name TOP_LEVEL_ENTITY calc - set_global_assignment -name TOP_LEVEL_ENTITY alu + set_global_assignment -name TOP_LEVEL_ENTITY parser set_global_assignment -name VHDL_FILE ../../src/gen_pkg.vhd #set_global_assignment -name VHDL_FILE ../../src/calc.vhd set_global_assignment -name VHDL_FILE ../../src/alu.vhd + set_global_assignment -name VHDL_FILE ../../src/parser.vhd set_location_assignment PIN_N3 -to sys_clk set_location_assignment PIN_AF17 -to sys_res_n diff --git a/quartus/project_web.tcl b/quartus/project_web.tcl index 5b368b7..5d297b1 100755 --- a/quartus/project_web.tcl +++ b/quartus/project_web.tcl @@ -32,10 +32,11 @@ if {$make_assignments} { set_global_assignment -name RESERVE_ASDO_AFTER_CONFIGURATION "AS INPUT TRI-STATED" #set_global_assignment -name TOP_LEVEL_ENTITY calc - set_global_assignment -name TOP_LEVEL_ENTITY alu + set_global_assignment -name TOP_LEVEL_ENTITY parser set_global_assignment -name VHDL_FILE ../../src/gen_pkg.vhd #set_global_assignment -name VHDL_FILE ../../src/calc.vhd set_global_assignment -name VHDL_FILE ../../src/alu.vhd + set_global_assignment -name VHDL_FILE ../../src/parser.vhd set_location_assignment PIN_N3 -to sys_clk set_location_assignment PIN_AF17 -to sys_res_n diff --git a/spec/speck.tex b/spec/speck.tex index 34cba26..dbe6ed4 100644 --- a/spec/speck.tex +++ b/spec/speck.tex @@ -606,5 +606,16 @@ Ist das History Modul mit der Speicheranfrage fertig, wird das andere Modul \"ub \emph{done}-Leitung benachrichtigt. Wurde das Signal vom entsprechenden \emph{*\_\{get,take,do\}}-Signal quittiert kann der n\"achste Request verarbeitet werden. + +\newpage +\section{Erg\"anzungen der Spezifikation w\"ahrend der Implementierung} + +\begin{itemize} +\item Das Signal \emph{error} der ALU wurde in \emph{calc\_error} umbenannt, da +\emph{error} ein Schl\"usselwort in VHDL ist. +\item Die Richtungen bei den Signalen \emph{p\_read} und \emph{p\_write} wurden +jeweils im Modul Parser und History vertauscht. +\end{itemize} + \end{document} diff --git a/src/Makefile b/src/Makefile index 10cc19e..47e4fb1 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 +SRCFILES := alu parser # o files der packages # o keine testbechnes hier angeben diff --git a/src/alu.vhd b/src/alu.vhd index caff495..cdb9fdd 100644 --- a/src/alu.vhd +++ b/src/alu.vhd @@ -14,7 +14,7 @@ entity alu is op3 : out csigned; do_calc : in std_logic; calc_done : out std_logic - -- TODO: hier debug ports hinzufuegen ;) + -- TODO: calc_error : out std_logic; ); end entity alu; diff --git a/src/beh_alu_tb.vhd b/src/beh_alu_tb.vhd index f4f77c3..0da87c2 100644 --- a/src/beh_alu_tb.vhd +++ b/src/beh_alu_tb.vhd @@ -7,26 +7,12 @@ entity beh_alu_tb is end entity beh_alu_tb; architecture sim of beh_alu_tb is - component alu is - port - ( - sys_clk : in std_logic; - sys_res_n : in std_logic; - opcode : in alu_ops; - op1 : in csigned; - op2 : in csigned; - op3 : out csigned; - do_calc : in std_logic; - calc_done : out std_logic - ); - end component alu; - signal sys_clk, sys_res_n, do_calc, calc_done : std_logic; signal opcode : alu_ops; signal op1, op2, op3 : csigned; signal stop : boolean := false; begin - inst : alu + inst : entity work.alu(beh) port map ( sys_clk => sys_clk, diff --git a/src/beh_parser_tb.do b/src/beh_parser_tb.do new file mode 100644 index 0000000..2f52a4c --- /dev/null +++ b/src/beh_parser_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_parser_tb.vhd b/src/beh_parser_tb.vhd new file mode 100644 index 0000000..fc43bcf --- /dev/null +++ b/src/beh_parser_tb.vhd @@ -0,0 +1,191 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; +use work.gen_pkg.all; + +entity beh_parser_tb is +end entity beh_parser_tb; + +architecture sim of beh_parser_tb is + -- system + signal sys_clk, sys_res_n : std_logic; + -- history + signal p_rw, p_rget, p_rdone, p_wtake, p_wdone, p_finished : std_logic; + signal p_read, p_write : hbyte; + signal p_spalte : hspalte; + + -- alu + signal opcode : alu_ops; + signal op1, op2, op3 : csigned; + signal do_calc, calc_done : std_logic; + + --scanner + signal do_it : std_logic; + signal finished : std_logic; + + signal stop : boolean := false; +begin + inst : entity work.parser(beh) + port map + ( + sys_clk => sys_clk, + sys_res_n => sys_res_n, + p_rw => p_rw, + p_spalte => p_spalte, + p_rget => p_rget, + p_rdone => p_rdone, + p_read => p_read, + p_wtake => p_wtake, + p_wdone => p_wdone, + p_write => p_write, + p_finished => p_finished, + -- ALU + opcode => opcode, + op1 => op1, + op2 => op2, + op3 => op3, + do_calc => do_calc, + calc_done => calc_done, + -- TODO: calc_error : in std_logic; + -- Scanner + do_it => do_it, + finished => finished + ); + + instalu : entity work.alu(beh) + port map + ( + sys_clk => sys_clk, + sys_res_n => sys_res_n, + do_calc => do_calc, + calc_done => calc_done, + op1 => op1, + op2 => op2, + op3 => op3, + opcode => opcode + ); + + 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 + -- textio stuff + use std.textio.all; + file f : text open read_mode is "../../src/parser.test"; + variable l : line; + + variable input : hstring; + variable expectedresult : hstring; + variable realresult : hstring; + + variable checkall : boolean := true; + variable run_tc : boolean := true; + variable i, j, k : natural; + begin + -- init & reset + sys_res_n <= '0'; + p_rdone <= '0'; + p_wdone <= '0'; + p_read <= (others => '0'); + do_it <= '0'; + + icwait(sys_clk, 5); + sys_res_n <= '1'; + + i := 1; + f_loop : while not endfile(f) loop + realresult := (others => character'val(0)); + + f1_loop : while not endfile(f) loop + readline (f, l); + input := (others => character'val(0)); + if (l'length <= 72) 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 parser.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 => character'val(0)); + if (l'length <= 72) then + expectedresult(1 to l'length) := l.all; + if (expectedresult(1) = '#') then + next f2_loop; + else + exit f2_loop; + end if; + else + report "fehler in parser.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); + do_it <= '1'; + run_tc := true; + j := 1; k := 1; + + while run_tc loop + wait on p_rget, p_wtake, p_finished, finished; + icwait(sys_clk, 2); + + if p_rget = '1' then + p_read <= hbyte( to_unsigned(character'pos(input(j)),8) ); + p_rdone <= '1'; + j := j + 1; + end if; + if p_rget = '0' then + p_rdone <= '0'; + end if; + + if p_wtake = '1' then + realresult(k) := character'val(to_integer(unsigned(p_write))); + p_wdone <= '1'; + k := k + 1; + end if; + if p_wtake = '0' then + p_wdone <= '0'; + end if; + + if p_finished = '1' or finished = '1' then + run_tc := false; + end if; + end loop; + + do_it <= '0'; + report "realresult: " & realresult; + if realresult /= expectedresult then + checkall := false; + end if; + report "=================="; + end loop f_loop; + + if checkall then + report "alle testfaelle des Parser waren erfolgreich!"; + else + report "nicht alle testfaelle des Parsers waren erfolgreich!"; + end if; + stop <= true; + wait; + end process; +end architecture sim; diff --git a/src/gen_pkg.vhd b/src/gen_pkg.vhd index 9eabeb0..e5c692e 100644 --- a/src/gen_pkg.vhd +++ b/src/gen_pkg.vhd @@ -15,6 +15,12 @@ package gen_pkg is subtype csigned is signed((CBITS-1) downto 0); --TODO: bei CBITS-1 gibts einen overflow :/ subtype cinteger is integer range -(2**(CBITS-2)) to ((2**(CBITS-2))-1); + + subtype hspalte is std_logic_vector(6 downto 0); + subtype hzeile is std_logic_vector(4 downto 0); + subtype hbyte is std_logic_vector(7 downto 0); + subtype hstring is string(1 to 71); + function find_msb(a : csigned) return natural; procedure icwait(signal clk_i : IN std_logic; cycles: Natural); end package gen_pkg; diff --git a/src/parser.test b/src/parser.test new file mode 100644 index 0000000..c3501c7 --- /dev/null +++ b/src/parser.test @@ -0,0 +1,8 @@ +# beachte, eingabe muss schon "scanner"-gecheckt sein +# +# testfall 1: +58243 +58243 +# testfall 2: +12345 +12345 diff --git a/src/parser.vhd b/src/parser.vhd new file mode 100644 index 0000000..6e41837 --- /dev/null +++ b/src/parser.vhd @@ -0,0 +1,139 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; +use work.gen_pkg.all; + +entity parser is + port + ( + sys_clk : in std_logic; + sys_res_n : in std_logic; + -- History + p_rw : out std_logic; + p_spalte : out hspalte; + p_rget : out std_logic; + p_rdone : in std_logic; + p_read : in hbyte; + p_wtake : out std_logic; + p_wdone : in std_logic; + p_write : out hbyte; + p_finished : out std_logic; + -- ALU + opcode : out alu_ops; + op1 : out csigned; + op2 : out csigned; + op3 : in csigned; + do_calc : out std_logic; + calc_done : in std_logic; + -- TODO: calc_error : in std_logic; + -- Scanner + do_it : in std_logic; + finished : out std_logic + ); +end entity parser; + +architecture beh of parser is + type PARSER_STATE is (SIDLE, SREAD_CHAR1, SREAD_CHAR2, SWRITE_CHAR); + signal state_int, state_next : PARSER_STATE; + signal z_int, z_next : csigned; + signal rbyte_int, rbyte_next : hbyte; + signal p_write_int, p_write_next : hbyte; + signal p_rget_int, p_rget_next : std_logic; + signal p_wtake_int, p_wtake_next : std_logic; + signal p_finished_int, p_finished_next : std_logic; +begin + p_write <= p_write_int; + p_rget <= p_rget_int; + p_wtake <= p_wtake_int; + p_finished <= p_finished_int; + + process(sys_clk, sys_res_n) + begin + if sys_res_n = '0' then + state_int <= SIDLE; + z_int <= (others => '0'); + rbyte_int <= (others => '0'); + -- out ports + p_rw <= '0'; + p_spalte <= (others => '0'); + p_rget_int <= '0'; + p_write_int <= (others => '0'); + p_wtake_int <= '0'; + p_finished_int <= '0'; + opcode <= ALU_NOP; + op1 <= (others => '0'); + op2 <= (others => '0'); + do_calc <= '0'; + finished <= '0'; + elsif rising_edge(sys_clk) then + -- internal + state_int <= state_next; + z_int <= z_next; + rbyte_int <= rbyte_next; + -- out ports + p_rget_int <= p_rget_next; + p_write_int <= p_write_next; + p_wtake_int <= p_wtake_next; + p_finished_int <= p_finished_next; + end if; + end process; + + -- next state + process(state_int, do_it, p_rdone, p_wdone, p_read) + begin + state_next <= state_int; + + case state_int is + when SIDLE => + if do_it = '1' then + state_next <= SREAD_CHAR1; + end if; + when SREAD_CHAR1 => + if p_rdone = '1' then + state_next <= SREAD_CHAR2; + end if; + when SREAD_CHAR2 => + if p_wdone = '1' then + state_next <= SWRITE_CHAR; + end if; + when SWRITE_CHAR => + if rbyte_int = hbyte(to_unsigned(character'pos(character'val(0)), 8)) then + if do_it = '0' then + state_next <= SIDLE; + end if; + else + state_next <= SREAD_CHAR1; + end if; + end case; + end process; + + process(state_int, p_read, p_write_int, z_int, rbyte_int, p_rget_int) + begin + -- internal + z_next <= z_int; + rbyte_next <= rbyte_int; + -- signals + p_rget_next <= '0'; + p_write_next <= p_write_int; + p_wtake_next <= '0'; + p_finished_next <= '0'; + + case state_int is + when SIDLE => + z_next <= (others => '0'); + rbyte_next <= (others => '0'); + p_write_next <= (others => '0'); + when SREAD_CHAR1 => + p_rget_next <= '1'; + p_write_next <= (others => '0'); + when SREAD_CHAR2 => + rbyte_next <= p_read; + p_wtake_next <= '1'; + p_write_next <= p_read; + when SWRITE_CHAR => + if rbyte_int = hbyte(to_unsigned(character'pos(character'val(0)), 8)) then + p_finished_next <= '1'; + end if; + end case; + end process; +end architecture beh; diff --git a/src/post_alu_tb.vhd b/src/post_alu_tb.vhd index a91426a..5c05298 100644 --- a/src/post_alu_tb.vhd +++ b/src/post_alu_tb.vhd @@ -7,6 +7,7 @@ entity post_alu_tb is end entity post_alu_tb; architecture sim of post_alu_tb is + -- TODO: braucht man hier wirklich eine andere entity definition? component alu is port ( -- 2.25.1