op3 : in csigned;
do_calc : out std_logic;
calc_done : in std_logic;
- -- TODO: calc_error : 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_CHAR1, SREAD_CHAR2, SWRITE_CHAR);
+ type PARSER_STATE is (SIDLE, SREAD_NEWNUMBER, SREAD_NEXTBYTE,
+ SREAD_CALCNUMBER1, SREAD_CALCNUMBER2, SCALC_1, SCALC_14, SCALC_15, SCALC_2, SWRITE_CHAR1,
+ SWRITE_CHAR2, SDONE, SERROR1, SERROR2);
signal state_int, state_next : PARSER_STATE;
- signal z_int, z_next : csigned;
+ signal z_int, z_next, strich_int, strich_next, wtmp_int, wtmp_next : csigned;
+ signal punkt_int, punkt_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;
+ 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;
begin
p_write <= p_write_int;
p_rget <= p_rget_int;
p_wtake <= p_wtake_int;
p_finished <= p_finished_int;
+ opcode <= opcode_int;
+ op1 <= op1_int;
+ op2 <= op2_int;
+ do_calc <= do_calc_int;
+
process(sys_clk, sys_res_n)
begin
if sys_res_n = '0' then
state_int <= SIDLE;
z_int <= (others => '0');
+ strich_int <= (others => '0');
+ punkt_int <= (others => '0');
+ wtmp_int <= (others => '0');
rbyte_int <= (others => '0');
+ aktop_int <= ALU_NOP;
+ opp_int <= ALU_NOP;
-- out ports
p_rw <= '0';
p_spalte <= (others => '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';
+ 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;
z_int <= z_next;
+ strich_int <= strich_next;
+ punkt_int <= punkt_next;
+ wtmp_int <= wtmp_next;
rbyte_int <= rbyte_next;
+ aktop_int <= aktop_next;
+ opp_int <= opp_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;
+ opcode_int <= opcode_next;
+ op1_int <= op1_next;
+ op2_int <= op2_next;
+ do_calc_int <= do_calc_next;
end if;
end process;
-- next state
- process(state_int, do_it, p_rdone, p_wdone, p_read)
+ process(state_int, do_it, p_rdone, p_wdone, p_read, aktop_int, strich_int,
+ punkt_int, calc_done, wtmp_int, opp_int)
begin
state_next <= state_int;
case state_int is
when SIDLE =>
if do_it = '1' then
- state_next <= SREAD_CHAR1;
+ state_next <= SREAD_NEWNUMBER;
end if;
- when SREAD_CHAR1 =>
+ when SREAD_NEWNUMBER =>
+ state_next <= SREAD_NEXTBYTE;
+ when SREAD_NEXTBYTE =>
if p_rdone = '1' then
- state_next <= SREAD_CHAR2;
+ state_next <= SREAD_CALCNUMBER1;
+ end if;
+ when SREAD_CALCNUMBER1 =>
+ state_next <= SREAD_CALCNUMBER2;
+ when SREAD_CALCNUMBER2 =>
+ if aktop_int /= ALU_NOP then
+ state_next <= SCALC_1;
+ else
+ state_next <= SREAD_NEXTBYTE;
+ end if;
+ when SCALC_1 =>
+ if calc_done = '1' then
+ case opp_int is
+ 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 aktop_int = ALU_DONE then
+ state_next <= SWRITE_CHAR1;
+ else
+ state_next <= SREAD_NEWNUMBER;
end if;
- when SREAD_CHAR2 =>
+ when SWRITE_CHAR1 =>
if p_wdone = '1' then
- state_next <= SWRITE_CHAR;
+ if strich_int < 10 then
+ state_next <= SDONE;
+ else
+ state_next <= SWRITE_CHAR2;
+ end if;
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;
+ when SERROR1 =>
+ if p_wdone = '1' then
+ -- TODO
+ if strich_int < 10 then
+ state_next <= SDONE;
+ else
+ state_next <= SWRITE_CHAR2;
end if;
- else
- state_next <= SREAD_CHAR1;
+ end if;
+ when SWRITE_CHAR2 | SERROR2 =>
+ if p_wdone = '0' then
+ state_next <= SWRITE_CHAR1;
+ end if;
+ when SDONE =>
+ if p_wdone = '0' and do_it = '0' then
+ state_next <= SIDLE;
end if;
end case;
end process;
- process(state_int, p_read, p_write_int, z_int, rbyte_int, p_rget_int)
+ -- 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)
+ function hbyte2csigned (x : hbyte) return csigned is
+ variable y : csigned;
+ begin
+ case x is
+ when x"30" => y := to_signed(0, CBITS);
+ when x"31" => y := to_signed(1, CBITS);
+ when x"32" => y := to_signed(2, CBITS);
+ when x"33" => y := to_signed(3, CBITS);
+ when x"34" => y := to_signed(4, CBITS);
+ when x"35" => y := to_signed(5, CBITS);
+ when x"36" => y := to_signed(6, CBITS);
+ when x"37" => y := to_signed(7, CBITS);
+ when x"38" => y := to_signed(8, CBITS);
+ when x"39" => y := to_signed(9, CBITS);
+ when others => assert(false) report "hbyte2csigned: shouldn't happen";
+ end case;
+ return y;
+ end function hbyte2csigned;
+
+ function csigned2hbyte (x : csigned) return hbyte is
+ variable y : hbyte;
+ begin
+ case x is
+ when x"00000000" => y := x"30";
+ when x"00000001" => y := x"31";
+ when x"00000002" => y := x"32";
+ when x"00000003" => y := x"33";
+ when x"00000004" => y := x"34";
+ when x"00000005" => y := x"35";
+ when x"00000006" => y := x"36";
+ when x"00000007" => y := x"37";
+ when x"00000008" => y := x"38";
+ when x"00000009" => y := x"39";
+ when others => assert(false) report "csigned2hbyte: shouldn't happen";
+ end case;
+ return y;
+ end function csigned2hbyte;
+
+ variable multmp : signed(((2*CBITS)-1) downto 0);
+ variable tmp : csigned;
begin
-- internal
z_next <= z_int;
+ strich_next <= strich_int;
+ punkt_next <= punkt_int;
+ wtmp_next <= wtmp_int;
rbyte_next <= rbyte_int;
+ aktop_next <= aktop_int;
+ opp_next <= opp_int;
-- signals
p_rget_next <= '0';
p_write_next <= p_write_int;
p_wtake_next <= '0';
p_finished_next <= '0';
+ opcode_next <= opcode_int;
+ op1_next <= op1_int;
+ op2_next <= op2_int;
+ do_calc_next <= '0';
case state_int is
when SIDLE =>
+ strich_next <= (others => '0');
+ punkt_next <= (0 => '1', others => '0');
+ opp_next <= ALU_NOP;
+ when SREAD_NEWNUMBER =>
z_next <= (others => '0');
rbyte_next <= (others => '0');
p_write_next <= (others => '0');
- when SREAD_CHAR1 =>
+ aktop_next <= ALU_NOP;
+ when SREAD_NEXTBYTE =>
p_rget_next <= '1';
- p_write_next <= (others => '0');
- when SREAD_CHAR2 =>
- rbyte_next <= p_read;
+ when SREAD_CALCNUMBER1 =>
+ case p_read is
+ -- '+'
+ when x"2B" =>
+ aktop_next <= ALU_ADD;
+ -- '-'
+ when x"2D" =>
+ -- TODO: sign check beim ersten byte lesen!
+ aktop_next <= ALU_SUB;
+ -- '*'
+ when x"2A" =>
+ aktop_next <= ALU_MUL;
+ -- '/'
+ when x"2F" =>
+ aktop_next <= ALU_DIV;
+
+ -- '\0'
+ when x"00" =>
+ aktop_next <= ALU_DONE;
+
+ when others =>
+ -- TODO: check auf overflow
+ multmp := (z_int * 10) + hbyte2csigned(p_read);
+ z_next <= multmp((CBITS-1) downto 0);
+ end case;
+ when SREAD_CALCNUMBER2 =>
+ null;
+
+ when SCALC_1 =>
+ 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;
+ end case;
+ case aktop_int is
+ when ALU_ADD | ALU_SUB | ALU_DONE =>
+ opcode_next <= ALU_ADD;
+ op2_next <= strich_int;
+ when ALU_MUL | ALU_DIV =>
+ opcode_next <= ALU_MUL;
+ op2_next <= punkt_int;
+ when others => assert(false) report "SCALC_1/1: shouldn't happen!";
+ end case;
+
+ when ALU_MUL | ALU_DIV =>
+ case aktop_int is
+ when ALU_ADD | ALU_SUB | ALU_DONE =>
+ op2_next <= z_int;
+ opcode_next <= opp_int;
+ op1_next <= punkt_int;
+ when ALU_MUL | ALU_DIV =>
+ op2_next <= z_int;
+ opcode_next <= opp_int;
+ op1_next <= punkt_int;
+ when others => assert(false) report "SCALC_1/2: shouldn't happen!";
+ end case;
+ when others => assert(false) report "SCALC_1/3: shouldn't happen!";
+ end case;
+ do_calc_next <= '1';
+
+ when SCALC_14 =>
+ case opp_int is
+ when ALU_MUL | ALU_DIV =>
+ case aktop_int is
+ when ALU_ADD | ALU_SUB | ALU_DONE =>
+ op1_next <= op3;
+ do_calc_next <= '0';
+ when others => assert(false) report("SCALC_14/1: bla!");
+ end case;
+ when others => assert(false) report("SCALC_14/2: bla!");
+ end case;
+
+ when SCALC_15 =>
+ case opp_int is
+ when ALU_MUL | ALU_DIV =>
+ case aktop_int is
+ when ALU_ADD | ALU_SUB | ALU_DONE =>
+ opcode_next <= ALU_ADD;
+ op2_next <= strich_int;
+ punkt_next <= (0 => '1', others => '0');
+ do_calc_next <= '1';
+ when others => assert(false) report("SCALC_15/1: bla!");
+ end case;
+ when others => assert(false) report("SCALC_15/2: bla!");
+ end case;
+
+ when SCALC_2 =>
+ case opp_int is
+ when ALU_NOP | ALU_ADD | ALU_SUB =>
+ case aktop_int is
+ when ALU_ADD | ALU_SUB | ALU_DONE =>
+ strich_next <= op3;
+ when ALU_MUL | ALU_DIV =>
+ punkt_next <= op3;
+ when others => assert (false) report "SCALC_2/1: shouldn't happen!";
+ end case;
+ when ALU_MUL | ALU_DIV =>
+ case aktop_int is
+ when ALU_ADD | ALU_SUB | ALU_DONE =>
+ strich_next <= op3;
+ when ALU_MUL | ALU_DIV =>
+ punkt_next <= op3;
+ when others => assert(false) report "SCALC_2/2: shouldn't happen!";
+ end case;
+ when others => assert (false) report "SCALC_2/3: shouldn't happen!";
+ end case;
+
+ opp_next <= aktop_int;
+
+ when SWRITE_CHAR1 =>
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;
+ tmp := strich_int mod 10;
+ p_write_next <= csigned2hbyte(tmp);
+ wtmp_next <= strich_int / 10;
+ when SWRITE_CHAR2 =>
+ strich_next <= wtmp_int;
+
+ when SERROR1 =>
+ -- TODO
+ null;
+ when SERROR2 =>
+ -- TODO
+ null;
+
+ when SDONE =>
+ p_finished_next <= '1';
end case;
end process;
end architecture beh;