OSDN Git Service

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