parser: vereinfachungen und kleinere verbesserungen
[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_NEXTBYTE,
37         SREAD_CALCNUMBER1, SREAD_CALCNUMBER2, SCALC_1, SCALC_14, SCALC_15, SCALC_2, SWRITE_CHAR1,
38         SWRITE_CHAR2, SDONE, SERROR1, SERROR2);
39         signal state_int, state_next : PARSER_STATE;
40         signal z_int, z_next, strich_int, strich_next, wtmp_int, wtmp_next : csigned;
41         signal punkt_int, punkt_next : csigned;
42         signal rbyte_int, rbyte_next : hbyte;
43         signal p_write_int, p_write_next : hbyte;
44         signal p_rget_int, p_rget_next : std_logic;
45         signal p_wtake_int, p_wtake_next : std_logic;
46         signal p_finished_int, p_finished_next : std_logic;
47         signal aktop_int, aktop_next : alu_ops;
48         signal opp_int, opp_next : alu_ops;
49         signal opcode_int, opcode_next : alu_ops;
50         signal op1_int, op1_next : csigned;
51         signal op2_int, op2_next : csigned;
52         signal do_calc_int, do_calc_next : std_logic;
53 begin
54         p_write <= p_write_int;
55         p_rget <= p_rget_int;
56         p_wtake <= p_wtake_int;
57         p_finished <= p_finished_int;
58
59         opcode <= opcode_int;
60         op1 <= op1_int;
61         op2 <= op2_int;
62         do_calc <= do_calc_int;
63
64         process(sys_clk, sys_res_n)
65         begin
66                 if sys_res_n = '0' then
67                         state_int <= SIDLE;
68                         z_int <= (others => '0');
69                         strich_int <= (others => '0');
70                         punkt_int <= (others => '0');
71                         wtmp_int <= (others => '0');
72                         rbyte_int <= (others => '0');
73                         aktop_int <= ALU_NOP;
74                         opp_int <= ALU_NOP;
75                         -- out ports
76                         p_rw <= '0';
77                         p_spalte <= (others => '0');
78                         p_rget_int <= '0';
79                         p_write_int <= (others => '0');
80                         p_wtake_int <= '0';
81                         p_finished_int <= '0';
82                         opcode_int <= ALU_NOP;
83                         op1_int <= (others => '0');
84                         op2_int <= (others => '0');
85                         do_calc_int <= '0';
86                         finished <= '0';
87                 elsif rising_edge(sys_clk) then
88                         -- internal
89                         state_int <= state_next;
90                         z_int <= z_next;
91                         strich_int <= strich_next;
92                         punkt_int <= punkt_next;
93                         wtmp_int <= wtmp_next;
94                         rbyte_int <= rbyte_next;
95                         aktop_int <= aktop_next;
96                         opp_int <= opp_next;
97                         -- out ports
98                         p_rget_int <= p_rget_next;
99                         p_write_int <= p_write_next;
100                         p_wtake_int <= p_wtake_next;
101                         p_finished_int <= p_finished_next;
102                         opcode_int <= opcode_next;
103                         op1_int <= op1_next;
104                         op2_int <= op2_next;
105                         do_calc_int <= do_calc_next;
106                 end if;
107         end process;
108
109         -- next state
110         process(state_int, do_it, p_rdone, p_wdone, p_read, aktop_int, strich_int,
111                 punkt_int, calc_done, wtmp_int, opp_int)
112         begin
113                 state_next <= state_int;
114
115                 case state_int is
116                         when SIDLE =>
117                                 if do_it = '1' then
118                                         state_next <= SREAD_NEWNUMBER;
119                                 end if;
120                         when SREAD_NEWNUMBER =>
121                                 state_next <= SREAD_NEXTBYTE;
122                         when SREAD_NEXTBYTE =>
123                                 if p_rdone = '1' then
124                                         state_next <= SREAD_CALCNUMBER1;
125                                 end if;
126                         when SREAD_CALCNUMBER1 =>
127                                 state_next <= SREAD_CALCNUMBER2;
128                         when SREAD_CALCNUMBER2 =>
129                                 if p_rdone = '0' then
130                                         if aktop_int /= ALU_NOP then
131                                                 state_next <= SCALC_1;
132                                         else
133                                                 state_next <= SREAD_NEXTBYTE;
134                                         end if;
135                                 end if;
136                         when SCALC_1 =>
137                                 if calc_done = '1' then
138                                         case opp_int is
139                                                 -- spezialfall: eine zwischenberechnung wird fuer diese
140                                                 -- kombination benoetigt
141                                                 when ALU_MUL | ALU_DIV =>
142                                                         case aktop_int is
143                                                                 when ALU_ADD | ALU_SUB | ALU_DONE => state_next <= SCALC_14;
144                                                                 when others => state_next <= SCALC_2;
145                                                         end case;
146                                                 when others => state_next <= SCALC_2;
147                                         end case;
148                                 end if;
149                         when SCALC_14 =>
150                                 if calc_done = '0' then
151                                         state_next <= SCALC_15;
152                                 end if;
153                         when SCALC_15 =>
154                                 if calc_done = '1' then
155                                         state_next <= SCALC_2;
156                                 end if;
157                         when SCALC_2 =>
158                                 if aktop_int = ALU_DONE then
159                                         state_next <= SWRITE_CHAR1;
160                                 else
161                                         state_next <= SREAD_NEWNUMBER;
162                                 end if;
163                         when SWRITE_CHAR1 =>
164                                 if p_wdone = '1' then
165                                         if strich_int < 10 then
166                                                 state_next <= SDONE;
167                                         else
168                                                 state_next <= SWRITE_CHAR2;
169                                         end if;
170                                 end if;
171                         when SERROR1 =>
172                                 if p_wdone = '1' then
173                                         -- TODO 
174                                         if strich_int < 10 then
175                                                 state_next <= SDONE;
176                                         else
177                                                 state_next <= SWRITE_CHAR2;
178                                         end if;
179                                 end if;
180                         when SWRITE_CHAR2 | SERROR2 =>
181                                 if p_wdone = '0' then
182                                         state_next <= SWRITE_CHAR1;
183                                 end if;
184                         when SDONE =>
185                                 if p_wdone = '0' and do_it = '0' then
186                                         state_next <= SIDLE;
187                                 end if;
188                 end case;
189         end process;
190
191         -- out
192         process(state_int, p_read, p_write_int, z_int, rbyte_int, p_rget_int,
193                 strich_int, aktop_int, opp_int, opcode_int, op1_int, op2_int, op3,
194                 do_calc_int, wtmp_int, punkt_int)
195                 function hbyte2csigned (x : hbyte) return csigned is
196                         variable y : csigned;
197                 begin
198                         case x is
199                                 when x"30" => y := to_signed(0, CBITS);
200                                 when x"31" => y := to_signed(1, CBITS);
201                                 when x"32" => y := to_signed(2, CBITS);
202                                 when x"33" => y := to_signed(3, CBITS);
203                                 when x"34" => y := to_signed(4, CBITS);
204                                 when x"35" => y := to_signed(5, CBITS);
205                                 when x"36" => y := to_signed(6, CBITS);
206                                 when x"37" => y := to_signed(7, CBITS);
207                                 when x"38" => y := to_signed(8, CBITS);
208                                 when x"39" => y := to_signed(9, CBITS);
209                                 when others => assert(false) report "hbyte2csigned: shouldn't happen";
210                         end case;
211                         return y;
212                 end function hbyte2csigned;
213
214                 function csigned2hbyte (x : csigned) return hbyte is
215                         variable y : hbyte;
216                 begin
217                         case x is
218                                 when x"00000000" => y := x"30";
219                                 when x"00000001" => y := x"31";
220                                 when x"00000002" => y := x"32";
221                                 when x"00000003" => y := x"33";
222                                 when x"00000004" => y := x"34";
223                                 when x"00000005" => y := x"35";
224                                 when x"00000006" => y := x"36";
225                                 when x"00000007" => y := x"37";
226                                 when x"00000008" => y := x"38";
227                                 when x"00000009" => y := x"39";
228                                 when others => assert(false) report "csigned2hbyte: shouldn't happen";
229                         end case;
230                         return y;
231                 end function csigned2hbyte;
232
233                 variable multmp : signed(((2*CBITS)-1) downto 0);
234                 variable tmp : csigned;
235         begin
236                 -- internal
237                 z_next <= z_int;
238                 strich_next <= strich_int;
239                 punkt_next <= punkt_int;
240                 wtmp_next <= wtmp_int;
241                 rbyte_next <= rbyte_int;
242                 aktop_next <= aktop_int;
243                 opp_next <= opp_int;
244                 -- signals
245                 p_rget_next <= '0';
246                 p_write_next <= p_write_int;
247                 p_wtake_next <= '0';
248                 p_finished_next <= '0';
249                 opcode_next <= opcode_int;
250                 op1_next <= op1_int;
251                 op2_next <= op2_int;
252                 do_calc_next <= '0';
253
254                 case state_int is
255                         when SIDLE =>
256                                 strich_next <= (others => '0');
257                                 punkt_next <= (0 => '1', others => '0');
258                                 opp_next <= ALU_NOP;
259                         when SREAD_NEWNUMBER =>
260                                 z_next <= (others => '0');
261                                 rbyte_next <= (others => '0');
262                                 p_write_next <= (others => '0');
263                                 aktop_next <= ALU_NOP;
264                         when SREAD_NEXTBYTE =>
265                                 p_rget_next <= '1';
266                         when SREAD_CALCNUMBER1 =>
267                                 case p_read is
268                                         -- '+'
269                                         when x"2B" =>
270                                                 aktop_next <= ALU_ADD;
271                                         -- '-'
272                                         when x"2D" =>
273                                                 -- TODO: sign check beim ersten byte lesen!
274                                                 aktop_next <= ALU_SUB;
275                                         -- '*'
276                                         when x"2A" =>
277                                                 aktop_next <= ALU_MUL;
278                                         -- '/'
279                                         when x"2F" =>
280                                                 aktop_next <= ALU_DIV;
281
282                                         -- '\0'
283                                         when x"00" =>
284                                                 aktop_next <= ALU_DONE;
285
286                                         when others =>
287                                                 -- TODO: check auf overflow
288                                                 multmp := (z_int * 10) + hbyte2csigned(p_read);
289                                                 z_next <= multmp((CBITS-1) downto 0);
290                                 end case;
291                         when SREAD_CALCNUMBER2 =>
292                                 null;
293
294                         when SCALC_1 =>
295                                 case opp_int is
296                                         when ALU_NOP | ALU_ADD | ALU_SUB =>
297                                                 case opp_int  is
298                                                         when ALU_SUB => op1_next <= (not z_int) + 1;
299                                                         when others => op1_next <= z_int;
300                                                 end case;
301                                                 case aktop_int is
302                                                         when ALU_ADD | ALU_SUB | ALU_DONE =>
303                                                                 opcode_next <= ALU_ADD;
304                                                                 op2_next <= strich_int;
305                                                         when ALU_MUL | ALU_DIV =>
306                                                                 opcode_next <= ALU_MUL;
307                                                                 op2_next <= punkt_int;
308                                                         when others => assert(false) report "SCALC_1/1: shouldn't happen!";
309                                                 end case;
310
311                                         when ALU_MUL | ALU_DIV =>
312                                                 case aktop_int is
313                                                         when ALU_ADD | ALU_SUB | ALU_DONE | ALU_MUL | ALU_DIV =>
314                                                                 op1_next <= punkt_int;
315                                                                 opcode_next <= opp_int;
316                                                                 op2_next <= z_int;
317                                                         when others => assert(false) report "SCALC_1/2: shouldn't happen!";
318                                                 end case;
319                                         when others => assert(false) report "SCALC_1/3: shouldn't happen!";
320                                 end case;
321                                 do_calc_next <= '1';
322
323                         when SCALC_14 =>
324                                 -- ueberpruefung kann man sich sparen, da diese ohnehin in
325                                 -- nextstate gemacht wird.
326                                 op1_next <= op3;
327                                 do_calc_next <= '0';
328
329                         when SCALC_15 =>
330                                 -- ueberpruefung kann man sich sparen, da diese ohnehin in
331                                 -- nextstate gemacht wird.
332                                 opcode_next <= ALU_ADD;
333                                 op2_next <= strich_int;
334                                 punkt_next <= (0 => '1', others => '0');
335                                 do_calc_next <= '1';
336
337                         when SCALC_2 =>
338                                 case opp_int is
339                                         when ALU_NOP | ALU_ADD | ALU_SUB | ALU_MUL | ALU_DIV =>
340                                                 case aktop_int is
341                                                         when ALU_ADD | ALU_SUB | ALU_DONE =>
342                                                                 strich_next <= op3;
343                                                         when ALU_MUL | ALU_DIV =>
344                                                                 punkt_next <= op3;
345                                                         when others => assert (false) report "SCALC_2/1: shouldn't happen!";
346                                                 end case;
347                                         when others => assert (false) report "SCALC_2/2: shouldn't happen!";
348                                 end case;
349                                 -- aktuelle rechenoperation fuer naechste 'runde' uebernehmen
350                                 opp_next <= aktop_int;
351
352                         when SWRITE_CHAR1 =>
353                                 p_wtake_next <= '1';
354                                 tmp := strich_int mod 10;
355                                 p_write_next <= csigned2hbyte(tmp);
356                                 wtmp_next <= strich_int / 10;
357                         when SWRITE_CHAR2 =>
358                                 strich_next <= wtmp_int;
359
360                         when SERROR1 =>
361                                 -- TODO
362                                 null;
363                         when SERROR2 =>
364                                 -- TODO
365                                 null;
366
367                         when SDONE =>
368                                 p_finished_next <= '1';
369                 end case;
370         end process;
371 end architecture beh;