OSDN Git Service

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