use work.gen_pkg.all;
entity parser is
- port
- (
+ 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_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;
- opM : in csigned;
- do_calc : out std_logic;
- calc_done : in std_logic;
- 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_NEWNUMBER, SREAD_SPACE1_2,
- SREAD_SPACE1_3, SREAD_SPACE2, SREAD_SPACE3, SREAD_OP1, SREAD_OP2,
- SREAD_SIGN1, SREAD_NEXTBYTE, SREAD_CALCNUMBER1, SREAD_CALCNUMBER2, SCALC_1,
- SCALC_14, SCALC_15, SCALC_2, SWRITE_CHAR0, SWRITE_CHAR1, SWRITE_CHAR2,
- SWRITE_SIGN1, SWRITE_SIGN2, SDONE, SERROR1, SERROR2);
+ type PARSER_STATE is (SIDLE, SREAD_NEWNUMBER, SREAD_SPACE_GET,
+ SREAD_SPACE_GET_SIGN, SREAD_SPACE_PROC, SREAD_SPACE_PROC_SIGN, SREAD_OP1, SREAD_OP2,
+ SREAD_SIGN, SREAD_NEXTBYTE, SREAD_CALCNUMBER1, SREAD_CALCNUMBER2, SCALC_1,
+ SCALC_14, SCALC_15, SCALC_2, SWRITE_CHAR0, SWRITE_CHAR1, SWRITE_CHAR2,
+ SWRITE_SIGN1, SWRITE_SIGN2, SDONE, SERROR1, SERROR2, SBLANK1, SBLANK2);
signal state_int, state_next : PARSER_STATE;
signal z_int, z_next, strich_int, strich_next, wtmp_int, wtmp_next : csigned;
signal punkt_int, punkt_next : csigned;
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;
+ signal finished_int, finished_next : std_logic;
signal aktop_int, aktop_next : alu_ops;
signal opp_int, opp_next : alu_ops;
signal opcode_int, opcode_next : alu_ops;
signal op1_int, op1_next : csigned;
signal op2_int, op2_next : csigned;
signal do_calc_int, do_calc_next : std_logic;
- signal goto_calcn1, goto_op1, goto_space3, goto_sign : std_logic;
signal z_sign_next, z_sign_int : std_logic;
signal firstz_next, firstz_int : boolean;
signal err_next, err_int : hstr_int;
signal errc_next, errc_int : hstr_int;
signal errc_tmp_next, errc_tmp_int : hstr_int;
+ -- ALU
+ signal opcode : alu_ops;
+ signal op1 : csigned;
+ signal op2 : csigned;
+ signal op3 : csigned;
+ signal opM : csigned;
+ signal do_calc : std_logic;
+ signal calc_done : std_logic;
+ signal calc_error : std_logic;
begin
+ instalu : alu
+ port map (
+ sys_clk => sys_clk,
+ sys_res_n => sys_res_n,
+ do_calc => do_calc,
+ calc_done => calc_done,
+ calc_error => calc_error,
+ op1 => op1,
+ op2 => op2,
+ op3 => op3,
+ opM => opM,
+ opcode => opcode
+ );
+
p_write <= p_write_int;
p_rget <= p_rget_int;
p_wtake <= p_wtake_int;
p_finished <= p_finished_int;
+ finished <= finished_int;
opcode <= opcode_int;
op1 <= op1_int;
aktop_int <= ALU_NOP;
opp_int <= ALU_NOP;
err_int <= 0;
- errc_int <= 70;
+ errc_int <= HSPALTE_MAX;
errc_tmp_int <= 0;
firstz_int <= true;
-- 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';
+ finished_int <= '0';
opcode_int <= ALU_NOP;
op1_int <= (others => '0');
op2_int <= (others => '0');
do_calc_int <= '0';
- finished <= '0';
elsif rising_edge(sys_clk) then
-- internal
state_int <= state_next;
p_write_int <= p_write_next;
p_wtake_int <= p_wtake_next;
p_finished_int <= p_finished_next;
+ finished_int <= finished_next;
opcode_int <= opcode_next;
op1_int <= op1_next;
op2_int <= op2_next;
end process;
-- next state
- process(state_int, do_it, p_rdone, p_wdone, p_read, aktop_int, strich_int,
- punkt_int, calc_done, wtmp_int, opp_int, goto_calcn1, goto_op1,
- goto_space3, goto_sign, z_sign_int, err_int, errc_int, calc_error,
- op2_int)
- begin
- state_next <= state_int;
-
- case state_int is
- when SIDLE =>
- if do_it = '1' then
- state_next <= SREAD_NEWNUMBER;
- end if;
- when SREAD_NEWNUMBER =>
- state_next <= SREAD_SPACE1_2;
- when SREAD_SPACE1_2 =>
- if p_rdone = '1' then
- state_next <= SREAD_SPACE2;
- end if;
- when SREAD_SPACE1_3 =>
- if p_rdone = '1' then
- state_next <= SREAD_SPACE3;
- end if;
- when SREAD_SPACE2 | SREAD_SPACE3 =>
- if goto_calcn1 = '1' then
- case state_int is
- when SREAD_SPACE2 => state_next <= SREAD_NEXTBYTE;
- when SREAD_SPACE3 => state_next <= SREAD_OP1;
- when others => assert(false) report "wtf @ state2";
- end case;
- end if;
- if goto_sign = '1' then
- case state_int is
- when SREAD_SPACE2 => state_next <= SREAD_SIGN1;
- when others => assert(false) report "wtf @ state3";
- end case;
- end if;
- if p_rdone = '0' then
- if goto_calcn1 = '0' then
- case state_int is
- when SREAD_SPACE2 => state_next <= SREAD_SPACE1_2;
- when SREAD_SPACE3 => state_next <= SREAD_SPACE1_3;
- when others => assert(false) report "wtf @ state1";
- end case;
- end if;
- end if;
- when SREAD_SIGN1 =>
- if p_rdone = '0' then
- state_next <= SREAD_NEXTBYTE;
- end if;
- when SREAD_NEXTBYTE =>
- if p_rdone = '1' then
- state_next <= SREAD_CALCNUMBER1;
- end if;
- when SREAD_CALCNUMBER1 =>
- if goto_op1 = '1' then
- state_next <= SREAD_OP1;
- elsif goto_space3 = '1' then
- state_next <= SREAD_SPACE3;
- elsif calc_done = '1' then
- state_next <= SREAD_CALCNUMBER2;
- end if;
- when SREAD_OP1 =>
- state_next <= SREAD_OP2;
- when SREAD_OP2 =>
- if p_rdone = '0' then
- if aktop_int /= ALU_NOP then
- state_next <= SCALC_1;
- end if;
- end if;
- when SREAD_CALCNUMBER2 =>
- if p_rdone = '0' and calc_done = '0' then
- state_next <= SREAD_NEXTBYTE;
- end if;
- when SCALC_1 =>
- if calc_done = '1' then
- case opp_int is
- -- spezialfall: eine zwischenberechnung wird fuer diese
- -- kombination benoetigt
- when ALU_MUL | ALU_DIV =>
- case aktop_int is
- when ALU_ADD | ALU_SUB | ALU_DONE => state_next <= SCALC_14;
- when others => state_next <= SCALC_2;
- end case;
- when others => state_next <= SCALC_2;
- end case;
- end if;
- when SCALC_14 =>
- if calc_done = '0' then
- state_next <= SCALC_15;
- end if;
- when SCALC_15 =>
- if calc_done = '1' then
- state_next <= SCALC_2;
- end if;
- when SCALC_2 =>
- if calc_done = '0' then
- if aktop_int = ALU_DONE then
- state_next <= SWRITE_CHAR2;
- else
- state_next <= SREAD_NEWNUMBER;
- end if;
- end if;
- when SWRITE_CHAR0 =>
- if calc_done = '1' then
- state_next <= SWRITE_CHAR1;
- end if;
- when SWRITE_CHAR1 =>
- if p_wdone = '1' then
- if strich_int < 10 then
- if z_sign_int = '1' then
- state_next <= SWRITE_SIGN1;
- else
- state_next <= SDONE;
- end if;
- else
- state_next <= SWRITE_CHAR2;
- end if;
- end if;
- when SERROR1 =>
- if p_wdone = '1' then
- if errc_int <= 2 then
- state_next <= SDONE;
- else
- state_next <= SERROR2;
- end if;
- end if;
- when SERROR2 =>
- if p_wdone = '0' then
- state_next <= SERROR1;
- end if;
- when SWRITE_CHAR2 =>
- if p_wdone = '0' and calc_done = '0' then
- state_next <= SWRITE_CHAR0;
- end if;
- when SWRITE_SIGN1 =>
- if p_wdone = '0' then
- state_next <= SWRITE_SIGN2;
- end if;
- when SWRITE_SIGN2 =>
- if p_wdone = '1' then
- state_next <= SDONE;
- end if;
-
- when SDONE =>
- if p_wdone = '0' and do_it = '0' then
- state_next <= SIDLE;
- end if;
- end case;
-
- -- fehlerbehandlung
- case state_int is
- when SERROR1 | SERROR2 | SDONE => null;
- when others =>
- if err_int > 0 then
- state_next <= SERROR1;
- end if;
- end case;
- end process;
-
- -- out
- process(state_int, p_read, p_write_int, z_int, rbyte_int, p_rget_int,
- strich_int, aktop_int, opp_int, opcode_int, op1_int, op2_int, op3, opM,
- do_calc_int, wtmp_int, punkt_int, z_sign_int, err_int, errc_int,
- errc_tmp_int, firstz_int, calc_done, calc_error)
+ process(do_it, p_rdone, p_wdone, p_read, aktop_int, strich_int, punkt_int,
+ calc_done, wtmp_int, opp_int, z_sign_int, err_int, errc_int,
+ calc_error, op2_int, state_int, p_write_int, z_int, rbyte_int,
+ p_rget_int, opcode_int, op1_int, op3, opM, do_calc_int,
+ errc_tmp_int, firstz_int)
function hbyte2csigned (x : hbyte) return csigned is
variable y : csigned;
begin
return y;
end function csigned2hbyte;
-
variable multmp : signed(((2*CBITS)-1) downto 0);
variable tmp : csigned;
type errstrings is array (natural range 1 to 3) of hstring;
constant error_str : errstrings := (
- 1 => " Division durch Null" & nul,
- 2 => " Syntax" & nul,
- 3 => " Over- bzw. Underflow" & nul
+ 1 => " Fehler: Division durch Null " & nul,
+ 2 => " Fehler: Syntax " & nul,
+ 3 => " Fehler: Over- bzw. Underflow " & nul
);
begin
+ state_next <= state_int;
-- internal
z_next <= z_int;
z_sign_next <= z_sign_int;
p_write_next <= p_write_int;
p_wtake_next <= '0';
p_finished_next <= '0';
+ finished_next <= '0';
opcode_next <= opcode_int;
op1_next <= op1_int;
op2_next <= op2_int;
do_calc_next <= '0';
- goto_calcn1 <= '0';
- goto_op1 <= '0';
- goto_space3 <= '0';
- goto_sign <= '0';
case state_int is
when SIDLE =>
strich_next <= (others => '0');
punkt_next <= (0 => '1', others => '0');
opp_next <= ALU_NOP;
+ if do_it = '1' then
+ state_next <= SREAD_NEWNUMBER;
+ end if;
+
when SREAD_NEWNUMBER =>
z_next <= (others => '0');
z_sign_next <= '0';
rbyte_next <= (others => '0');
p_write_next <= (others => '0');
aktop_next <= ALU_NOP;
- when SREAD_NEXTBYTE | SREAD_SPACE1_2 | SREAD_SPACE1_3 =>
+ state_next <= SREAD_SPACE_GET;
+
+ when SREAD_SPACE_GET =>
p_rget_next <= '1';
- when SREAD_SPACE2 | SREAD_SPACE3 =>
- case p_read is
- when x"20" =>
- null;
- when x"2D" =>
+ if p_rdone = '1' then
+ state_next <= SREAD_SPACE_PROC;
+ end if;
+ when SREAD_SPACE_GET_SIGN =>
+ p_rget_next <= '1';
+ if p_rdone = '1' then
+ state_next <= SREAD_SPACE_PROC_SIGN;
+ end if;
+ when SREAD_SPACE_PROC | SREAD_SPACE_PROC_SIGN =>
+ if p_rdone = '0' then
+ case state_int is
+ when SREAD_SPACE_PROC => state_next <= SREAD_SPACE_GET;
+ when SREAD_SPACE_PROC_SIGN => state_next <= SREAD_SPACE_GET_SIGN;
+ when others => assert(false) report "wtf @ state1";
+ end case;
+ else
+ if p_read = x"2d" and state_int = SREAD_SPACE_PROC then
+ -- vorzeichen?
+ state_next <= SREAD_SIGN;
+ elsif p_read /= x"20" then
+ -- leerzeichen sollen ignoriert werden
+ p_rget_next <= '1';
case state_int is
- when SREAD_SPACE2 => goto_sign <= '1';
- when SREAD_SPACE3 => goto_calcn1 <= '1'; p_rget_next <= '1';
- when others => assert(false) report "SREAD_SPACE2/3: shouldn't happen";
+ when SREAD_SPACE_PROC => state_next <= SREAD_NEXTBYTE;
+ when SREAD_SPACE_PROC_SIGN => state_next <= SREAD_OP1;
+ when others => assert(false) report "SREAD_SPACE_PROC{,_SIGN}: shouldn't happen";
end case;
- when others =>
- goto_calcn1 <= '1';
- p_rget_next <= '1';
- end case;
+ end if;
+ end if;
+ when SREAD_SIGN =>
+ z_sign_next <= '1';
+ if p_rdone = '0' then
+ state_next <= SREAD_NEXTBYTE;
+ end if;
+ when SREAD_NEXTBYTE =>
+ p_rget_next <= '1';
+ if p_rdone = '1' then
+ state_next <= SREAD_CALCNUMBER1;
+ end if;
when SREAD_CALCNUMBER1 =>
case p_read is
-- '+', '-', '*', '/'
if firstz_int then
err_next <= 2;
else
- goto_op1 <= '1';
+ state_next <= SREAD_OP1;
p_rget_next <= '1';
end if;
-- ' '
when x"20" =>
- goto_space3 <= '1';
+ state_next <= SREAD_SPACE_PROC_SIGN;
p_rget_next <= '1';
when others =>
firstz_next <= false;
do_calc_next <= '1';
end case;
- when SREAD_SIGN1 =>
- z_sign_next <= '1';
+ if calc_done = '1' then
+ state_next <= SREAD_CALCNUMBER2;
+ end if;
when SREAD_CALCNUMBER2 =>
z_next <= op3 + hbyte2csigned(p_read);
- when SREAD_OP2 =>
- null;
+ if p_rdone = '0' and calc_done = '0' then
+ state_next <= SREAD_NEXTBYTE;
+ end if;
+
when SREAD_OP1 =>
case p_read is
when x"2B" => aktop_next <= ALU_ADD; -- '+'
when others => err_next <= 2;
end case;
-
+ state_next <= SREAD_OP2;
+ when SREAD_OP2 =>
+ if p_rdone = '0' then
+ state_next <= SCALC_1;
+ end if;
when SCALC_1 =>
if z_sign_int = '1' then
case opp_int is
when ALU_NOP | ALU_ADD | ALU_SUB =>
case opp_int is
- when ALU_SUB => op1_next <= (not tmp) + 1;
+ when ALU_SUB =>
+ -- xst (xilinx) workaround
+ if x"80000000" = tmp then
+ -- vgl. testfall 37 und 38
+ err_next <= 3;
+ op1_next <= tmp;
+ else
+ op1_next <= (not tmp) + 1;
+ end if;
when others => op1_next <= tmp;
end case;
case aktop_int is
end case;
do_calc_next <= '1';
+ if calc_done = '1' then
+ case opp_int is
+ -- spezialfall: eine zwischenberechnung wird fuer diese
+ -- kombination benoetigt
+ when ALU_MUL | ALU_DIV =>
+ case aktop_int is
+ when ALU_ADD | ALU_SUB | ALU_DONE => state_next <= SCALC_14;
+ when others => state_next <= SCALC_2;
+ end case;
+ when others => state_next <= SCALC_2;
+ end case;
+ end if;
when SCALC_14 =>
-- ueberpruefung kann man sich sparen, da diese ohnehin in
-- nextstate gemacht wird.
op1_next <= op3;
do_calc_next <= '0';
+ if calc_done = '0' then
+ state_next <= SCALC_15;
+ end if;
when SCALC_15 =>
-- ueberpruefung kann man sich sparen, da diese ohnehin in
-- nextstate gemacht wird.
punkt_next <= (0 => '1', others => '0');
do_calc_next <= '1';
+ if calc_done = '1' then
+ state_next <= SCALC_2;
+ end if;
when SCALC_2 =>
case opp_int is
when ALU_NOP | ALU_ADD | ALU_SUB | ALU_MUL | ALU_DIV =>
punkt_next <= op3;
when others => assert (false) report "SCALC_2/1: shouldn't happen!";
end case;
+ when ALU_DONE => null;
when others => assert (false) report "SCALC_2/2: shouldn't happen!";
end case;
-- aktuelle rechenoperation fuer naechste 'runde' uebernehmen
opp_next <= aktop_int;
+ if calc_done = '0' then
+ if aktop_int = ALU_DONE then
+ state_next <= SWRITE_CHAR2;
+ else
+ state_next <= SREAD_NEWNUMBER;
+ end if;
+ end if;
+
when SWRITE_CHAR0 =>
- op1_next <= strich_int;
+ -- fuer testfall 39 und 40
+ if strich_int = to_signed(-214748364,CBITS) then
+ op1_next <= to_signed(214748364,CBITS);
+ strich_next <= to_signed(214748364,CBITS);
+ else
+ op1_next <= strich_int;
+ end if;
opcode_next <= ALU_DIV;
op2_next <= to_signed(10,CBITS);
do_calc_next <= '1';
+
+ if calc_done = '1' then
+ state_next <= SWRITE_CHAR1;
+ end if;
when SWRITE_CHAR1 =>
do_calc_next <= '1';
p_wtake_next <= '1';
tmp := opM;
p_write_next <= csigned2hbyte(tmp);
wtmp_next <= op3;
+
+ if p_wdone = '1' then
+ errc_next <= errc_int - 1;
+ -- ueberpruefung auf -2147483648 fuer testfall 39 und 40
+ -- x"80000000": xst (xilinx) workaround
+ if strich_int < 10 and strich_int /= x"80000000" then
+ if z_sign_int = '1' then
+ state_next <= SWRITE_SIGN1;
+ else
+ state_next <= SBLANK1;
+ end if;
+ else
+ state_next <= SWRITE_CHAR2;
+ end if;
+ end if;
when SWRITE_CHAR2 =>
strich_next <= wtmp_int;
+ if p_wdone = '0' and calc_done = '0' then
+ state_next <= SWRITE_CHAR0;
+ end if;
when SWRITE_SIGN1 =>
- null;
+ if p_wdone = '0' then
+ state_next <= SWRITE_SIGN2;
+ end if;
when SWRITE_SIGN2 =>
if z_sign_int = '1' then
p_wtake_next <= '1';
assert(false) report "SWRITE_SIGN: shouldn't happen!";
end if;
+ if p_wdone = '1' then
+ errc_next <= errc_int - 1;
+ state_next <= SDONE;
+ end if;
+
+ when SBLANK1 =>
+ p_wtake_next <= '1';
+ p_write_next <= x"20";
+ errc_tmp_next <= errc_int - 1;
+ if p_wdone = '1' then
+ if errc_int <= 2 then
+ state_next <= SDONE;
+ else
+ state_next <= SBLANK2;
+ end if;
+ end if;
+ when SBLANK2 =>
+ errc_next <= errc_tmp_int;
+ if p_wdone = '0' then
+ state_next <= SBLANK1;
+ end if;
+
when SERROR1 =>
p_wtake_next <= '1';
p_write_next <= hbyte(to_unsigned (character'pos(error_str(err_int)(errc_int)),8));
errc_tmp_next <= errc_int - 1;
+ if p_wdone = '1' then
+ if errc_int <= 2 then
+ state_next <= SDONE;
+ else
+ state_next <= SERROR2;
+ end if;
+ end if;
when SERROR2 =>
errc_next <= errc_tmp_int;
+ if p_wdone = '0' then
+ state_next <= SERROR1;
+ end if;
when SDONE =>
err_next <= 0;
- errc_next <= 70;
+ errc_next <= HSPALTE_MAX;
p_finished_next <= '1';
+ finished_next <= '1';
+
+ if p_wdone = '0' and do_it = '0' then
+ state_next <= SIDLE;
+ end if;
end case;
-- fehlerbehandlung
case state_int is
+ -- diese states sind ausgenommen vom "pokemon-exception-handling"
when SERROR1 | SERROR2 | SDONE => null;
when others =>
if calc_error = '1' then
err_next <= 3;
end if;
end if;
+
+ if err_int > 0 then
+ state_next <= SERROR1;
+ end if;
end case;
end process;
end architecture beh;