OSDN Git Service

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