OSDN Git Service

sta ok...
[motonesfpga/motonesfpga.git] / de1_nes / cpu / alu.vhd
1 ----------------------------
2 ---- 6502 address calrucator
3 ----------------------------
4 library ieee;
5 use ieee.std_logic_1164.all;
6 use ieee.std_logic_unsigned.all;
7 use ieee.std_logic_arith.conv_std_logic_vector;
8 use work.motonesfpga_common.all;
9
10 entity address_calcurator is 
11     generic (   dsize : integer := 8
12             );
13     port (  
14             trig_clk        : in std_logic;
15
16             --instruction reg
17             instruction     : in std_logic_vector (dsize - 1 downto 0);
18             exec_cycle      : in std_logic_vector (5 downto 0);
19
20             --control line.
21             pcl_inc_n       : in std_logic;
22             sp_oe_n         : in std_logic;
23             sp_push_n       : in std_logic;
24             sp_pop_n        : in std_logic;
25             abs_xy_n        : in std_logic;
26             pg_next_n       : in std_logic;
27             zp_n            : in std_logic;
28             zp_xy_n         : in std_logic;
29             rel_calc_n      : in std_logic;
30             indir_n         : in std_logic;
31             indir_x_n       : in std_logic;
32             indir_y_n       : in std_logic;
33
34             --in/out buses.
35             index_bus       : in std_logic_vector (dsize - 1 downto 0);
36             bal             : in std_logic_vector (dsize - 1 downto 0);
37             bah             : in std_logic_vector (dsize - 1 downto 0);
38             int_d_bus       : in std_logic_vector (dsize - 1 downto 0);
39             addr_back_l     : out std_logic_vector (dsize - 1 downto 0);
40             addr_back_h     : out std_logic_vector (dsize - 1 downto 0);
41             abl             : out std_logic_vector (dsize - 1 downto 0);
42             abh             : out std_logic_vector (dsize - 1 downto 0);
43             ea_carry        : out std_logic
44             );
45 end address_calcurator;
46
47 architecture rtl of address_calcurator is
48
49 component d_flip_flop
50     generic (
51             dsize : integer := 8
52             );
53     port (  
54             clk     : in std_logic;
55             res_n   : in std_logic;
56             set_n   : in std_logic;
57             we_n    : in std_logic;
58             d       : in std_logic_vector (dsize - 1 downto 0);
59             q       : out std_logic_vector (dsize - 1 downto 0)
60         );
61 end component;
62
63 component d_flip_flop_bit
64     port (  
65             clk     : in std_logic;
66             res_n   : in std_logic;
67             set_n   : in std_logic;
68             we_n    : in std_logic;
69             d       : in std_logic;
70             q       : out std_logic
71         );
72 end component;
73
74 component tri_state_buffer
75     generic (
76             dsize : integer := 8
77             );
78     port (  
79             oe_n    : in std_logic;
80             d       : in std_logic_vector (dsize - 1 downto 0);
81             q       : out std_logic_vector (dsize - 1 downto 0)
82         );
83 end component;
84
85 component addr_alu
86     generic (   dsize : integer := 8
87             );
88     port ( 
89             sel         : in std_logic_vector (1 downto 0);
90             addr1       : in std_logic_vector (dsize - 1 downto 0);
91             addr2       : in std_logic_vector (dsize - 1 downto 0);
92             addr_out    : out std_logic_vector (dsize - 1 downto 0);
93             carry_in    : in std_logic;
94             carry_out   : out std_logic
95     );
96 end component;
97
98
99 constant ADDR_ADC    : std_logic_vector (1 downto 0) := "00";
100 constant ADDR_INC    : std_logic_vector (1 downto 0) := "01";
101 constant ADDR_DEC    : std_logic_vector (1 downto 0) := "10";
102 constant ADDR_SIGNED_ADD : std_logic_vector (1 downto 0) := "11";
103
104 ---for indirect addressing.
105 constant T0 : std_logic_vector (5 downto 0) := "000000";
106 constant T1 : std_logic_vector (5 downto 0) := "000001";
107 constant T2 : std_logic_vector (5 downto 0) := "000010";
108 constant T3 : std_logic_vector (5 downto 0) := "000011";
109 constant T4 : std_logic_vector (5 downto 0) := "000100";
110 constant T5 : std_logic_vector (5 downto 0) := "000101";
111
112
113 --------- signals for address calucuration ----------
114 signal al_buf_we_n : std_logic;
115 signal ah_buf_we_n : std_logic;
116 signal tmp_buf_we_n : std_logic;
117
118 signal al_reg_in : std_logic_vector (dsize - 1 downto 0);
119 signal ah_reg_in : std_logic_vector (dsize - 1 downto 0);
120 signal tmp_reg_in : std_logic_vector (dsize - 1 downto 0);
121 signal al_reg : std_logic_vector (dsize - 1 downto 0);
122 signal ah_reg : std_logic_vector (dsize - 1 downto 0);
123 signal tmp_reg : std_logic_vector (dsize - 1 downto 0);
124
125 signal a_sel : std_logic_vector (1 downto 0);
126 signal addr1 : std_logic_vector (dsize - 1 downto 0);
127 signal addr2 : std_logic_vector (dsize - 1 downto 0);
128 signal addr_out : std_logic_vector (dsize - 1 downto 0);
129
130 signal addr_c_in : std_logic;
131 signal addr_c : std_logic;
132 signal addr_c_reg : std_logic;
133
134 begin
135     ----work registers...
136     al_dff : d_flip_flop generic map (dsize) 
137             port map(trig_clk, '1', '1', al_buf_we_n, al_reg_in, al_reg);
138     ah_dff : d_flip_flop generic map (dsize) 
139             port map(trig_clk, '1', '1', ah_buf_we_n, ah_reg_in, ah_reg);
140     tmp_dff : d_flip_flop generic map (dsize) 
141             port map(trig_clk, '1', '1', tmp_buf_we_n, tmp_reg_in, tmp_reg);
142     ea_carry_dff_bit : d_flip_flop_bit 
143             port map(trig_clk, '1', '1', '0', addr_c, addr_c_reg);
144
145     ----------------------------------------
146      -- address calucurator instances ----
147     ----------------------------------------
148     addr_calc_inst : addr_alu generic map (dsize)
149             port map (a_sel, addr1, addr2, addr_out, addr_c_in, addr_c);
150
151     ------------------------------------------------
152     ----- address calcuration state machine...-----
153     ------------------------------------------------
154     alu_addr_p : process (
155                     pcl_inc_n, sp_oe_n, sp_pop_n, sp_push_n,
156                     zp_n, zp_xy_n, abs_xy_n, pg_next_n, rel_calc_n,
157                     int_d_bus(7), indir_n, indir_x_n, exec_cycle,
158                     indir_y_n
159                     )
160     begin
161     
162     if (pcl_inc_n = '0') then
163         ea_carry <= '0';
164         a_sel <= ADDR_INC;
165         addr1 <= bal;
166         addr_back_l <= addr_out;
167         addr_back_h <= bah + addr_c;
168         abl <= bal;
169         abh <= bah;
170
171     elsif (sp_oe_n = '0') then
172         --stack operation...
173         abh <= "00000001";
174         ea_carry <= '0';
175
176         if (sp_push_n /= '0' and sp_pop_n /= '0') then
177             abl <= bal;
178         elsif (sp_pop_n = '0') then
179             --case pop
180             a_sel <= ADDR_INC;
181             addr1 <= bal;
182             addr_back_l <= addr_out;
183             abl <= bal;
184         else
185             ---case push
186             a_sel <= ADDR_DEC;
187             addr1 <= bal;
188             addr_back_l <= addr_out;
189             abl <= bal;
190         end if;
191     elsif (zp_n = '0') then
192         ea_carry <= '0';
193         if (zp_xy_n <= '0') then
194             a_sel <= ADDR_ADC;
195             addr1 <= bal;
196             addr2 <= index_bus;
197             addr_c_in <= '0';
198
199             abh <= "00000000";
200             abl <= addr_out;
201         else
202             abh <= "00000000";
203             abl <= bal;
204         end if;
205
206     elsif (abs_xy_n = '0') then
207         if (pg_next_n = '0') then
208             a_sel <= ADDR_INC;
209             addr1 <= bah;
210             ea_carry <= '0';
211
212             al_buf_we_n <= '1';
213             abh <= addr_out;
214             ---al is in the al_reg.
215             abl <= al_reg;
216         else
217             a_sel <= ADDR_ADC;
218             addr1 <= bal;
219             addr2 <= index_bus;
220             addr_c_in <= '0';
221             ea_carry <= addr_c;
222
223             ---keep al for page crossed case
224             al_buf_we_n <= '0';
225             al_reg_in <= addr_out;
226             abh <= bah;
227             abl <= addr_out;
228         end if;
229
230     elsif (rel_calc_n = '0') then
231         if (pg_next_n = '0') then
232             if (int_d_bus(7) = '1') then
233                 ---backward relative branch
234                 a_sel <= ADDR_DEC;
235             else
236                 ---forward relative branch
237                 a_sel <= ADDR_INC;
238             end if;
239             ---addr1 is pch.`
240             addr1 <= bah;
241             ---rel val is on the d_bus.
242             addr_back_h <= addr_out;
243             ea_carry <= '0'; 
244
245             --keep the value in the cycle
246             ah_buf_we_n <= '0';
247             ah_reg_in <= addr_out;
248             abh <= addr_out;
249             --al no change.
250             abl <= bal;
251         else
252             a_sel <= ADDR_SIGNED_ADD;
253             ---addr1 is pcl.`
254             addr1 <= bal;
255             ---rel val is on the d_bus.
256             addr2 <= int_d_bus;
257             addr_back_l <= addr_out;
258             addr_c_in <= '0';
259             ea_carry <= addr_c_reg;
260
261             --keep the value in the cycle
262             al_buf_we_n <= '0';
263             al_reg_in <= addr_out;
264             abh <= bah;
265             abl <= addr_out;
266         end if;
267     elsif (indir_n = '0') then
268         abh <= bah;
269         --get next address.
270         addr1 <= bal;
271         a_sel <= ADDR_INC;
272         abl <= addr_out;
273
274         ea_carry <= addr_c;
275
276     elsif (indir_x_n = '0') then
277         if (exec_cycle = T2) then
278             ---input is IAL, but this cycle doesn't do anything....
279             abh <= "00000000";
280             abl <= bal;
281
282             --save base addr.
283             tmp_buf_we_n <= '0';
284             tmp_reg_in <= bal;
285         elsif (exec_cycle = T3) then
286
287             ---add x reg.
288             a_sel <= ADDR_ADC;
289             addr1 <= tmp_reg;
290             addr2 <= index_bus;
291             addr_c_in <= '0';
292
293             --save base addr.
294             tmp_buf_we_n <= '0';
295             tmp_reg_in <= addr_out;
296
297             --output @IAL+x
298             abh <= "00000000";
299             abl <= addr_out;
300
301             ---save BAL.
302             al_buf_we_n <= '0';
303             al_reg_in <= int_d_bus;
304
305         elsif (exec_cycle = T4) then
306             al_buf_we_n <= '1';
307             tmp_buf_we_n <= '1';
308
309             ---increment.
310             a_sel <= ADDR_INC;
311             addr1 <= tmp_reg;
312
313             --output @IAL+x
314             abh <= "00000000";
315             abl <= addr_out;
316
317             ---save BAH.
318             ah_buf_we_n <= '0';
319             ah_reg_in <= int_d_bus;
320         elsif (exec_cycle = T5 or exec_cycle = T0) then
321             ah_buf_we_n <= '1';
322
323             --output ah/al reg.
324             abh <= ah_reg;
325             abl <= al_reg;
326         end if; -- if (exec_cycle = T2) then
327
328     elsif (indir_y_n = '0') then
329
330         if (exec_cycle = T2) then
331             ---input is IAL.
332             abh <= "00000000";
333             abl <= bal;
334
335             ---save BAL.
336             al_buf_we_n <= '0';
337             al_reg_in <= int_d_bus;
338             ea_carry <= '0';
339
340             --get next address (IAL + 1)
341             a_sel <= ADDR_INC;
342             addr1 <= bal;
343             tmp_buf_we_n <= '0';
344             tmp_reg_in <= addr_out;
345
346         elsif (exec_cycle = T3) then
347             al_buf_we_n <= '1';
348             tmp_buf_we_n <= '1';
349
350             abh <= "00000000";
351
352             --input is IAL + 1
353             abl <= tmp_reg;
354
355             ---save BAH.
356             ah_buf_we_n <= '0';
357             ah_reg_in <= int_d_bus;
358             ea_carry <= addr_c;
359
360         elsif (exec_cycle = T4) then
361             ah_buf_we_n <= '1';
362
363             ---add y reg.
364             a_sel <= ADDR_ADC;
365
366             --bal from al_reg.
367             addr1 <= al_reg;
368             addr2 <= index_bus;
369             addr_c_in <= '0';
370             ea_carry <= addr_c;
371
372             --bah from ah_reg
373             abh <= ah_reg;
374             abl <= addr_out;
375
376             ---save the address.
377             al_buf_we_n <= '0';
378             al_reg_in <= addr_out;
379             tmp_buf_we_n <= '0';
380             tmp_reg_in <= ah_reg;
381         elsif (exec_cycle = T5 or exec_cycle = T0) then
382             al_buf_we_n <= '1';
383             tmp_buf_we_n <= '1';
384             ea_carry <= '0';
385
386             if (pg_next_n = '0') then
387                 a_sel <= ADDR_INC;
388                 addr1 <= tmp_reg;
389                 ---next page.
390                 abh <= addr_out;
391                 abl <= al_reg;
392             else
393                 abh <= tmp_reg;
394                 abl <= al_reg;
395             end if;
396         else
397             al_buf_we_n <= '1';
398             ah_buf_we_n <= '1';
399             tmp_buf_we_n <= '1';
400             ea_carry <= '0';
401         end if; -- if (exec_cycle = T2) then
402     else
403         al_buf_we_n <= '1';
404         ah_buf_we_n <= '1';
405         tmp_buf_we_n <= '1';
406         ea_carry <= '0';
407
408         abl <= bal;
409         abh <= bah;
410
411         ----addr_back is always bal for jmp/jsr instruction....
412         -----TODO must check later if it's ok.
413         addr_back_l <= bal;
414         addr_back_h <= bah;
415     end if; --if (pcl_inc_n = '0') then
416
417     end process;
418 end rtl;
419
420
421
422
423
424 ----------------------------
425 ---- 6502 ALU
426 ----------------------------
427 library ieee;
428 use ieee.std_logic_1164.all;
429 use ieee.std_logic_unsigned.all;
430 use ieee.std_logic_arith.conv_std_logic_vector;
431 use work.motonesfpga_common.all;
432
433 entity alu is 
434     generic (   dsize : integer := 8
435             );
436     port (  
437             set_clk         : in std_logic;
438             trig_clk        : in std_logic;
439             instruction     : in std_logic_vector (dsize - 1 downto 0);
440             exec_cycle      : in std_logic_vector (5 downto 0);
441             arith_en_n      : in std_logic;
442             int_d_bus       : inout std_logic_vector (dsize - 1 downto 0);
443             acc_in          : out std_logic_vector (dsize - 1 downto 0);
444             acc_out         : in std_logic_vector (dsize - 1 downto 0);
445             index_bus       : in std_logic_vector (dsize - 1 downto 0);
446             carry_in        : in std_logic;
447             negative        : out std_logic;
448             zero            : out std_logic;
449             carry_out       : out std_logic;
450             overflow        : out std_logic
451     );
452 end alu;
453
454 architecture rtl of alu is
455
456 component alu_core
457     generic (   dsize : integer := 8
458             );
459     port ( 
460             sel         : in std_logic_vector (3 downto 0);
461             d1          : in std_logic_vector (dsize - 1 downto 0);
462             d2          : in std_logic_vector (dsize - 1 downto 0);
463             d_out       : out std_logic_vector (dsize - 1 downto 0);
464             carry_in    : in std_logic;
465             negative    : out std_logic;
466             zero        : out std_logic;
467             carry_out   : out std_logic;
468             overflow    : out std_logic
469     );
470 end component;
471
472 component d_flip_flop
473     generic (
474             dsize : integer := 8
475             );
476     port (  
477             clk     : in std_logic;
478             res_n   : in std_logic;
479             set_n   : in std_logic;
480             we_n    : in std_logic;
481             d       : in std_logic_vector (dsize - 1 downto 0);
482             q       : out std_logic_vector (dsize - 1 downto 0)
483         );
484 end component;
485
486 component tri_state_buffer
487     generic (
488             dsize : integer := 8
489             );
490     port (  
491             oe_n    : in std_logic;
492             d       : in std_logic_vector (dsize - 1 downto 0);
493             q       : out std_logic_vector (dsize - 1 downto 0)
494         );
495 end component;
496
497 constant ALU_AND    : std_logic_vector (3 downto 0) := "0000";
498 constant ALU_EOR    : std_logic_vector (3 downto 0) := "0001";
499 constant ALU_OR     : std_logic_vector (3 downto 0) := "0010";
500 constant ALU_BIT    : std_logic_vector (3 downto 0) := "0011";
501 constant ALU_ADC    : std_logic_vector (3 downto 0) := "0100";
502 constant ALU_SBC    : std_logic_vector (3 downto 0) := "0101";
503 constant ALU_CMP    : std_logic_vector (3 downto 0) := "0110";
504 constant ALU_ASL    : std_logic_vector (3 downto 0) := "0111";
505 constant ALU_LSR    : std_logic_vector (3 downto 0) := "1000";
506 constant ALU_ROL    : std_logic_vector (3 downto 0) := "1001";
507 constant ALU_ROR    : std_logic_vector (3 downto 0) := "1010";
508 constant ALU_INC    : std_logic_vector (3 downto 0) := "1011";
509 constant ALU_DEC    : std_logic_vector (3 downto 0) := "1100";
510
511 constant T0 : std_logic_vector (5 downto 0) := "000000";
512 constant T1 : std_logic_vector (5 downto 0) := "000001";
513 constant T2 : std_logic_vector (5 downto 0) := "000010";
514 constant T3 : std_logic_vector (5 downto 0) := "000011";
515 constant T4 : std_logic_vector (5 downto 0) := "000100";
516 constant T5 : std_logic_vector (5 downto 0) := "000101";
517
518 ----------- signals for arithmatic ----------
519 signal sel : std_logic_vector (3 downto 0);
520 signal d1 : std_logic_vector (dsize - 1 downto 0);
521 signal d2 : std_logic_vector (dsize - 1 downto 0);
522 signal d_out : std_logic_vector (dsize - 1 downto 0);
523 signal alu_out : std_logic_vector (dsize - 1 downto 0);
524
525 signal n : std_logic;
526 signal z : std_logic;
527 signal c : std_logic;
528 signal v : std_logic;
529
530 signal arith_buf_we_n : std_logic;
531 signal arith_buf_oe_n : std_logic;
532 signal arith_reg_in : std_logic_vector (dsize - 1 downto 0);
533 signal arith_reg : std_logic_vector (dsize - 1 downto 0);
534 signal arith_reg_out : std_logic_vector (dsize - 1 downto 0);
535 signal d_oe_n : std_logic;
536
537 begin
538     ----------------------------------------
539      -- arithmatic operation instances ----
540     ----------------------------------------
541     arith_dff : d_flip_flop generic map (dsize) 
542             port map(trig_clk, '1', '1', arith_buf_we_n, arith_reg_in, arith_reg);
543     arith_buf : tri_state_buffer generic map (dsize)
544             port map (arith_buf_oe_n, arith_reg, arith_reg_out);
545
546     alu_inst : alu_core generic map (dsize)
547             port map (sel, d1, d2, alu_out, carry_in, n, z, c, v);
548     alu_buf : tri_state_buffer generic map (dsize)
549             port map (d_oe_n, alu_out, d_out);
550
551     alu_arith_p : process (
552                     arith_en_n,
553                     instruction, exec_cycle, int_d_bus, acc_out, 
554                     carry_in, n, z, c, v
555                     )
556     --data calcuration follows the bus input...
557
558 procedure output_d_bus is
559 begin
560     arith_buf_we_n <= '0';
561     arith_buf_oe_n <= '0';
562     d_oe_n <= '0';
563     arith_reg_in <= d_out;
564     if (set_clk = '0') then
565         int_d_bus <= d_out;
566     else
567         int_d_bus <= arith_reg_out;
568     end if;
569 end  procedure;
570
571 procedure set_nz is
572 begin
573     negative <= n;
574     zero <= z;
575 end procedure;
576
577     begin
578     if (arith_en_n = '0') then
579
580         if instruction = conv_std_logic_vector(16#ca#, dsize) then
581             --d_print("dex");
582             sel <= ALU_DEC;
583             d1 <= index_bus;
584             set_nz;
585             output_d_bus;
586
587         elsif instruction = conv_std_logic_vector(16#88#, dsize) then
588             --d_print("dey");
589             sel <= ALU_DEC;
590             d1 <= index_bus;
591             set_nz;
592             output_d_bus;
593
594         elsif instruction = conv_std_logic_vector(16#e8#, dsize) then
595             --d_print("inx");
596             sel <= ALU_INC;
597             d1 <= index_bus;
598             set_nz;
599             output_d_bus;
600
601         elsif instruction = conv_std_logic_vector(16#c8#, dsize) then
602             --d_print("iny");
603             sel <= ALU_INC;
604             d1 <= index_bus;
605             set_nz;
606             output_d_bus;
607
608         elsif instruction = conv_std_logic_vector(16#0a#, dsize) then
609             --d_print("asl");
610             sel <= ALU_ASL;
611             d1 <= acc_out;
612             set_nz;
613             carry_out <= c;
614             output_d_bus;
615
616         elsif instruction = conv_std_logic_vector(16#2a#, dsize) then
617             --rol acc.
618             sel <= ALU_ROL;
619             d1 <= acc_out;
620             set_nz;
621             carry_out <= c;
622             output_d_bus;
623
624         elsif instruction = conv_std_logic_vector(16#4a#, dsize) then
625             --lsr acc.
626             sel <= ALU_LSR;
627             d1 <= acc_out;
628             set_nz;
629             carry_out <= c;
630             output_d_bus;
631
632         elsif instruction = conv_std_logic_vector(16#6a#, dsize) then
633             --ror acc.
634             sel <= ALU_ROR;
635             d1 <= acc_out;
636             set_nz;
637             carry_out <= c;
638             output_d_bus;
639
640         --instruction is aaabbbcc format.
641         --aaa=opcode
642         --bbb=addr mode
643         --000   #immediate
644         --001   zero page
645         --010   accumulator
646         --011   absolute
647         --101   zero page,X
648         --111   absolute,X
649         --cc=optional field.
650         elsif instruction (1 downto 0) = "01" then
651             if instruction (7 downto 5) = "000" then
652                 --d_print("ora");
653                 sel <= ALU_OR;
654                 d1 <= acc_out;
655                 d2 <= int_d_bus;
656                 d_oe_n <= '0';
657                 acc_in <= d_out;
658                 set_nz;
659
660             elsif instruction (7 downto 5) = "001" then
661                 --d_print("and");
662                 sel <= ALU_AND;
663                 d1 <= acc_out;
664                 d2 <= int_d_bus;
665                 d_oe_n <= '0';
666                 acc_in <= d_out;
667                 set_nz;
668
669             elsif instruction (7 downto 5) = "010" then
670                 --d_print("eor");
671                 sel <= ALU_EOR;
672                 d1 <= acc_out;
673                 d2 <= int_d_bus;
674                 d_oe_n <= '0';
675                 acc_in <= d_out;
676                 set_nz;
677
678             elsif instruction (7 downto 5) = "011" then
679                 --d_print("adc");
680                 sel <= ALU_ADC;
681                 d1 <= acc_out;
682                 d2 <= int_d_bus;
683                 d_oe_n <= '0';
684
685                 acc_in <= d_out;
686                 set_nz;
687                 carry_out <= c;
688                 overflow <= v;
689
690             elsif instruction (7 downto 5) = "110" then
691                 --d_print("cmp");
692                 --cmpare A - M.
693                 sel <= ALU_CMP;
694                 d1 <= acc_out;
695                 d2 <= int_d_bus;
696                 set_nz;
697                 carry_out <= c;
698
699             elsif instruction (7 downto 5) = "111" then
700                 --d_print("sbc");
701                 sel <= ALU_SBC;
702                 d1 <= acc_out;
703                 d2 <= int_d_bus;
704                 d_oe_n <= '0';
705
706                 acc_in <= d_out;
707                 set_nz;
708                 carry_out <= c;
709                 overflow <= v;
710
711             end if; --if instruction (7 downto 5) = "000" then
712
713         elsif instruction (1 downto 0) = "10" then
714
715             --this group is all memory to memory instruction (except for stx/ldx).
716             --memory to memory operation takes two cycles.
717             --first is write original data 
718             --second is write modified data
719
720             --001       zero page
721             --011       absolute
722             --101       zero page,X
723             --111       absolute,X
724             if ((exec_cycle = T2 and instruction (4 downto 2) = "001") or 
725                 (exec_cycle = T3 and instruction (4 downto 2) = "011") or 
726                 (exec_cycle = T3 and instruction (4 downto 2) = "101") or 
727                 (exec_cycle = T4 and instruction (4 downto 2) = "111")) then
728                 arith_buf_we_n <= '0';
729                 arith_reg_in <= int_d_bus;
730
731             elsif ((exec_cycle = T3 and instruction (4 downto 2) = "001") or 
732                 (exec_cycle = T4 and instruction (4 downto 2) = "011") or 
733                 (exec_cycle = T4 and instruction (4 downto 2) = "101") or 
734                 (exec_cycle = T5 and instruction (4 downto 2) = "111")) then
735                 --first cycle. keep input variable.
736                 --d_print("inc first.");
737                 arith_buf_we_n <= '1';
738
739                 arith_buf_oe_n <= '1';
740                 d_oe_n <= '1';
741
742                 d1 <= arith_reg;
743             else
744                 --second cycle read from register, output modified data.
745                 --d_print("inc second...");
746                 arith_buf_we_n <= '1';
747                 arith_buf_oe_n <= '0';
748                 d_oe_n <= '0';
749
750                 int_d_bus <= d_out;
751             end if;
752
753             if instruction (7 downto 5) = "000" then
754                 --d_print("asl");
755                 sel <= ALU_ASL;
756                 set_nz;
757                 carry_out <= c;
758
759             elsif instruction (7 downto 5) = "001" then
760                 --d_print("rol");
761                 sel <= ALU_ROL;
762                 set_nz;
763                 carry_out <= c;
764
765             elsif instruction (7 downto 5) = "010" then
766                 --d_print("lsr");
767                 sel <= ALU_LSR;
768                 set_nz;
769                 carry_out <= c;
770
771             elsif instruction (7 downto 5) = "011" then
772                 --d_print("ror");
773                 sel <= ALU_ROR;
774                 set_nz;
775                 carry_out <= c;
776
777             elsif instruction (7 downto 5) = "110" then
778                 --d_print("dec");
779                 sel <= ALU_DEC;
780                 set_nz;
781
782             elsif instruction (7 downto 5) = "111" then
783                 --d_print("alu inc");
784                 sel <= ALU_INC;
785                 set_nz;
786
787             end if; --if instruction (7 downto 5) = "000" then
788
789         elsif instruction (1 downto 0) = "00" then
790             if instruction (7 downto 5) = "001" then
791                 --d_print("bit");
792                 sel <= ALU_BIT;
793                 d1 <= acc_out;
794                 d2 <= int_d_bus;
795                 set_nz;
796                 overflow <= v;
797             elsif instruction (7 downto 5) = "110" then
798                 --d_print("cpy");
799                 sel <= ALU_CMP;
800                 d1 <= index_bus;
801                 d2 <= int_d_bus;
802                 set_nz;
803                 carry_out <= c;
804
805             elsif instruction (7 downto 5) = "111" then
806                -- d_print("cpx");
807                 sel <= ALU_CMP;
808                 d1 <= index_bus;
809                 d2 <= int_d_bus;
810                 set_nz;
811                 carry_out <= c;
812
813             end if; --if instruction (7 downto 5) = "001" then
814         end if; --if instruction = conv_std_logic_vector(16#ca#, dsize) 
815     else
816         --d_print("no arith");
817         d_oe_n <= '1';
818         arith_buf_we_n <= '1';
819         arith_buf_oe_n <= '1';
820         int_d_bus <= (others => 'Z');
821     end if; -- if (arith_en_n = '0') then
822
823     end process;
824
825 end rtl;
826
827 -----------------------------------------
828  ------- Address calcuration core -----
829 -----------------------------------------
830
831 library ieee;
832 use ieee.std_logic_1164.all;
833 use ieee.std_logic_unsigned.all;
834
835 entity addr_alu is 
836     generic (   dsize : integer := 8
837             );
838     port ( 
839             sel         : in std_logic_vector (1 downto 0);
840             addr1       : in std_logic_vector (dsize - 1 downto 0);
841             addr2       : in std_logic_vector (dsize - 1 downto 0);
842             addr_out    : out std_logic_vector (dsize - 1 downto 0);
843             carry_in    : in std_logic;
844             carry_out   : out std_logic
845     );
846 end addr_alu;
847
848 architecture rtl of addr_alu is
849
850 constant ADDR_ADC    : std_logic_vector (1 downto 0) := "00";
851 constant ADDR_INC    : std_logic_vector (1 downto 0) := "01";
852 constant ADDR_DEC    : std_logic_vector (1 downto 0) := "10";
853 constant ADDR_SIGNED_ADD : std_logic_vector (1 downto 0) := "11";
854
855 begin
856
857     alu_p : process (sel, addr1, addr2, carry_in)
858     variable res : std_logic_vector (dsize downto 0);
859
860     begin
861     if sel = ADDR_ADC then
862         res := ('0' & addr1) + ('0' & addr2) + carry_in;
863         addr_out <= res(dsize - 1 downto 0);
864         carry_out <= res(dsize);
865
866     elsif sel = ADDR_SIGNED_ADD then
867         res := ('0' & addr1) + ('0' & addr2);
868         addr_out <= res(dsize - 1 downto 0);
869         -->>>simplified above.
870         if ((addr2(dsize - 1) xor res(dsize)) = '1') then
871             carry_out <= '1';
872         else
873             carry_out <= '0';
874         end if;
875
876     elsif sel = ADDR_INC then
877         res := ('0' & addr1) + "000000001";
878         addr_out <= res(dsize - 1 downto 0);
879         carry_out <= res(dsize);
880     elsif sel = ADDR_DEC then
881         res := ('0' & addr1) - "000000001";
882         addr_out <= res(dsize - 1 downto 0);
883         carry_out <= res(dsize);
884     end if;
885     end process;
886
887 end rtl;
888
889
890 -----------------------------------------
891  ------------ ALU Core -----------------
892 -----------------------------------------
893
894 library ieee;
895 use ieee.std_logic_1164.all;
896 use ieee.std_logic_unsigned.all;
897
898 ----d1 = acc
899 ----d2 = memory
900 entity alu_core is 
901     generic (   dsize : integer := 8
902             );
903     port ( 
904             sel         : in std_logic_vector (3 downto 0);
905             d1          : in std_logic_vector (dsize - 1 downto 0);
906             d2          : in std_logic_vector (dsize - 1 downto 0);
907             d_out       : out std_logic_vector (dsize - 1 downto 0);
908             carry_in    : in std_logic;
909             negative    : out std_logic;
910             zero        : out std_logic;
911             carry_out   : out std_logic;
912             overflow    : out std_logic
913     );
914 end alu_core;
915
916 architecture rtl of alu_core is
917
918 constant ALU_AND    : std_logic_vector (3 downto 0) := "0000";
919 constant ALU_EOR    : std_logic_vector (3 downto 0) := "0001";
920 constant ALU_OR     : std_logic_vector (3 downto 0) := "0010";
921 constant ALU_BIT    : std_logic_vector (3 downto 0) := "0011";
922 constant ALU_ADC    : std_logic_vector (3 downto 0) := "0100";
923 constant ALU_SBC    : std_logic_vector (3 downto 0) := "0101";
924 constant ALU_CMP    : std_logic_vector (3 downto 0) := "0110";
925 constant ALU_ASL    : std_logic_vector (3 downto 0) := "0111";
926 constant ALU_LSR    : std_logic_vector (3 downto 0) := "1000";
927 constant ALU_ROL    : std_logic_vector (3 downto 0) := "1001";
928 constant ALU_ROR    : std_logic_vector (3 downto 0) := "1010";
929 constant ALU_INC    : std_logic_vector (3 downto 0) := "1011";
930 constant ALU_DEC    : std_logic_vector (3 downto 0) := "1100";
931
932 begin
933
934     alu_p : process (sel, d1, d2, carry_in)
935     variable res : std_logic_vector (dsize downto 0);
936
937 procedure set_n (data : in std_logic_vector (dsize - 1 downto 0)) is
938 begin
939     if (data(7) = '1') then
940         negative <= '1';
941     else
942         negative <= '0';
943     end if;
944 end procedure;
945
946 procedure set_z (data : in std_logic_vector (dsize - 1 downto 0)) is
947 begin
948     if  (data = "00000000") then
949         zero <= '1';
950     else
951         zero <= '0';
952     end if;
953 end procedure;
954
955     begin
956     if sel = ALU_AND then
957         res(dsize - 1 downto 0) := d1 and d2;
958         set_n(res(dsize - 1 downto 0));
959         set_z(res(dsize - 1 downto 0));
960         d_out <= res(dsize - 1 downto 0);
961
962     elsif sel = ALU_EOR then
963         res(dsize - 1 downto 0) := d1 xor d2;
964         set_n(res(dsize - 1 downto 0));
965         set_z(res(dsize - 1 downto 0));
966         d_out <= res(dsize - 1 downto 0);
967
968     elsif sel = ALU_OR then
969         res(dsize - 1 downto 0) := d1 or d2;
970         set_n(res(dsize - 1 downto 0));
971         set_z(res(dsize - 1 downto 0));
972         d_out <= res(dsize - 1 downto 0);
973
974     elsif sel = ALU_BIT then
975         --transfer bit 7 and 6  of memory data to n, v flag.
976         negative <= d2(7);
977         overflow <= d2(6);
978         ----zero bit after A and M.
979         res(dsize - 1 downto 0) := d1 and d2;
980         set_z(res(dsize - 1 downto 0));
981
982     elsif sel = ALU_ADC then
983         res := ('0' & d1) + ('0' & d2) + carry_in;
984         d_out <= res(dsize - 1 downto 0);
985         carry_out <= res(dsize);
986         if ((d1(dsize - 1) = d2(dsize - 1)) 
987             and (d1(dsize - 1) /= res(dsize - 1))) then
988             overflow <= '1';
989         else
990             overflow <= '0';
991         end if;
992         set_n(res(dsize - 1 downto 0));
993         set_z(res(dsize - 1 downto 0));
994
995     elsif sel = ALU_SBC then
996         ---A - M - ~C -> A
997         res := ('0' & d1) - ('0' & d2) - not carry_in;
998         d_out <= res(dsize - 1 downto 0);
999
1000         --c Set if unsigned borrow not required; cleared if unsigned borrow.
1001         carry_out <= not res(dsize);
1002         --v Set if signed borrow required; cleared if no signed borrow.
1003         if ((d1(dsize - 1) /= d2(dsize - 1)) 
1004             and (d1(dsize - 1) /= res(dsize - 1))) then
1005             overflow <= '1';
1006         else
1007             overflow <= '0';
1008         end if;
1009         set_n(res(dsize - 1 downto 0));
1010         set_z(res(dsize - 1 downto 0));
1011
1012     elsif sel = ALU_CMP then
1013         res := ('0' & d1) - ('0' & d2);
1014         if (d1 >= d2) then
1015             carry_out <= '1';
1016         else
1017             carry_out <= '0';
1018         end if;
1019         set_n(res(dsize - 1 downto 0));
1020         set_z(res(dsize - 1 downto 0));
1021
1022     elsif sel = ALU_ASL then
1023         res(dsize - 1 downto 1) := d1(dsize - 2 downto 0);
1024         res(0) := '0';
1025
1026         d_out <= res(dsize - 1 downto 0);
1027         set_n(res(dsize - 1 downto 0));
1028         set_z(res(dsize - 1 downto 0));
1029         carry_out <= d1(dsize - 1);
1030
1031     elsif sel = ALU_LSR then
1032         res(dsize - 1) := '0';
1033         res(dsize - 2 downto 0) := d1(dsize - 1 downto 1);
1034
1035         d_out <= res(dsize - 1 downto 0);
1036         set_n(res(dsize - 1 downto 0));
1037         set_z(res(dsize - 1 downto 0));
1038         carry_out <= d1(0);
1039
1040     elsif sel = ALU_ROL then
1041         res(dsize - 1 downto 1) := d1(dsize - 2 downto 0);
1042         res(0) := carry_in;
1043
1044         d_out <= res(dsize - 1 downto 0);
1045         set_n(res(dsize - 1 downto 0));
1046         set_z(res(dsize - 1 downto 0));
1047         carry_out <= d1(7);
1048
1049     elsif sel = ALU_ROR then
1050         res(dsize - 1) := carry_in;
1051         res(dsize - 2 downto 0) := d1(dsize - 1 downto 1);
1052
1053         d_out <= res(dsize - 1 downto 0);
1054         set_n(res(dsize - 1 downto 0));
1055         set_z(res(dsize - 1 downto 0));
1056         carry_out <= d1(0);
1057
1058     elsif sel = ALU_INC then
1059         res := ('0' & d1) + "000000001";
1060         d_out <= res(dsize - 1 downto 0);
1061         set_n(res(dsize - 1 downto 0));
1062         set_z(res(dsize - 1 downto 0));
1063
1064     elsif sel = ALU_DEC then
1065         res := ('0' & d1) - "000000001";
1066         d_out <= res(dsize - 1 downto 0);
1067         set_n(res(dsize - 1 downto 0));
1068         set_z(res(dsize - 1 downto 0));
1069
1070     end if;
1071
1072     end process;
1073
1074 end rtl;
1075