OSDN Git Service

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