alu: error flag setzen bei overflow/underflow bzw. bei division durch 0
[hwmod.git] / src / parser.vhd
1 library ieee;
2 use ieee.std_logic_1164.all;
3 use ieee.numeric_std.all;
4 use work.gen_pkg.all;
5
6 entity parser is
7         port
8         (
9                 sys_clk : in std_logic;
10                 sys_res_n : in std_logic;
11                 -- History
12                 p_rw : out std_logic;
13                 p_spalte : out hspalte;
14                 p_rget : out std_logic;
15                 p_rdone : in std_logic;
16                 p_read : in hbyte;
17                 p_wtake : out std_logic;
18                 p_wdone : in std_logic;
19                 p_write : out hbyte;
20                 p_finished : out std_logic;
21                 -- ALU
22                 opcode : out alu_ops;
23                 op1 : out csigned;
24                 op2 : out csigned;
25                 op3 : in csigned;
26                 do_calc : out std_logic;
27                 calc_done : in std_logic;
28                 -- TODO: calc_error : in std_logic;
29                 -- Scanner
30                 do_it : in std_logic;
31                 finished : out std_logic
32         );
33 end entity parser;
34
35 architecture beh of parser is
36         type PARSER_STATE is (SIDLE, SREAD_NEWNUMBER, SREAD_NEXTBYTE,
37         SREAD_CALCNUMBER1, SREAD_CALCNUMBER2, SCALC_1, SCALC_2, SWRITE_CHAR1, SWRITE_CHAR2, SDONE);
38         signal state_int, state_next : PARSER_STATE;
39         signal z_int, z_next, strich_int, strich_next, wtmp_int, wtmp_next : csigned;
40         signal rbyte_int, rbyte_next : hbyte;
41         signal p_write_int, p_write_next : hbyte;
42         signal p_rget_int, p_rget_next : std_logic;
43         signal p_wtake_int, p_wtake_next : std_logic;
44         signal p_finished_int, p_finished_next : std_logic;
45         signal aktop_int, aktop_next : alu_ops;
46         signal opp_int, opp_next : alu_ops;
47         signal opcode_int, opcode_next : alu_ops;
48         signal op1_int, op1_next : csigned;
49         signal op2_int, op2_next : csigned;
50         signal do_calc_int, do_calc_next : std_logic;
51 begin
52         p_write <= p_write_int;
53         p_rget <= p_rget_int;
54         p_wtake <= p_wtake_int;
55         p_finished <= p_finished_int;
56
57         opcode <= opcode_int;
58         op1 <= op1_int;
59         op2 <= op2_int;
60         do_calc <= do_calc_int;
61
62         process(sys_clk, sys_res_n)
63         begin
64                 if sys_res_n = '0' then
65                         state_int <= SIDLE;
66                         z_int <= (others => '0');
67                         strich_int <= (others => '0');
68                         wtmp_int <= (others => '0');
69                         rbyte_int <= (others => '0');
70                         aktop_int <= ALU_NOP;
71                         opp_int <= ALU_NOP;
72                         -- out ports
73                         p_rw <= '0';
74                         p_spalte <= (others => '0');
75                         p_rget_int <= '0';
76                         p_write_int <= (others => '0');
77                         p_wtake_int <= '0';
78                         p_finished_int <= '0';
79                         opcode_int <= ALU_NOP;
80                         op1_int <= (others => '0');
81                         op2_int <= (others => '0');
82                         do_calc_int <= '0';
83                         finished <= '0';
84                 elsif rising_edge(sys_clk) then
85                         -- internal
86                         state_int <= state_next;
87                         z_int <= z_next;
88                         strich_int <= strich_next;
89                         wtmp_int <= wtmp_next;
90                         rbyte_int <= rbyte_next;
91                         aktop_int <= aktop_next;
92                         opp_int <= opp_next;
93                         -- out ports
94                         p_rget_int <= p_rget_next;
95                         p_write_int <= p_write_next;
96                         p_wtake_int <= p_wtake_next;
97                         p_finished_int <= p_finished_next;
98                         opcode_int <= opcode_next;
99                         op1_int <= op1_next;
100                         op2_int <= op2_next;
101                         do_calc_int <= do_calc_next;
102                 end if;
103         end process;
104
105         -- next state
106         process(state_int, do_it, p_rdone, p_wdone, p_read, aktop_int, strich_int,
107                 strich_next, calc_done, wtmp_int)
108         begin
109                 state_next <= state_int;
110
111                 case state_int is
112                         when SIDLE =>
113                                 if do_it = '1' then
114                                         state_next <= SREAD_NEWNUMBER;
115                                 end if;
116                         when SREAD_NEWNUMBER =>
117                                 state_next <= SREAD_NEXTBYTE;
118                         when SREAD_NEXTBYTE =>
119                                 if p_rdone = '1' then
120                                         state_next <= SREAD_CALCNUMBER1;
121                                 end if;
122                         when SREAD_CALCNUMBER1 =>
123                                 state_next <= SREAD_CALCNUMBER2;
124                         when SREAD_CALCNUMBER2 =>
125                                 if aktop_int /= ALU_NOP then
126                                         state_next <= SCALC_1;
127                                 else
128                                         state_next <= SREAD_NEXTBYTE;
129                                 end if;
130                         when SCALC_1 =>
131                                 if calc_done = '1' then
132                                         state_next <= SCALC_2;
133                                 end if;
134                         when SCALC_2 =>
135                                 if aktop_int = ALU_DONE then
136                                         state_next <= SWRITE_CHAR1;
137                                 else
138                                         state_next <= SREAD_NEWNUMBER;
139                                 end if;
140                         when SWRITE_CHAR1 =>
141                                 if p_wdone = '1' then
142                                         if strich_int < 10 then
143                                                 state_next <= SDONE;
144                                         else
145                                                 state_next <= SWRITE_CHAR2;
146                                         end if;
147                                 end if;
148                         when SWRITE_CHAR2 =>
149                                 if p_wdone = '0' then
150                                         state_next <= SWRITE_CHAR1;
151                                 end if;
152                         when SDONE =>
153                                 if p_wdone = '0' and do_it = '0' then
154                                         state_next <= SIDLE;
155                                 end if;
156                 end case;
157         end process;
158
159         -- out
160         process(state_int, p_read, p_write_int, z_int, rbyte_int, p_rget_int,
161                 strich_int, aktop_int, opp_int, opcode_int, op1_int, op2_int, op3,
162                 do_calc_int, wtmp_int)
163                 function hbyte2csigned (x : hbyte) return csigned is
164                         variable y : csigned;
165                 begin
166                         case x is
167                                 when x"30" => y := to_signed(0, CBITS);
168                                 when x"31" => y := to_signed(1, CBITS);
169                                 when x"32" => y := to_signed(2, CBITS);
170                                 when x"33" => y := to_signed(3, CBITS);
171                                 when x"34" => y := to_signed(4, CBITS);
172                                 when x"35" => y := to_signed(5, CBITS);
173                                 when x"36" => y := to_signed(6, CBITS);
174                                 when x"37" => y := to_signed(7, CBITS);
175                                 when x"38" => y := to_signed(8, CBITS);
176                                 when x"39" => y := to_signed(9, CBITS);
177                                 when others => assert(false) report "hbyte2csigned: shouldn't happen";
178                         end case;
179                         return y;
180                 end function hbyte2csigned;
181
182                 function csigned2hbyte (x : csigned) return hbyte is
183                         variable y : hbyte;
184                 begin
185                         case x is
186                                 when x"00000000" => y := x"30";
187                                 when x"00000001" => y := x"31";
188                                 when x"00000002" => y := x"32";
189                                 when x"00000003" => y := x"33";
190                                 when x"00000004" => y := x"34";
191                                 when x"00000005" => y := x"35";
192                                 when x"00000006" => y := x"36";
193                                 when x"00000007" => y := x"37";
194                                 when x"00000008" => y := x"38";
195                                 when x"00000009" => y := x"39";
196                                 when others => assert(false) report "csigned2hbyte: shouldn't happen";
197                         end case;
198                         return y;
199                 end function csigned2hbyte;
200
201                 variable multmp : signed(((2*CBITS)-1) downto 0);
202                 variable tmp : csigned;
203         begin
204                 -- internal
205                 z_next <= z_int;
206                 strich_next <= strich_int;
207                 wtmp_next <= wtmp_int;
208                 rbyte_next <= rbyte_int;
209                 aktop_next <= aktop_int;
210                 opp_next <= opp_int;
211                 -- signals
212                 p_rget_next <= '0';
213                 p_write_next <= p_write_int;
214                 p_wtake_next <= '0';
215                 p_finished_next <= '0';
216                 opcode_next <= opcode_int;
217                 op1_next <= op1_int;
218                 op2_next <= op2_int;
219                 do_calc_next <= '0';
220
221                 case state_int is
222                         when SIDLE =>
223                                 strich_next <= (others => '0');
224                                 opp_next <= ALU_NOP;
225                         when SREAD_NEWNUMBER =>
226                                 z_next <= (others => '0');
227                                 rbyte_next <= (others => '0');
228                                 p_write_next <= (others => '0');
229                                 aktop_next <= ALU_NOP;
230                         when SREAD_NEXTBYTE =>
231                                 p_rget_next <= '1';
232                         when SREAD_CALCNUMBER1 =>
233                                 case p_read is
234                                         -- '+'
235                                         when x"2B" =>
236                                                 aktop_next <= ALU_ADD;
237
238                                         -- '\0'
239                                         when x"00" =>
240                                                 aktop_next <= ALU_DONE;
241
242                                         when others =>
243                                                 -- TODO: check auf overflow
244                                                 multmp := (z_int * 10) + hbyte2csigned(p_read);
245                                                 z_next <= multmp((CBITS-1) downto 0);
246                                 end case;
247                         when SREAD_CALCNUMBER2 =>
248                                 null;
249
250                         when SCALC_1 =>
251                                 case opp_int is
252                                         when ALU_NOP | ALU_ADD =>
253                                                 op1_next <= z_int;
254                                                 case aktop_int is
255                                                         when ALU_ADD | ALU_SUB | ALU_NOP | ALU_DONE =>
256                                                                 opcode_next <= ALU_ADD;
257                                                                 op2_next <= strich_int;
258                                                         when ALU_MUL | ALU_DIV =>
259                                                                 opcode_next <= ALU_MUL;
260                                                                 op2_next <= strich_int;
261                                                         when others => assert(false) report "SCALC_1/ALU_NOP: not implemented yet";
262                                                 end case;
263                                                 do_calc_next <= '1';
264                                         when others => assert(false) report "SCALC_1: not implemented yet";
265                                 end case;
266                         when SCALC_2 =>
267                                 case opp_int is
268                                         when ALU_NOP | ALU_ADD =>
269                                                 strich_next <= op3;
270                                         when others => assert (false) report "SCALC_2: not implemented yet";
271                                 end case;
272                                 opp_next <= aktop_int;
273
274                         when SWRITE_CHAR1 =>
275                                 p_wtake_next <= '1';
276                                 tmp := strich_int mod 10;
277                                 p_write_next <= csigned2hbyte(tmp);
278                                 wtmp_next <= strich_int / 10;
279                         when SWRITE_CHAR2 =>
280                                 strich_next <= wtmp_int;
281
282                         when SDONE =>
283                                 p_finished_next <= '1';
284                 end case;
285         end process;
286 end architecture beh;