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