OSDN Git Service

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