parser: / und mod in hardware
[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                 opM : in csigned;
27                 do_calc : out std_logic;
28                 calc_done : in std_logic;
29                 calc_error : in std_logic;
30                 -- Scanner
31                 do_it : in std_logic;
32                 finished : out std_logic
33         );
34 end entity parser;
35
36 architecture beh of parser is
37         type PARSER_STATE is (SIDLE, SREAD_NEWNUMBER, SREAD_SPACE1_2,
38         SREAD_SPACE1_3, SREAD_SPACE2, SREAD_SPACE3, SREAD_OP1, SREAD_OP2,
39         SREAD_SIGN1, SREAD_NEXTBYTE, SREAD_CALCNUMBER1, SREAD_CALCNUMBER2, SCALC_1,
40         SCALC_14, SCALC_15, SCALC_2, SWRITE_CHAR0, SWRITE_CHAR1, SWRITE_CHAR2,
41         SWRITE_SIGN1, SWRITE_SIGN2, SDONE, SERROR1, SERROR2);
42         signal state_int, state_next : PARSER_STATE;
43         signal z_int, z_next, strich_int, strich_next, wtmp_int, wtmp_next : csigned;
44         signal punkt_int, punkt_next : csigned;
45         signal rbyte_int, rbyte_next : hbyte;
46         signal p_write_int, p_write_next : hbyte;
47         signal p_rget_int, p_rget_next : std_logic;
48         signal p_wtake_int, p_wtake_next : std_logic;
49         signal p_finished_int, p_finished_next : std_logic;
50         signal aktop_int, aktop_next : alu_ops;
51         signal opp_int, opp_next : alu_ops;
52         signal opcode_int, opcode_next : alu_ops;
53         signal op1_int, op1_next : csigned;
54         signal op2_int, op2_next : csigned;
55         signal do_calc_int, do_calc_next : std_logic;
56         signal goto_calcn1, goto_op1, goto_space3, goto_sign : std_logic;
57         signal z_sign_next, z_sign_int : std_logic;
58         signal firstz_next, firstz_int : boolean;
59         signal err_next, err_int : hstr_int;
60         signal errc_next, errc_int : hstr_int;
61         signal errc_tmp_next, errc_tmp_int : hstr_int;
62 begin
63         p_write <= p_write_int;
64         p_rget <= p_rget_int;
65         p_wtake <= p_wtake_int;
66         p_finished <= p_finished_int;
67
68         opcode <= opcode_int;
69         op1 <= op1_int;
70         op2 <= op2_int;
71         do_calc <= do_calc_int;
72
73         process(sys_clk, sys_res_n)
74         begin
75                 if sys_res_n = '0' then
76                         state_int <= SIDLE;
77                         z_int <= (others => '0');
78                         z_sign_int <= '0';
79                         strich_int <= (others => '0');
80                         punkt_int <= (others => '0');
81                         wtmp_int <= (others => '0');
82                         rbyte_int <= (others => '0');
83                         aktop_int <= ALU_NOP;
84                         opp_int <= ALU_NOP;
85                         err_int <= 0;
86                         errc_int <= 70;
87                         errc_tmp_int <= 0;
88                         firstz_int <= true;
89                         -- out ports
90                         p_rw <= '0';
91                         p_spalte <= (others => '0');
92                         p_rget_int <= '0';
93                         p_write_int <= (others => '0');
94                         p_wtake_int <= '0';
95                         p_finished_int <= '0';
96                         opcode_int <= ALU_NOP;
97                         op1_int <= (others => '0');
98                         op2_int <= (others => '0');
99                         do_calc_int <= '0';
100                         finished <= '0';
101                 elsif rising_edge(sys_clk) then
102                         -- internal
103                         state_int <= state_next;
104                         z_int <= z_next;
105                         z_sign_int <= z_sign_next;
106                         strich_int <= strich_next;
107                         punkt_int <= punkt_next;
108                         wtmp_int <= wtmp_next;
109                         rbyte_int <= rbyte_next;
110                         aktop_int <= aktop_next;
111                         opp_int <= opp_next;
112                         err_int <= err_next;
113                         errc_int <= errc_next;
114                         errc_tmp_int <= errc_tmp_next;
115                         firstz_int <= firstz_next;
116                         -- out ports
117                         p_rget_int <= p_rget_next;
118                         p_write_int <= p_write_next;
119                         p_wtake_int <= p_wtake_next;
120                         p_finished_int <= p_finished_next;
121                         opcode_int <= opcode_next;
122                         op1_int <= op1_next;
123                         op2_int <= op2_next;
124                         do_calc_int <= do_calc_next;
125                 end if;
126         end process;
127
128         -- next state
129         process(state_int, do_it, p_rdone, p_wdone, p_read, aktop_int, strich_int,
130                 punkt_int, calc_done, wtmp_int, opp_int, goto_calcn1, goto_op1,
131                 goto_space3, goto_sign, z_sign_int, err_int, errc_int, calc_error,
132                 op2_int)
133         begin
134                 state_next <= state_int;
135
136                 case state_int is
137                         when SIDLE =>
138                                 if do_it = '1' then
139                                         state_next <= SREAD_NEWNUMBER;
140                                 end if;
141                         when SREAD_NEWNUMBER =>
142                                 state_next <= SREAD_SPACE1_2;
143                         when SREAD_SPACE1_2 =>
144                                 if p_rdone = '1' then
145                                         state_next <= SREAD_SPACE2;
146                                 end if;
147                         when SREAD_SPACE1_3 =>
148                                 if p_rdone = '1' then
149                                         state_next <= SREAD_SPACE3;
150                                 end if;
151                         when SREAD_SPACE2 | SREAD_SPACE3 =>
152                                 if goto_calcn1 = '1' then
153                                         case state_int is
154                                                 when SREAD_SPACE2 => state_next <= SREAD_NEXTBYTE;
155                                                 when SREAD_SPACE3 => state_next <= SREAD_OP1;
156                                                 when others => assert(false) report "wtf @ state2";
157                                         end case;
158                                 end if;
159                                 if goto_sign = '1' then
160                                         case state_int is
161                                                 when SREAD_SPACE2 => state_next <= SREAD_SIGN1;
162                                                 when others => assert(false) report "wtf @ state3";
163                                         end case;
164                                 end if;
165                                 if p_rdone = '0' then
166                                         if goto_calcn1 = '0' then
167                                                 case state_int is
168                                                         when SREAD_SPACE2 => state_next <= SREAD_SPACE1_2;
169                                                         when SREAD_SPACE3 => state_next <= SREAD_SPACE1_3;
170                                                         when others => assert(false) report "wtf @ state1";
171                                                 end case;
172                                         end if;
173                                 end if;
174                         when SREAD_SIGN1 =>
175                                 if p_rdone = '0' then
176                                         state_next <= SREAD_NEXTBYTE;
177                                 end if;
178                         when SREAD_NEXTBYTE =>
179                                 if p_rdone = '1' then
180                                         state_next <= SREAD_CALCNUMBER1;
181                                 end if;
182                         when SREAD_CALCNUMBER1 =>
183                                 if goto_op1 = '1' then
184                                         state_next <= SREAD_OP1;
185                                 elsif goto_space3 = '1' then
186                                         state_next <= SREAD_SPACE3;
187                                 elsif calc_done = '1' then
188                                         state_next <= SREAD_CALCNUMBER2;
189                                 end if;
190                         when SREAD_OP1 =>
191                                 state_next <= SREAD_OP2;
192                         when SREAD_OP2 =>
193                                 if p_rdone = '0' then
194                                         if aktop_int /= ALU_NOP then
195                                                 state_next <= SCALC_1;
196                                         end if;
197                                 end if;
198                         when SREAD_CALCNUMBER2 =>
199                                 if p_rdone = '0' and calc_done = '0' then
200                                         state_next <= SREAD_NEXTBYTE;
201                                 end if;
202                         when SCALC_1 =>
203                                 if calc_done = '1' then
204                                         case opp_int is
205                                                 -- spezialfall: eine zwischenberechnung wird fuer diese
206                                                 -- kombination benoetigt
207                                                 when ALU_MUL | ALU_DIV =>
208                                                         case aktop_int is
209                                                                 when ALU_ADD | ALU_SUB | ALU_DONE => state_next <= SCALC_14;
210                                                                 when others => state_next <= SCALC_2;
211                                                         end case;
212                                                 when others => state_next <= SCALC_2;
213                                         end case;
214                                 end if;
215                         when SCALC_14 =>
216                                 if calc_done = '0' then
217                                         state_next <= SCALC_15;
218                                 end if;
219                         when SCALC_15 =>
220                                 if calc_done = '1' then
221                                         state_next <= SCALC_2;
222                                 end if;
223                         when SCALC_2 =>
224                                 if calc_done = '0' then
225                                         if aktop_int = ALU_DONE then
226                                                 state_next <= SWRITE_CHAR2;
227                                         else
228                                                 state_next <= SREAD_NEWNUMBER;
229                                         end if;
230                                 end if;
231                         when SWRITE_CHAR0 =>
232                                 if calc_done = '1' then
233                                         state_next <= SWRITE_CHAR1;
234                                 end if;
235                         when SWRITE_CHAR1 =>
236                                 if p_wdone = '1' then
237                                         if strich_int < 10 then
238                                                 if z_sign_int = '1' then
239                                                         state_next <= SWRITE_SIGN1;
240                                                 else
241                                                         state_next <= SDONE;
242                                                 end if;
243                                         else
244                                                 state_next <= SWRITE_CHAR2;
245                                         end if;
246                                 end if;
247                         when SERROR1 =>
248                                 if p_wdone = '1' then
249                                         if errc_int <= 2 then
250                                                 state_next <= SDONE;
251                                         else
252                                                 state_next <= SERROR2;
253                                         end if;
254                                 end if;
255                         when SERROR2 =>
256                                 if p_wdone = '0' then
257                                         state_next <= SERROR1;
258                                 end if;
259                         when SWRITE_CHAR2 =>
260                                 if p_wdone = '0' and calc_done = '0' then
261                                         state_next <= SWRITE_CHAR0;
262                                 end if;
263                         when SWRITE_SIGN1 =>
264                                 if p_wdone = '0' then
265                                         state_next <= SWRITE_SIGN2;
266                                 end if;
267                         when SWRITE_SIGN2 =>
268                                 if p_wdone = '1' then
269                                         state_next <= SDONE;
270                                 end if;
271
272                         when SDONE =>
273                                 if p_wdone = '0' and do_it = '0' then
274                                         state_next <= SIDLE;
275                                 end if;
276                 end case;
277
278                 -- fehlerbehandlung
279                 case state_int is
280                         when SERROR1 | SERROR2 | SDONE => null;
281                         when others =>
282                                 if err_int > 0 then
283                                         state_next <= SERROR1;
284                                 end if;
285                 end case;
286         end process;
287
288         -- out
289         process(state_int, p_read, p_write_int, z_int, rbyte_int, p_rget_int,
290                 strich_int, aktop_int, opp_int, opcode_int, op1_int, op2_int, op3, opM,
291                 do_calc_int, wtmp_int, punkt_int, z_sign_int, err_int, errc_int,
292                 errc_tmp_int, firstz_int, calc_done, calc_error)
293                 function hbyte2csigned (x : hbyte) return csigned is
294                         variable y : csigned;
295                 begin
296                         case x is
297                                 when x"30" => y := x"00000000";
298                                 when x"31" => y := x"00000001";
299                                 when x"32" => y := x"00000002";
300                                 when x"33" => y := x"00000003";
301                                 when x"34" => y := x"00000004";
302                                 when x"35" => y := x"00000005";
303                                 when x"36" => y := x"00000006";
304                                 when x"37" => y := x"00000007";
305                                 when x"38" => y := x"00000008";
306                                 when x"39" => y := x"00000009";
307                                 when others => assert(false) report "hbyte2csigned: shouldn't happen";
308                         end case;
309                         return y;
310                 end function hbyte2csigned;
311
312                 function csigned2hbyte (x : csigned) return hbyte is
313                         variable y : hbyte;
314                 begin
315                         case x is
316                                 when x"00000000" => y := x"30";
317                                 when x"00000001" => y := x"31";
318                                 when x"00000002" => y := x"32";
319                                 when x"00000003" => y := x"33";
320                                 when x"00000004" => y := x"34";
321                                 when x"00000005" => y := x"35";
322                                 when x"00000006" => y := x"36";
323                                 when x"00000007" => y := x"37";
324                                 when x"00000008" => y := x"38";
325                                 when x"00000009" => y := x"39";
326                                 when others => assert(false) report "csigned2hbyte: shouldn't happen";
327                         end case;
328                         return y;
329                 end function csigned2hbyte;
330
331
332                 variable multmp : signed(((2*CBITS)-1) downto 0);
333                 variable tmp : csigned;
334
335                 type errstrings is array (natural range 1 to 3) of hstring;
336                 constant error_str : errstrings := (
337                         1 => "                                                   Division durch Null" & nul,
338                         2 => "                                                                Syntax" & nul,
339                         3 => "                                                  Over- bzw. Underflow" & nul
340                 );
341         begin
342                 -- internal
343                 z_next <= z_int;
344                 z_sign_next <= z_sign_int;
345                 strich_next <= strich_int;
346                 punkt_next <= punkt_int;
347                 wtmp_next <= wtmp_int;
348                 rbyte_next <= rbyte_int;
349                 aktop_next <= aktop_int;
350                 opp_next <= opp_int;
351                 err_next <= err_int;
352                 errc_next <= errc_int;
353                 errc_tmp_next <= errc_tmp_int;
354                 firstz_next <= firstz_int;
355                 -- signals
356                 p_rget_next <= '0';
357                 p_write_next <= p_write_int;
358                 p_wtake_next <= '0';
359                 p_finished_next <= '0';
360                 opcode_next <= opcode_int;
361                 op1_next <= op1_int;
362                 op2_next <= op2_int;
363                 do_calc_next <= '0';
364                 goto_calcn1 <= '0';
365                 goto_op1 <= '0';
366                 goto_space3 <= '0';
367                 goto_sign <= '0';
368
369                 case state_int is
370                         when SIDLE =>
371                                 strich_next <= (others => '0');
372                                 punkt_next <= (0 => '1', others => '0');
373                                 opp_next <= ALU_NOP;
374                         when SREAD_NEWNUMBER =>
375                                 z_next <= (others => '0');
376                                 z_sign_next <= '0';
377                                 firstz_next <= true;
378                                 rbyte_next <= (others => '0');
379                                 p_write_next <= (others => '0');
380                                 aktop_next <= ALU_NOP;
381                         when SREAD_NEXTBYTE | SREAD_SPACE1_2 | SREAD_SPACE1_3 =>
382                                 p_rget_next <= '1';
383                         when SREAD_SPACE2 | SREAD_SPACE3 =>
384                                 case p_read is
385                                         when x"20" =>
386                                                 null;
387                                         when x"2D" =>
388                                                 case state_int is
389                                                         when SREAD_SPACE2 => goto_sign <= '1';
390                                                         when SREAD_SPACE3 => goto_calcn1 <= '1'; p_rget_next <= '1';
391                                                         when others => assert(false) report "SREAD_SPACE2/3: shouldn't happen";
392                                                 end case;
393                                         when others =>
394                                                 goto_calcn1 <= '1';
395                                                 p_rget_next <= '1';
396                                 end case;
397
398                         when SREAD_CALCNUMBER1 =>
399                                 case p_read is
400                                         -- '+', '-', '*', '/'
401                                         when x"2B" | x"2D" | x"2A" | x"2F" | x"00" =>
402                                                 if firstz_int then
403                                                         err_next <= 2;
404                                                 else
405                                                         goto_op1 <= '1';
406                                                         p_rget_next <= '1';
407                                                 end if;
408
409                                         -- ' '
410                                         when x"20" =>
411                                                 goto_space3 <= '1';
412                                                 p_rget_next <= '1';
413
414                                         when others =>
415                                                 op1_next <= z_int;
416                                                 opcode_next <= ALU_MUL;
417                                                 op2_next <= to_signed(10,CBITS);
418                                                 firstz_next <= false;
419                                                 do_calc_next <= '1';
420                                 end case;
421                         when SREAD_SIGN1 =>
422                                 z_sign_next <= '1';
423                         when SREAD_CALCNUMBER2 =>
424                                 z_next <= op3 + hbyte2csigned(p_read);
425                         when SREAD_OP2 =>
426                                 null;
427                         when SREAD_OP1 =>
428                                 case p_read is
429                                         when x"2B" => aktop_next <= ALU_ADD; -- '+'
430                                         when x"2D" => aktop_next <= ALU_SUB; -- '-'
431                                         when x"2A" => aktop_next <= ALU_MUL; -- '*'
432                                         when x"2F" => aktop_next <= ALU_DIV; -- '/'
433                                         when x"00" => aktop_next <= ALU_DONE; -- '\0'
434
435                                         when others => err_next <= 2;
436                                 end case;
437
438
439                         when SCALC_1 =>
440                                 if z_sign_int = '1' then
441                                         tmp := (not z_int) + 1;
442                                         z_next <= tmp;
443                                         z_sign_next <= '0';
444                                 else
445                                         tmp := z_int;
446                                 end if;
447
448                                 case opp_int is
449                                         when ALU_NOP | ALU_ADD | ALU_SUB =>
450                                                 case opp_int  is
451                                                         when ALU_SUB => op1_next <= (not tmp) + 1;
452                                                         when others => op1_next <= tmp;
453                                                 end case;
454                                                 case aktop_int is
455                                                         when ALU_ADD | ALU_SUB | ALU_DONE =>
456                                                                 opcode_next <= ALU_ADD;
457                                                                 op2_next <= strich_int;
458                                                         when ALU_MUL | ALU_DIV =>
459                                                                 opcode_next <= ALU_MUL;
460                                                                 op2_next <= punkt_int;
461                                                         when others => assert(false) report "SCALC_1/1: shouldn't happen!";
462                                                 end case;
463
464                                         when ALU_MUL | ALU_DIV =>
465                                                 case aktop_int is
466                                                         when ALU_ADD | ALU_SUB | ALU_DONE | ALU_MUL | ALU_DIV =>
467                                                                 op1_next <= punkt_int;
468                                                                 opcode_next <= opp_int;
469                                                                 op2_next <= tmp;
470                                                         when others => assert(false) report "SCALC_1/2: shouldn't happen!";
471                                                 end case;
472                                         when others => assert(false) report "SCALC_1/3: shouldn't happen!";
473                                 end case;
474                                 do_calc_next <= '1';
475
476                         when SCALC_14 =>
477                                 -- ueberpruefung kann man sich sparen, da diese ohnehin in
478                                 -- nextstate gemacht wird.
479                                 op1_next <= op3;
480                                 do_calc_next <= '0';
481
482                         when SCALC_15 =>
483                                 -- ueberpruefung kann man sich sparen, da diese ohnehin in
484                                 -- nextstate gemacht wird.
485                                 opcode_next <= ALU_ADD;
486                                 op2_next <= strich_int;
487                                 punkt_next <= (0 => '1', others => '0');
488                                 do_calc_next <= '1';
489
490                         when SCALC_2 =>
491                                 case opp_int is
492                                         when ALU_NOP | ALU_ADD | ALU_SUB | ALU_MUL | ALU_DIV =>
493                                                 case aktop_int is
494                                                         when ALU_ADD | ALU_SUB | ALU_DONE =>
495                                                                 if aktop_int = ALU_DONE and op3 < 0 then
496                                                                         strich_next <= (not op3) + 1;
497                                                                         wtmp_next <= (not op3) + 1;
498                                                                         z_sign_next <= '1';
499                                                                 else
500                                                                         strich_next <= op3;
501                                                                         wtmp_next <= op3;
502                                                                 end if;
503                                                         when ALU_MUL | ALU_DIV =>
504                                                                 punkt_next <= op3;
505                                                         when others => assert (false) report "SCALC_2/1: shouldn't happen!";
506                                                 end case;
507                                         when others => assert (false) report "SCALC_2/2: shouldn't happen!";
508                                 end case;
509                                 -- aktuelle rechenoperation fuer naechste 'runde' uebernehmen
510                                 opp_next <= aktop_int;
511
512                         when SWRITE_CHAR0 =>
513                                 op1_next <= strich_int;
514                                 opcode_next <= ALU_DIV;
515                                 op2_next <= to_signed(10,CBITS);
516                                 do_calc_next <= '1';
517                         when SWRITE_CHAR1 =>
518                                 do_calc_next <= '1';
519                                 p_wtake_next <= '1';
520                                 tmp := opM;
521                                 p_write_next <= csigned2hbyte(tmp);
522                                 wtmp_next <= op3;
523                         when SWRITE_CHAR2 =>
524                                 strich_next <= wtmp_int;
525
526                         when SWRITE_SIGN1 =>
527                                 null;
528                         when SWRITE_SIGN2 =>
529                                 if z_sign_int = '1' then
530                                         p_wtake_next <= '1';
531                                         p_write_next <= x"2D";
532                                 else
533                                         assert(false) report "SWRITE_SIGN: shouldn't happen!";
534                                 end if;
535
536                         when SERROR1 =>
537                                 p_wtake_next <= '1';
538                                 p_write_next <= hbyte(to_unsigned (character'pos(error_str(err_int)(errc_int)),8));
539                                 errc_tmp_next <= errc_int - 1;
540                         when SERROR2 =>
541                                 errc_next <= errc_tmp_int;
542
543                         when SDONE =>
544                                 err_next <= 0;
545                                 errc_next <= 70;
546                                 p_finished_next <= '1';
547                 end case;
548
549                 -- fehlerbehandlung
550                 case state_int is
551                         when SERROR1 | SERROR2 | SDONE => null;
552                         when others =>
553                                 if calc_error = '1' then
554                                         if op2_int = 0 then
555                                                 err_next <= 1;
556                                         else
557                                                 err_next <= 3;
558                                         end if;
559                                 end if;
560                 end case;
561         end process;
562 end architecture beh;