abeedb9806ef1e2371a876e229f4eeb6f8f66922
[calu.git] / cpu / src / decoder_b.vhd
1 --   `Deep Thought', a softcore CPU implemented on a FPGA
2 --
3 --  Copyright (C) 2010 Markus Hofstaetter <markus.manrow@gmx.at>
4 --  Copyright (C) 2010 Martin Perner <e0725782@student.tuwien.ac.at>
5 --  Copyright (C) 2010 Stefan Rebernig <stefan.rebernig@gmail.com>
6 --  Copyright (C) 2010 Manfred Schwarz <e0725898@student.tuwien.ac.at>
7 --  Copyright (C) 2010 Bernhard Urban <lewurm@gmail.com>
8 --
9 --  This program is free software: you can redistribute it and/or modify
10 --  it under the terms of the GNU General Public License as published by
11 --  the Free Software Foundation, either version 3 of the License, or
12 --  (at your option) any later version.
13 --
14 --  This program is distributed in the hope that it will be useful,
15 --  but WITHOUT ANY WARRANTY; without even the implied warranty of
16 --  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 --  GNU General Public License for more details.
18 --
19 --  You should have received a copy of the GNU General Public License
20 --  along with this program.  If not, see <http://www.gnu.org/licenses/>.
21
22 library IEEE;
23 use IEEE.std_logic_1164.all;
24 use IEEE.numeric_std.all;
25
26 use work.mem_pkg.all;
27 use work.core_pkg.all;
28 use work.common_pkg.all;
29
30
31 architecture behav_d of decoder is
32
33 begin
34
35 split_instr: process(instruction)
36
37 variable instr_s : instruction_rec;
38
39 begin
40
41         instr_s.predicates := instruction(31 downto 28);
42         instr_s.opcode := instruction(27 downto 27-OPCODE_WIDTH+1);
43
44         instr_s.reg_dest_addr := (others => '0');
45         instr_s.reg_src1_addr := (others => '0');
46         instr_s.reg_src2_addr := (others => '0');
47
48         instr_s.immediate := (others => '0');
49         instr_s.jmptype := (others => '0');
50         instr_s.high_low := '0';
51         instr_s.fill := '0';
52         instr_s.signext := '0';
53         instr_s.bp := '0';
54         instr_s.op_detail := (others => '0');
55         instr_s.displacement := (others => '0');
56         instr_s.int := '0';
57
58         instr_s.op_group := ADDSUB_OP;
59
60 --      type op_info_t is (ADDSUB_OP,AND_OP,OR_OP, XOR_OP,SHIFT_OP);
61
62 --  special function register operations missing
63
64 --      case opcode is
65 --=================================================================
66         if (instr_s.opcode = "00000" or instr_s.opcode = "00001" or instr_s.opcode = "00100" or instr_s.opcode = "00110" or instr_s.opcode = "01000") then
67 --      when "00000" =>         --add
68                 instr_s.reg_dest_addr := instruction(22 downto 19);
69                 instr_s.reg_src1_addr := instruction(18 downto 15);
70                 instr_s.reg_src2_addr := instruction(14 downto 11);
71
72                 instr_s.op_detail(NO_PSW_OPT) := instruction(0); --instr_s.sreg_update;
73                 
74                 instr_s.op_group := ADDSUB_OP;
75
76                 if (instr_s.opcode = "00000") then              
77                         instr_s.op_detail(CARRY_OPT) := instruction(1); --instr_s.carry;
78                 end if;
79
80                 if (instr_s.opcode = "00001") then
81                         instr_s.op_detail(SUB_OPT) := '1';
82                         instr_s.op_detail(CARRY_OPT) := instruction(1); --instr_s.carry;
83                 end if;
84
85                 if (instr_s.opcode = "00100") then
86                         instr_s.op_group := AND_OP;
87                 end if;
88                 
89                 if (instr_s.opcode = "00110") then
90                         instr_s.op_group := OR_OP;
91                 end if;
92                 
93                 if (instr_s.opcode = "01000") then
94                         instr_s.op_group := XOR_OP;
95                 end if;
96
97         end if;
98 --      when "00001" =>         --sub
99 --              instr_s.reg_dest_addr := instruction(22 downto 19);
100 --              instr_s.reg_src1_addr := instruction(18 downto 15);
101 --              instr_s.reg_src2_addr := instruction(14 downto 11);
102 --              instr_s.carry := instruction(1);
103 --              instr_s.sreg_update := instruction(0);
104
105
106 --      when "00100" =>         --and
107 --              instr_s.reg_dest_addr := instruction(22 downto 19);
108 --              instr_s.reg_src1_addr := instruction(18 downto 15);
109 --              instr_s.reg_src2_addr := instruction(14 downto 11);
110 --              instr_s.carry := instruction(1);                        --negligible
111 --              instr_s.sreg_update := instruction(0);
112
113 --      when "00110" =>         --or
114 --              instr_s.reg_dest_addr := instruction(22 downto 19);
115 --              instr_s.reg_src1_addr := instruction(18 downto 15);
116 --              instr_s.reg_src2_addr := instruction(14 downto 11);
117 --              instr_s.carry := instruction(1);                        --negligible
118 --              instr_s.sreg_update := instruction(0);
119
120 --      when "01000" =>         --xor
121 --              instr_s.reg_dest_addr := instruction(22 downto 19);
122 --              instr_s.reg_src1_addr := instruction(18 downto 15);
123 --              instr_s.reg_src2_addr := instruction(14 downto 11);
124 --              instr_s.carry := instruction(1);                        --negligible
125 --              instr_s.sreg_update := instruction(0);
126
127 --=================================================================
128         if (instr_s.opcode = "00010" or instr_s.opcode = "00011") then
129
130 --      when "00010" =>         --addi
131                 instr_s.reg_dest_addr := instruction(22 downto 19);
132                 instr_s.reg_src1_addr := instruction(18 downto 15);
133                 instr_s.immediate(11 downto 0) := instruction(14 downto 3);
134                 instr_s.signext := instruction(2);              
135
136                 if (instr_s.signext = '1' and instr_s.immediate(11) = '1') then
137                         instr_s.immediate(31 downto 12) := (others => '1');
138                 end if;
139
140                 instr_s.op_detail(IMM_OPT) := '1';
141                 instr_s.op_detail(CARRY_OPT) := instruction(1);
142                 instr_s.op_detail(NO_PSW_OPT) := instruction(0);
143
144                 instr_s.op_group := ADDSUB_OP;
145
146                 if (instr_s.opcode = "00011") then
147                         instr_s.op_detail(SUB_OPT) := '1';
148                 end if;
149         end if;
150
151 --      when "00011" =>         --subi
152 --              instr_s.reg_dest_addr := instruction(22 downto 19);
153 --              instr_s.reg_src1_addr := instruction(18 downto 15);
154 --              instr_s.immediate(11 downto 0) := instruction(14 downto 3);
155 --              instr_s.signext := instruction(2);              
156 --              instr_s.carry := instruction(1);
157 --              instr_s.sreg_update := instruction(0);
158
159
160
161
162 --=================================================================
163         if (instr_s.opcode = "00101" or instr_s.opcode = "00111" or instr_s.opcode = "01001") then
164
165 --      when "00101" =>         --andx
166                 instr_s.reg_dest_addr := instruction(22 downto 19);
167                 instr_s.reg_src1_addr := instruction(22 downto 19);
168                 instr_s.immediate(15 downto 0) := instruction(18 downto 3);
169                 instr_s.high_low := instruction(2);             
170                 instr_s.fill := instruction(1);
171
172                 if (instr_s.fill = '1') then
173                         instr_s.immediate(31 downto 16) := (others => '1');
174                 end if;
175
176                 instr_s.op_detail(IMM_OPT) := '1';
177                 instr_s.op_detail(NO_PSW_OPT) := instruction(0);
178
179                 if (instr_s.opcode = "00101") then
180                         instr_s.op_group := AND_OP;
181                 end if;
182
183                 if (instr_s.opcode = "00111") then
184                         instr_s.op_group := OR_OP;
185                 end if;
186
187                 if (instr_s.opcode = "01001") then
188                         instr_s.op_group := XOR_OP;
189                 end if;
190         end if;
191
192 --      when "00111" =>         --orx
193 --              instr_s.reg_dest_addr := instruction(22 downto 19);
194 --              instr_s.reg_src1_addr := instruction(22 downto 19);
195 --              instr_s.immediate(15 downto 0) := instruction(18 downto 3);
196 --              instr_s.high_low := instruction(2);             
197 --              instr_s.fill := instruction(1);
198 --              instr_s.sreg_update := instruction(0);
199 --
200 --      when "01001" =>         --xorx
201 --              instr_s.reg_dest_addr := instruction(22 downto 19);
202 --              instr_s.reg_src1_addr := instruction(22 downto 19);
203 --              instr_s.immediate(15 downto 0) := instruction(18 downto 3);
204 --              instr_s.high_low := instruction(2);             
205 --              instr_s.fill := instruction(1);
206 --              instr_s.sreg_update := instruction(0);
207 --
208 --=================================================================
209         if (instr_s.opcode = "01010") then
210
211 --      when "01010" =>         --shift
212                 instr_s.reg_dest_addr := instruction(22 downto 19);
213                 instr_s.reg_src1_addr := instruction(18 downto 15);
214                 instr_s.immediate(4 downto 0) := instruction(14 downto 10);
215
216                 instr_s.op_detail(RIGHT_OPT) := instruction(3);
217                 instr_s.op_detail(NO_PSW_OPT) := instruction(0);
218                 instr_s.op_detail(CARRY_OPT) := instruction(1);
219                 instr_s.op_detail(ARITH_OPT) := instruction(2);
220                 instr_s.op_detail(IMM_OPT) := '1';
221
222                 instr_s.op_group := SHIFT_OP;
223         end if;
224
225 --      when "01011" =>         --stackop
226 --              instr_s.reg_dest_addr := instruction(22 downto 19);
227 --              instr_s.reg_src1_addr := instruction(22 downto 19);
228 --              instr_s.immediate(1 downto 0) := instruction(18 downto 17);
229 --              instr_s.left_right := instruction(3);           
230 --              instr_s.arith := instruction(2);                
231 --              instr_s.carry := instruction(1);
232 --              instr_s.sreg_update := instruction(0);
233
234 --=================================================================
235         if (instr_s.opcode = "01110" or instr_s.opcode = "10000" or instr_s.opcode = "10010" or instr_s.opcode = "11010") then
236
237 --      when "01110" =>         --ldw
238                 instr_s.reg_dest_addr := instruction(22 downto 19);
239                 instr_s.reg_src1_addr := instruction(18 downto 15);
240                 instr_s.signext := instruction(2);
241                 instr_s.high_low := instruction(1);
242                 instr_s.displacement(14 downto 0) := instruction(14 downto 0);
243
244                 instr_s.op_group := LDST_OP;
245                 instr_s.op_detail(NO_PSW_OPT) := '1';
246
247                 if (instr_s.displacement(14) = '1') then
248                         instr_s.displacement(31 downto 15) := (others => '1');
249                 end if;
250
251                 if (instr_s.opcode = "11010") then              --ldi
252                         instr_s.reg_src1_addr := instr_s.reg_dest_addr;
253                         instr_s.op_detail(LOW_HIGH_OPT) := instr_s.high_low;
254                         instr_s.op_detail(LDI_REPLACE_OPT) := instr_s.signext;
255                         
256                         if (instr_s.high_low = '1') then
257                                 instr_s.immediate(31 downto 16) := instruction(18 downto 3);
258                                 instr_s.immediate(15 downto 0) := (others => '0');
259                         else
260                                 instr_s.immediate(15 downto 0) := instruction(18 downto 3);
261                                 instr_s.immediate(31 downto 16) := (others => '0');
262                         end if;                 
263
264                         if (instr_s.signext = '1' and instr_s.immediate(11) = '1') then
265                                 instr_s.immediate(31 downto 16) := (others => '1');
266                         end if;
267
268                         instr_s.op_detail(IMM_OPT) := '1';
269                 end if;
270                 
271                 if (instr_s.opcode = "10000") then
272                         instr_s.op_detail(HWORD_OPT) := '1';
273                 end if;
274                 
275                 if (instr_s.opcode = "10010") then
276                         instr_s.op_detail(BYTE_OPT) := '1';
277                 end if;
278         end if;
279
280 --      when "10000" =>         --ldh
281 --              instr_s.reg_dest_addr := instruction(22 downto 19);
282 --              instr_s.reg_src1_addr := instruction(18 downto 15);
283 --              instr_s.displacement(14 downto 0) := instruction(14 downto 0);
284 --              instr_s.immediate(15 downto 0) := instruction(18 downto 3);
285 --              instr_s.signext := instruction(2);
286 --              instr_s.high_low := instruction(1);
287
288 --      when "10010" =>         --ldb
289 --              instr_s.reg_dest_addr := instruction(22 downto 19);
290 --              instr_s.reg_src1_addr := instruction(18 downto 15);
291 --              instr_s.displacement(14 downto 0) := instruction(14 downto 0);
292 --              instr_s.immediate(15 downto 0) := instruction(18 downto 3);
293 --              instr_s.signext := instruction(2);
294 --              instr_s.high_low := instruction(1);
295
296 --      when "11010" =>         --ldi
297 --              instr_s.reg_dest_addr := instruction(22 downto 19);
298 --              instr_s.reg_src1_addr := instruction(18 downto 15);
299 --              instr_s.displacement(14 downto 0) := instruction(14 downto 0);
300 --              instr_s.immediate(15 downto 0) := instruction(18 downto 3);
301 --              instr_s.signext := instruction(2);
302 --              instr_s.high_low := instruction(1);
303
304 --=================================================================
305         if (instr_s.opcode = "01111" or instr_s.opcode = "10001" or instr_s.opcode = "10011" or instr_s.opcode = "10101") then
306
307         --when "01111" =>               --stw
308                 instr_s.reg_src2_addr := instruction(22 downto 19);     -- register value
309                 instr_s.reg_src1_addr := instruction(18 downto 15);     -- mem addr
310                 instr_s.displacement(14 downto 0) := instruction(14 downto 0);
311                 instr_s.op_detail(NO_PSW_OPT) := '1';
312                 instr_s.op_detail(ST_OPT) := '1';
313                 instr_s.op_group := LDST_OP;
314
315                 if (instr_s.displacement(14) = '1') then
316                         instr_s.displacement(31 downto 15) := (others => '1');
317                 end if;
318
319                 if (instr_s.opcode = "10001") then
320                         instr_s.op_detail(HWORD_OPT) := '1';
321                 end if;
322                 
323                 if (instr_s.opcode = "10011") then
324                         instr_s.op_detail(BYTE_OPT) := '1';
325                 end if;
326
327         end if;
328
329         -- ===============================================================
330         
331         if (instr_s.opcode = "01011") then      -- stack op
332                 instr_s.reg_src1_addr := instruction(22 downto 19);
333                 instr_s.reg_dest_addr := instruction(22 downto 19);
334                 instr_s.op_group := STACK_OP;
335                 instr_s.op_detail(NO_PSW_OPT) := '1';
336                 instr_s.op_detail(PWREN_OPT) := '1';
337         
338                 case instruction(18 downto 17) is
339                         when "00" => --pop
340                                 instr_s.op_detail(PUSH_OPT) := '0';
341                         
342                         when "01" => --disc
343                                 instr_s.op_detail(PUSH_OPT) := '0';
344                                 instr_s.op_detail(NO_DST_OPT) := '1';
345                         
346                         when "10" => --fetch
347                                 instr_s.op_detail(PUSH_OPT) := '0';
348                                 instr_s.op_detail(PWREN_OPT) := '0';
349                         
350                         when "11" => --push
351                                 instr_s.op_detail(PUSH_OPT) := '1';
352                                 
353                         when others => null;
354                 end case;
355         
356         end if;
357         
358 --      when "10001" =>         --sth
359 --              instr_s.reg_src1_addr := instruction(22 downto 19);
360 --              instr_s.reg_src2_addr := instruction(18 downto 15);
361 --              instr_s.displacement(14 downto 0) := instruction(14 downto 0);
362
363 --      when "10011" =>         --stb
364 --              instr_s.reg_src1_addr := instruction(22 downto 19);
365 --              instr_s.reg_src2_addr := instruction(18 downto 15);
366 --              instr_s.displacement(14 downto 0) := instruction(14 downto 0);
367
368 --      when "10101" =>         --stx
369 --              instr_s.reg_src1_addr := instruction(22 downto 19);
370 --              instr_s.reg_src2_addr := instruction(18 downto 15);
371 --              instr_s.displacement(14 downto 0) := instruction(14 downto 0);
372
373 --=================================================================
374         if (instr_s.opcode = "10110" or instr_s.opcode = "10111") then
375
376 --      when "10110" =>         --jumpop
377                 instr_s.reg_src1_addr := instruction(22 downto 19);     -- register value
378                 instr_s.immediate(15 downto 0) := instruction(22 downto 7);
379                 instr_s.bp := instruction(1);
380                 instr_s.jmptype := instruction(3 downto 2);
381                 instr_s.signext := instruction(0);
382                 instr_s.op_detail(NO_PSW_OPT) := '1';
383                 instr_s.op_detail(DIRECT_JUMP_OPT) := instruction(4);
384                 instr_s.int := instruction(4);
385
386                 if (instr_s.opcode = "10110") then
387                         instr_s.op_detail(IMM_OPT) := '1';      
388                 else
389                         instr_s.immediate(31 downto 0) := (others => '0');
390                         instr_s.op_detail(JMP_REG_OPT) := '1';
391                         instr_s.op_detail(IMM_OPT) := '1';      
392                 end if;
393
394                 if (instr_s.signext = '1' and instr_s.immediate(15) = '1') then
395                         instr_s.immediate(31 downto 16) := (others => '1');
396                 end if;
397
398                 case instr_s.jmptype is 
399                         when "00" =>
400                                 instr_s.op_group := JMP_OP;
401                         
402                         when "01" =>
403                                 instr_s.op_group := JMP_ST_OP;
404                         
405                         when "10" =>
406                                 instr_s.op_group := JMP_ST_OP;
407                                 instr_s.op_detail(RET_OPT) := '1';
408                         
409                         when "11" =>
410                                 instr_s.op_group := JMP_OP;
411                                 instr_s.op_detail(JMP_REG_OPT) := '1';
412                                 instr_s.op_detail(IMM_OPT) := '1';
413                                 instr_s.immediate := (others => '0');
414                         
415                         when others => null;
416                 end case;
417                 
418 --              if (instr_s.jmptype = "00") then
419 ----                    instr_s.op_detail(SUB_OPT) := not instr_s.opcode(0);
420 --                      instr_s.op_group := JMP_OP;
421 --              end if;
422 --              
423 --              if (instr_s.jmptype = "01") then
424 --                      instr_s.op_group := JMP_ST_OP;
425 --              --      instr_s.op_detail(RET_OPT) := '0';
426 --              end if;
427 --
428 --              if (instr_s.jmptype = "10") then
429 --                      instr_s.op_group := JMP_ST_OP;
430 --                      instr_s.op_detail(RET_OPT) := '1';
431 --              end if;
432 --              
433 --              if (instr_s.jmptype = "11") then
434 --                      instr_s.op_group := JMP_OP;
435 --                      instr_s.op_detail(JMP_REG_OPT) := '1';
436 --                      instr_s.op_detail(IMM_OPT) := '1';
437 --                      instr_s.immediate := (others => '0');
438 --              end if;
439
440                 if (instr_s.predicates = "1111" or instr_s.jmptype = "10") then
441                         instr_s.bp := '0';
442                 end if;
443         end if;
444
445 --      when "10111" =>         --brreg
446 --              instr_s.reg_src1_addr := instruction(22 downto 19);     -- register value
447 --              instr_s.immediate(15 downto 0) := instruction(22 downto 7);     -- negligible
448 --              instr_s.bp := instruction(1);                           -- negligible
449 --              instr_s.jmptype := instruction(3 downto 2);             -- only lsb
450 --              instr_s.signext := instruction(0);                      -- negligible
451
452 --=================================================================
453         if (instr_s.opcode = "11000" or instr_s.opcode = "11001") then
454
455 --      when "11000" =>         --cmp
456                 instr_s.reg_src1_addr := instruction(22 downto 19);
457                 instr_s.reg_src2_addr := instruction(18 downto 15);
458
459                 if (instr_s.opcode = "11001") then
460                         instr_s.immediate(15 downto 0) := instruction(18 downto 3);
461                         instr_s.signext := instruction(2);              
462
463                         if (instr_s.signext = '1' and instr_s.immediate(15) = '1') then
464                                 instr_s.immediate(31 downto 16) := (others => '1');
465                         end if;
466
467                         instr_s.op_detail(IMM_OPT) := '1';
468                 end if;
469                 instr_s.op_detail(NO_DST_OPT) := '1';
470                 instr_s.op_group := ADDSUB_OP;
471                 instr_s.op_detail(SUB_OPT) := '1';
472
473         end if;
474
475 --      when "11001" =>         --cmpi
476 --              instr_s.reg_src1_addr := instruction(22 downto 19);
477 --              instr_s.reg_src2_addr := instruction(18 downto 15);
478 --              instr_s.immediate(15 downto 0) := instruction(18 downto 3);
479
480 --      when others => null;
481
482 --      end case;
483
484
485
486         instr_spl <= instr_s;
487
488 end process;
489
490 end behav_d;
491
492
493 --===========================================================================
494
495