OSDN Git Service

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