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_NEXTBYTE, SREAD_CALCNUMBER1, SREAD_CALCNUMBER2, SCALC_1, SCALC_14,
- SCALC_15, SCALC_2, SWRITE_CHAR1, SWRITE_CHAR2, SDONE, SERROR1, SERROR2);
+ SREAD_SIGN1, SREAD_NEXTBYTE, SREAD_CALCNUMBER1, SREAD_CALCNUMBER2, SCALC_1,
+ SCALC_14, SCALC_15, SCALC_2, SWRITE_CHAR1, SWRITE_CHAR2, SWRITE_SIGN1,
+ SWRITE_SIGN2, SDONE, SERROR1, SERROR2);
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 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 : std_logic;
+ signal goto_calcn1, goto_op1, goto_space3, goto_sign : std_logic;
+ signal z_sign_next, z_sign_int : std_logic;
begin
p_write <= p_write_int;
p_rget <= p_rget_int;
if sys_res_n = '0' then
state_int <= SIDLE;
z_int <= (others => '0');
+ z_sign_int <= '0';
strich_int <= (others => '0');
punkt_int <= (others => '0');
wtmp_int <= (others => '0');
-- internal
state_int <= state_next;
z_int <= z_next;
+ z_sign_int <= z_sign_next;
strich_int <= strich_next;
punkt_int <= punkt_next;
wtmp_int <= wtmp_next;
-- 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_space3, goto_sign, z_sign_int)
begin
state_next <= state_int;
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 @ state2";
+ when others => assert(false) report "wtf @ state1";
end case;
end if;
end if;
- 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 @ state1";
- end case;
+ when SREAD_SIGN1 =>
+ if p_rdone = '0' then
+ state_next <= SREAD_NEXTBYTE;
end if;
when SREAD_NEXTBYTE =>
if p_rdone = '1' then
when SWRITE_CHAR1 =>
if p_wdone = '1' then
if strich_int < 10 then
- state_next <= SDONE;
+ if z_sign_int = '1' then
+ state_next <= SWRITE_SIGN1;
+ else
+ state_next <= SDONE;
+ end if;
else
state_next <= SWRITE_CHAR2;
end if;
if p_wdone = '0' then
state_next <= SWRITE_CHAR1;
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;
-- 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,
- do_calc_int, wtmp_int, punkt_int)
+ do_calc_int, wtmp_int, punkt_int, z_sign_int)
function hbyte2csigned (x : hbyte) return csigned is
variable y : csigned;
begin
begin
-- internal
z_next <= z_int;
+ z_sign_next <= z_sign_int;
strich_next <= strich_int;
punkt_next <= punkt_int;
wtmp_next <= wtmp_int;
goto_calcn1 <= '0';
goto_op1 <= '0';
goto_space3 <= '0';
+ goto_sign <= '0';
case state_int is
when SIDLE =>
opp_next <= ALU_NOP;
when SREAD_NEWNUMBER =>
z_next <= (others => '0');
+ z_sign_next <= '0';
rbyte_next <= (others => '0');
p_write_next <= (others => '0');
aktop_next <= ALU_NOP;
case p_read is
when x"20" =>
null;
+ when x"2D" =>
+ 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";
+ end case;
when others =>
goto_calcn1 <= '1';
p_rget_next <= '1';
multmp := (z_int * 10) + hbyte2csigned(p_read);
z_next <= multmp((CBITS-1) downto 0);
end case;
+ when SREAD_SIGN1 =>
+ z_sign_next <= '1';
when SREAD_CALCNUMBER2 | SREAD_OP2 =>
null;
when SREAD_OP1 =>
when SCALC_1 =>
+ if z_sign_int = '1' then
+ tmp := (not z_int) + 1;
+ z_next <= tmp;
+ z_sign_next <= '0';
+ else
+ tmp := z_int;
+ end if;
+
case opp_int is
when ALU_NOP | ALU_ADD | ALU_SUB =>
case opp_int is
- when ALU_SUB => op1_next <= (not z_int) + 1;
- when others => op1_next <= z_int;
+ when ALU_SUB => op1_next <= (not tmp) + 1;
+ when others => op1_next <= tmp;
end case;
case aktop_int is
when ALU_ADD | ALU_SUB | ALU_DONE =>
when ALU_ADD | ALU_SUB | ALU_DONE | ALU_MUL | ALU_DIV =>
op1_next <= punkt_int;
opcode_next <= opp_int;
- op2_next <= z_int;
+ op2_next <= tmp;
when others => assert(false) report "SCALC_1/2: shouldn't happen!";
end case;
when others => assert(false) report "SCALC_1/3: shouldn't happen!";
when ALU_NOP | ALU_ADD | ALU_SUB | ALU_MUL | ALU_DIV =>
case aktop_int is
when ALU_ADD | ALU_SUB | ALU_DONE =>
- strich_next <= op3;
+ if aktop_int = ALU_DONE and op3 < 0 then
+ strich_next <= (not op3) + 1;
+ z_sign_next <= '1';
+ else
+ strich_next <= op3;
+ end if;
when ALU_MUL | ALU_DIV =>
punkt_next <= op3;
when others => assert (false) report "SCALC_2/1: shouldn't happen!";
when SWRITE_CHAR2 =>
strich_next <= wtmp_int;
+ when SWRITE_SIGN1 =>
+ null;
+ when SWRITE_SIGN2 =>
+ if z_sign_int = '1' then
+ p_wtake_next <= '1';
+ p_write_next <= x"2D";
+ else
+ assert(false) report "SWRITE_SIGN: shouldn't happen!";
+ end if;
+
when SERROR1 =>
-- TODO
null;