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