OSDN Git Service

fb369ec643541b85757f5c994064f16cdef93a06
[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         ea_carry <= addr_c;
416
417     elsif (indir_x_n = '0') then
418         if (exec_cycle = T2) then
419             ---input is IAL, but this cycle doesn't do anything....
420             abh <= "00000000";
421             abl <= bal;
422
423             --save base addr.
424             tmp_buf_we_n <= '0';
425             tmp_reg_in <= bal;
426         elsif (exec_cycle = T3) then
427
428             ---add x reg.
429             a_sel <= ADDR_ADC;
430             addr1 <= tmp_reg;
431             addr2 <= index_bus;
432             addr_c_in <= '0';
433
434             --save base addr.
435             tmp_buf_we_n <= '0';
436             tmp_reg_in <= addr_out;
437
438             --output @IAL+x
439             abh <= "00000000";
440             abl <= addr_out;
441
442             ---save BAL.
443             al_buf_we_n <= '0';
444             al_reg_in <= int_d_bus;
445
446         elsif (exec_cycle = T4) then
447             al_buf_we_n <= '1';
448             tmp_buf_we_n <= '1';
449
450             ---increment.
451             a_sel <= ADDR_INC;
452             addr1 <= tmp_reg;
453
454             --output @IAL+x
455             abh <= "00000000";
456             abl <= addr_out;
457
458             ---save BAH.
459             ah_buf_we_n <= '0';
460             ah_reg_in <= int_d_bus;
461         elsif (exec_cycle = T5 or exec_cycle = T0) then
462             ah_buf_we_n <= '1';
463
464             --output ah/al reg.
465             abh <= ah_reg;
466             abl <= al_reg;
467         end if; -- if (exec_cycle = T2) then
468
469     elsif (indir_y_n = '0') then
470
471         if (exec_cycle = T2) then
472             ---input is IAL.
473             abh <= "00000000";
474             abl <= bal;
475
476             ---save BAL.
477             al_buf_we_n <= '0';
478             al_reg_in <= int_d_bus;
479             ea_carry <= '0';
480
481             --get next address (IAL + 1)
482             a_sel <= ADDR_INC;
483             addr1 <= bal;
484             tmp_buf_we_n <= '0';
485             tmp_reg_in <= addr_out;
486
487         elsif (exec_cycle = T3) then
488             al_buf_we_n <= '1';
489             tmp_buf_we_n <= '1';
490
491             abh <= "00000000";
492
493             --input is IAL + 1
494             abl <= tmp_reg;
495
496             ---save BAH.
497             ah_buf_we_n <= '0';
498             ah_reg_in <= int_d_bus;
499             ea_carry <= addr_c;
500
501         elsif (exec_cycle = T4) then
502             ah_buf_we_n <= '1';
503
504             ---add y reg.
505             a_sel <= ADDR_ADC;
506
507             --bal from al_reg.
508             addr1 <= al_reg;
509             addr2 <= index_bus;
510             addr_c_in <= '0';
511             ea_carry <= addr_c;
512
513             --bah from ah_reg
514             abh <= ah_reg;
515             abl <= addr_out;
516
517             ---save the address.
518             al_buf_we_n <= '0';
519             al_reg_in <= addr_out;
520             tmp_buf_we_n <= '0';
521             tmp_reg_in <= ah_reg;
522         elsif (exec_cycle = T5 or exec_cycle = T0) then
523             al_buf_we_n <= '1';
524             tmp_buf_we_n <= '1';
525             ea_carry <= '0';
526
527             if (pg_next_n = '0') then
528                 a_sel <= ADDR_INC;
529                 addr1 <= tmp_reg;
530                 ---next page.
531                 abh <= addr_out;
532                 abl <= al_reg;
533             else
534                 abh <= tmp_reg;
535                 abl <= al_reg;
536             end if;
537         else
538             al_buf_we_n <= '1';
539             ah_buf_we_n <= '1';
540             tmp_buf_we_n <= '1';
541             ea_carry <= '0';
542         end if; -- if (exec_cycle = T2) then
543     else
544         al_buf_we_n <= '1';
545         ah_buf_we_n <= '1';
546         tmp_buf_we_n <= '1';
547         ea_carry <= '0';
548
549         abl <= bal;
550         abh <= bah;
551
552         ----addr_back is always bal for jmp/jsr instruction....
553         -----TODO must check later if it's ok.
554         addr_back <= bal;
555     end if; --if (pcl_inc_n = '0') then
556
557     -------------------------------
558     ---- arithmatic operations-----
559     -------------------------------
560     if (arith_en_n = '0') then
561
562         if instruction = conv_std_logic_vector(16#ca#, dsize) then
563             --d_print("dex");
564             sel <= ALU_DEC;
565             d1 <= index_bus;
566             set_nz;
567             output_d_bus;
568
569         elsif instruction = conv_std_logic_vector(16#88#, dsize) then
570             --d_print("dey");
571             sel <= ALU_DEC;
572             d1 <= index_bus;
573             set_nz;
574             output_d_bus;
575
576         elsif instruction = conv_std_logic_vector(16#e8#, dsize) then
577             --d_print("inx");
578             sel <= ALU_INC;
579             d1 <= index_bus;
580             set_nz;
581             output_d_bus;
582
583         elsif instruction = conv_std_logic_vector(16#c8#, dsize) then
584             --d_print("iny");
585             sel <= ALU_INC;
586             d1 <= index_bus;
587             set_nz;
588             output_d_bus;
589
590         elsif instruction = conv_std_logic_vector(16#0a#, dsize) then
591             --d_print("asl");
592             sel <= ALU_ASL;
593             d1 <= acc_out;
594             set_nz;
595             carry_out <= c;
596             output_d_bus;
597
598         elsif instruction = conv_std_logic_vector(16#2a#, dsize) then
599             --rol acc.
600             sel <= ALU_ROL;
601             d1 <= acc_out;
602             set_nz;
603             carry_out <= c;
604             output_d_bus;
605
606         elsif instruction = conv_std_logic_vector(16#4a#, dsize) then
607             --lsr acc.
608             sel <= ALU_LSR;
609             d1 <= acc_out;
610             set_nz;
611             carry_out <= c;
612             output_d_bus;
613
614         elsif instruction = conv_std_logic_vector(16#6a#, dsize) then
615             --ror acc.
616             sel <= ALU_ROR;
617             d1 <= acc_out;
618             set_nz;
619             carry_out <= c;
620             output_d_bus;
621
622         --instruction is aaabbbcc format.
623         --aaa=opcode
624         --bbb=addr mode
625         --000   #immediate
626         --001   zero page
627         --010   accumulator
628         --011   absolute
629         --101   zero page,X
630         --111   absolute,X
631         --cc=optional field.
632         elsif instruction (1 downto 0) = "01" then
633             if instruction (7 downto 5) = "000" then
634                 --d_print("ora");
635                 sel <= ALU_OR;
636                 d1 <= acc_out;
637                 d2 <= int_d_bus;
638                 d_oe_n <= '0';
639                 acc_in <= d_out;
640                 set_nz;
641
642             elsif instruction (7 downto 5) = "001" then
643                 --d_print("and");
644                 sel <= ALU_AND;
645                 d1 <= acc_out;
646                 d2 <= int_d_bus;
647                 d_oe_n <= '0';
648                 acc_in <= d_out;
649                 set_nz;
650
651             elsif instruction (7 downto 5) = "010" then
652                 --d_print("eor");
653                 sel <= ALU_EOR;
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) = "011" then
661                 --d_print("adc");
662                 sel <= ALU_ADC;
663                 d1 <= acc_out;
664                 d2 <= int_d_bus;
665                 d_oe_n <= '0';
666
667                 acc_in <= d_out;
668                 set_nz;
669                 carry_out <= c;
670                 overflow <= v;
671
672             elsif instruction (7 downto 5) = "110" then
673                 --d_print("cmp");
674                 --cmpare A - M.
675                 sel <= ALU_CMP;
676                 d1 <= acc_out;
677                 d2 <= int_d_bus;
678                 set_nz;
679                 carry_out <= c;
680
681             elsif instruction (7 downto 5) = "111" then
682                 --d_print("sbc");
683                 sel <= ALU_SBC;
684                 d1 <= acc_out;
685                 d2 <= int_d_bus;
686                 d_oe_n <= '0';
687
688                 acc_in <= d_out;
689                 set_nz;
690                 carry_out <= c;
691                 overflow <= v;
692
693             end if; --if instruction (7 downto 5) = "000" then
694
695         elsif instruction (1 downto 0) = "10" then
696
697             --this group is all memory to memory instruction (except for stx/ldx).
698             --memory to memory operation takes two cycles.
699             --first is write original data 
700             --second is write modified data
701
702             --001       zero page
703             --011       absolute
704             --101       zero page,X
705             --111       absolute,X
706             if ((exec_cycle = T2 and instruction (4 downto 2) = "001") or 
707                 (exec_cycle = T3 and instruction (4 downto 2) = "011") or 
708                 (exec_cycle = T3 and instruction (4 downto 2) = "101") or 
709                 (exec_cycle = T4 and instruction (4 downto 2) = "111")) then
710                 arith_buf_we_n <= '0';
711                 arith_reg_in <= int_d_bus;
712
713             elsif ((exec_cycle = T3 and instruction (4 downto 2) = "001") or 
714                 (exec_cycle = T4 and instruction (4 downto 2) = "011") or 
715                 (exec_cycle = T4 and instruction (4 downto 2) = "101") or 
716                 (exec_cycle = T5 and instruction (4 downto 2) = "111")) then
717                 --first cycle. keep input variable.
718                 --d_print("inc first.");
719                 arith_buf_we_n <= '1';
720
721                 arith_buf_oe_n <= '1';
722                 d_oe_n <= '1';
723
724                 d1 <= arith_reg;
725             else
726                 --second cycle read from register, output modified data.
727                 --d_print("inc second...");
728                 arith_buf_we_n <= '1';
729                 arith_buf_oe_n <= '0';
730                 d_oe_n <= '0';
731
732                 int_d_bus <= d_out;
733             end if;
734
735             if instruction (7 downto 5) = "000" then
736                 --d_print("asl");
737                 sel <= ALU_ASL;
738                 set_nz;
739                 carry_out <= c;
740
741             elsif instruction (7 downto 5) = "001" then
742                 --d_print("rol");
743                 sel <= ALU_ROL;
744                 set_nz;
745                 carry_out <= c;
746
747             elsif instruction (7 downto 5) = "010" then
748                 --d_print("lsr");
749                 sel <= ALU_LSR;
750                 set_nz;
751                 carry_out <= c;
752
753             elsif instruction (7 downto 5) = "011" then
754                 --d_print("ror");
755                 sel <= ALU_ROR;
756                 set_nz;
757                 carry_out <= c;
758
759             elsif instruction (7 downto 5) = "110" then
760                 --d_print("dec");
761                 sel <= ALU_DEC;
762                 set_nz;
763
764             elsif instruction (7 downto 5) = "111" then
765                 --d_print("alu inc");
766                 sel <= ALU_INC;
767                 set_nz;
768
769             end if; --if instruction (7 downto 5) = "000" then
770
771         elsif instruction (1 downto 0) = "00" then
772             if instruction (7 downto 5) = "001" then
773                 --d_print("bit");
774                 sel <= ALU_BIT;
775                 d1 <= acc_out;
776                 d2 <= int_d_bus;
777                 set_nz;
778                 overflow <= v;
779             elsif instruction (7 downto 5) = "110" then
780                 --d_print("cpy");
781                 sel <= ALU_CMP;
782                 d1 <= index_bus;
783                 d2 <= int_d_bus;
784                 set_nz;
785                 carry_out <= c;
786
787             elsif instruction (7 downto 5) = "111" then
788                -- d_print("cpx");
789                 sel <= ALU_CMP;
790                 d1 <= index_bus;
791                 d2 <= int_d_bus;
792                 set_nz;
793                 carry_out <= c;
794
795             end if; --if instruction (7 downto 5) = "001" then
796         end if; --if instruction = conv_std_logic_vector(16#ca#, dsize) 
797     else
798         --d_print("no arith");
799         d_oe_n <= '1';
800         arith_buf_we_n <= '1';
801         arith_buf_oe_n <= '1';
802         int_d_bus <= (others => 'Z');
803     end if; -- if (arith_en_n = '0') then
804
805     end process;
806
807 end rtl;
808
809 -----------------------------------------
810 ---------- Address calculator------------
811 -----------------------------------------
812
813 library ieee;
814 use ieee.std_logic_1164.all;
815 use ieee.std_logic_unsigned.all;
816
817 entity address_calculator is 
818     generic (   dsize : integer := 8
819             );
820     port ( 
821             sel         : in std_logic_vector (1 downto 0);
822             addr1       : in std_logic_vector (dsize - 1 downto 0);
823             addr2       : in std_logic_vector (dsize - 1 downto 0);
824             addr_out    : out std_logic_vector (dsize - 1 downto 0);
825             carry_in    : in std_logic;
826             carry_out   : out std_logic
827     );
828 end address_calculator;
829
830 architecture rtl of address_calculator is
831
832 constant ADDR_ADC    : std_logic_vector (1 downto 0) := "00";
833 constant ADDR_INC    : std_logic_vector (1 downto 0) := "01";
834 constant ADDR_DEC    : std_logic_vector (1 downto 0) := "10";
835 constant ADDR_SIGNED_ADD : std_logic_vector (1 downto 0) := "11";
836
837 begin
838
839     alu_p : process (sel, addr1, addr2, carry_in)
840     variable res : std_logic_vector (dsize downto 0);
841
842     begin
843     if sel = ADDR_ADC then
844         res := ('0' & addr1) + ('0' & addr2) + carry_in;
845         addr_out <= res(dsize - 1 downto 0);
846         carry_out <= res(dsize);
847
848     elsif sel = ADDR_SIGNED_ADD then
849         res := ('0' & addr1) + ('0' & addr2);
850         addr_out <= res(dsize - 1 downto 0);
851 --        if (addr2(dsize - 1) = '0') then
852 --            ---positive value add.
853 --            if (res(dsize) = '1') then
854 --                carry_out <= '1';
855 --            else
856 --                carry_out <= '0';
857 --            end if;
858 --        else
859 --            ---negative value add.
860 --            if (res(dsize) = '0') then
861 --                carry_out <= '1';
862 --            else
863 --                carry_out <= '0';
864 --            end if;
865 --        end if;
866         -->>>simplified above.
867         if ((addr2(dsize - 1) xor res(dsize)) = '1') then
868             carry_out <= '1';
869         else
870             carry_out <= '0';
871         end if;
872
873     elsif sel = ADDR_INC then
874         res := ('0' & addr1) + "000000001";
875         addr_out <= res(dsize - 1 downto 0);
876         carry_out <= res(dsize);
877     elsif sel = ADDR_DEC then
878         res := ('0' & addr1) - "000000001";
879         addr_out <= res(dsize - 1 downto 0);
880         carry_out <= res(dsize);
881     end if;
882     end process;
883
884 end rtl;
885
886
887 -----------------------------------------
888 ------------- ALU Core -----------------
889 -----------------------------------------
890
891 library ieee;
892 use ieee.std_logic_1164.all;
893 use ieee.std_logic_unsigned.all;
894
895 ----d1 = acc
896 ----d2 = memory
897 entity alu_core is 
898     generic (   dsize : integer := 8
899             );
900     port ( 
901             sel         : in std_logic_vector (3 downto 0);
902             d1          : in std_logic_vector (dsize - 1 downto 0);
903             d2          : in std_logic_vector (dsize - 1 downto 0);
904             d_out       : out std_logic_vector (dsize - 1 downto 0);
905             carry_in    : in std_logic;
906             negative    : out std_logic;
907             zero        : out std_logic;
908             carry_out   : out std_logic;
909             overflow    : out std_logic
910     );
911 end alu_core;
912
913 architecture rtl of alu_core is
914
915 constant ALU_AND    : std_logic_vector (3 downto 0) := "0000";
916 constant ALU_EOR    : std_logic_vector (3 downto 0) := "0001";
917 constant ALU_OR     : std_logic_vector (3 downto 0) := "0010";
918 constant ALU_BIT    : std_logic_vector (3 downto 0) := "0011";
919 constant ALU_ADC    : std_logic_vector (3 downto 0) := "0100";
920 constant ALU_SBC    : std_logic_vector (3 downto 0) := "0101";
921 constant ALU_CMP    : std_logic_vector (3 downto 0) := "0110";
922 constant ALU_ASL    : std_logic_vector (3 downto 0) := "0111";
923 constant ALU_LSR    : std_logic_vector (3 downto 0) := "1000";
924 constant ALU_ROL    : std_logic_vector (3 downto 0) := "1001";
925 constant ALU_ROR    : std_logic_vector (3 downto 0) := "1010";
926 constant ALU_INC    : std_logic_vector (3 downto 0) := "1011";
927 constant ALU_DEC    : std_logic_vector (3 downto 0) := "1100";
928
929 begin
930
931     alu_p : process (sel, d1, d2, carry_in)
932     variable res : std_logic_vector (dsize downto 0);
933
934 procedure set_n (data : in std_logic_vector (dsize - 1 downto 0)) is
935 begin
936     if (data(7) = '1') then
937         negative <= '1';
938     else
939         negative <= '0';
940     end if;
941 end procedure;
942
943 procedure set_z (data : in std_logic_vector (dsize - 1 downto 0)) is
944 begin
945     if  (data = "00000000") then
946         zero <= '1';
947     else
948         zero <= '0';
949     end if;
950 end procedure;
951
952     begin
953     if sel = ALU_AND then
954         res(dsize - 1 downto 0) := d1 and d2;
955         set_n(res(dsize - 1 downto 0));
956         set_z(res(dsize - 1 downto 0));
957         d_out <= res(dsize - 1 downto 0);
958
959     elsif sel = ALU_EOR then
960         res(dsize - 1 downto 0) := d1 xor d2;
961         set_n(res(dsize - 1 downto 0));
962         set_z(res(dsize - 1 downto 0));
963         d_out <= res(dsize - 1 downto 0);
964
965     elsif sel = ALU_OR then
966         res(dsize - 1 downto 0) := d1 or d2;
967         set_n(res(dsize - 1 downto 0));
968         set_z(res(dsize - 1 downto 0));
969         d_out <= res(dsize - 1 downto 0);
970
971     elsif sel = ALU_BIT then
972         --transfer bit 7 and 6  of memory data to n, v flag.
973         negative <= d2(7);
974         overflow <= d2(6);
975         ----zero bit after A and M.
976         res(dsize - 1 downto 0) := d1 and d2;
977         set_z(res(dsize - 1 downto 0));
978
979     elsif sel = ALU_ADC then
980         res := ('0' & d1) + ('0' & d2) + carry_in;
981         d_out <= res(dsize - 1 downto 0);
982         carry_out <= res(dsize);
983         if ((d1(dsize - 1) = d2(dsize - 1)) 
984             and (d1(dsize - 1) /= res(dsize - 1))) then
985             overflow <= '1';
986         else
987             overflow <= '0';
988         end if;
989         set_n(res(dsize - 1 downto 0));
990         set_z(res(dsize - 1 downto 0));
991
992     elsif sel = ALU_SBC then
993         ---A - M - ~C -> A
994         res := ('0' & d1) - ('0' & d2) - not carry_in;
995         d_out <= res(dsize - 1 downto 0);
996
997         --c Set if unsigned borrow not required; cleared if unsigned borrow.
998         carry_out <= not res(dsize);
999         --v Set if signed borrow required; cleared if no signed borrow.
1000         if ((d1(dsize - 1) /= d2(dsize - 1)) 
1001             and (d1(dsize - 1) /= res(dsize - 1))) then
1002             overflow <= '1';
1003         else
1004             overflow <= '0';
1005         end if;
1006         set_n(res(dsize - 1 downto 0));
1007         set_z(res(dsize - 1 downto 0));
1008
1009     elsif sel = ALU_CMP then
1010         res := ('0' & d1) - ('0' & d2);
1011         if (d1 >= d2) then
1012             carry_out <= '1';
1013         else
1014             carry_out <= '0';
1015         end if;
1016         set_n(res(dsize - 1 downto 0));
1017         set_z(res(dsize - 1 downto 0));
1018
1019     elsif sel = ALU_ASL then
1020         res(dsize - 1 downto 1) := d1(dsize - 2 downto 0);
1021         res(0) := '0';
1022
1023         d_out <= res(dsize - 1 downto 0);
1024         set_n(res(dsize - 1 downto 0));
1025         set_z(res(dsize - 1 downto 0));
1026         carry_out <= d1(dsize - 1);
1027
1028     elsif sel = ALU_LSR then
1029         res(dsize - 1) := '0';
1030         res(dsize - 2 downto 0) := d1(dsize - 1 downto 1);
1031
1032         d_out <= res(dsize - 1 downto 0);
1033         set_n(res(dsize - 1 downto 0));
1034         set_z(res(dsize - 1 downto 0));
1035         carry_out <= d1(0);
1036
1037     elsif sel = ALU_ROL then
1038         res(dsize - 1 downto 1) := d1(dsize - 2 downto 0);
1039         res(0) := carry_in;
1040
1041         d_out <= res(dsize - 1 downto 0);
1042         set_n(res(dsize - 1 downto 0));
1043         set_z(res(dsize - 1 downto 0));
1044         carry_out <= d1(7);
1045
1046     elsif sel = ALU_ROR then
1047         res(dsize - 1) := carry_in;
1048         res(dsize - 2 downto 0) := d1(dsize - 1 downto 1);
1049
1050         d_out <= res(dsize - 1 downto 0);
1051         set_n(res(dsize - 1 downto 0));
1052         set_z(res(dsize - 1 downto 0));
1053         carry_out <= d1(0);
1054
1055     elsif sel = ALU_INC then
1056         res := ('0' & d1) + "000000001";
1057         d_out <= res(dsize - 1 downto 0);
1058         set_n(res(dsize - 1 downto 0));
1059         set_z(res(dsize - 1 downto 0));
1060
1061     elsif sel = ALU_DEC then
1062         res := ('0' & d1) - "000000001";
1063         d_out <= res(dsize - 1 downto 0);
1064         set_n(res(dsize - 1 downto 0));
1065         set_z(res(dsize - 1 downto 0));
1066
1067     end if;
1068
1069     end process;
1070
1071 end rtl;
1072