OSDN Git Service

Merge branch 'master' of git.sourceforge.jp:/gitroot/motonesfpga/motonesfpga
[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 signal m2m_stat_1 : std_logic;
157 signal m2m_stat_2 : std_logic;
158
159 begin
160
161     ----------------------------------------
162      -- address calucurator instances ----
163     ----------------------------------------
164     al_dff : d_flip_flop generic map (dsize) 
165             port map(clk, '1', '1', al_buf_we_n, al_reg_in, al_reg);
166     ah_dff : d_flip_flop generic map (dsize) 
167             port map(clk, '1', '1', ah_buf_we_n, ah_reg_in, ah_reg);
168
169     --pcl carry flag set.
170     pcl_carry_reg_in <= addr_c when pcl_inc_n = '0' else
171                 '0';
172
173     pch_carry_dff_bit : d_flip_flop_bit 
174             port map(clk, '1', '1', 
175                     '0', pcl_carry_reg_in, pcl_inc_carry);
176
177     addr_calc_inst : address_calculator generic map (dsize)
178             port map (a_sel, addr1, addr2, addr_out, addr_c_in, addr_c);
179
180
181     ----------------------------------------
182      -- arithmatic operation instances ----
183     ----------------------------------------
184     arith_dff : d_flip_flop generic map (dsize) 
185             port map(clk, '1', '1', arith_buf_we_n, arith_reg_in, arith_reg);
186     arith_buf : tri_state_buffer generic map (dsize)
187             port map (arith_buf_oe_n, arith_reg, arith_reg_out);
188
189     alu_inst : alu_core generic map (dsize)
190             port map (sel, d1, d2, alu_out, carry_in, n, z, c, v);
191     alu_buf : tri_state_buffer generic map (dsize)
192             port map (d_oe_n, alu_out, d_out);
193
194     -------------------------------
195     ------ alu main process -------
196     -------------------------------
197     alu_p : process (
198                     clk, 
199                     ---for address calucuration
200                     pcl_inc_n, pch_inc_n, sp_oe_n, sp_push_n, sp_pop_n,
201                     abs_xy_n, pg_next_n, zp_n, zp_xy_n, rel_calc_n, 
202                     indir_n, indir_x_n, indir_y_n, 
203                     index_bus, bal, bah, addr_c_in, addr_out, addr_c,
204
205                     --for arithmatic operation.
206                     arith_en_n,
207                     instruction, exec_cycle, int_d_bus, acc_out, 
208                     carry_in, n, z, c, v,
209                     arith_reg, arith_reg_out, alu_out, d_out
210                     )
211
212 constant ADDR_ADC    : std_logic_vector (1 downto 0) := "00";
213 constant ADDR_INC    : std_logic_vector (1 downto 0) := "01";
214 constant ADDR_DEC    : std_logic_vector (1 downto 0) := "10";
215 constant ADDR_SIGNED_ADD : std_logic_vector (1 downto 0) := "11";
216
217 constant ALU_AND    : std_logic_vector (3 downto 0) := "0000";
218 constant ALU_EOR    : std_logic_vector (3 downto 0) := "0001";
219 constant ALU_OR     : std_logic_vector (3 downto 0) := "0010";
220 constant ALU_BIT    : std_logic_vector (3 downto 0) := "0011";
221 constant ALU_ADC    : std_logic_vector (3 downto 0) := "0100";
222 constant ALU_SBC    : std_logic_vector (3 downto 0) := "0101";
223 constant ALU_CMP    : std_logic_vector (3 downto 0) := "0110";
224 constant ALU_ASL    : std_logic_vector (3 downto 0) := "0111";
225 constant ALU_LSR    : std_logic_vector (3 downto 0) := "1000";
226 constant ALU_ROL    : std_logic_vector (3 downto 0) := "1001";
227 constant ALU_ROR    : std_logic_vector (3 downto 0) := "1010";
228 constant ALU_INC    : std_logic_vector (3 downto 0) := "1011";
229 constant ALU_DEC    : std_logic_vector (3 downto 0) := "1100";
230
231 ---for indirect addressing.
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             ea_carry <= addr_c;
392
393             --keep the value in the cycle
394             al_buf_we_n <= '0';
395             al_reg_in <= addr_out;
396             if (clk = '0') then
397                 abl <= addr_out;
398             else
399                 abl <= al_reg;
400             end if;
401             abh <= bah;
402         end if;
403     elsif (indir_n = '0') then
404         abh <= bah;
405         --get next address.
406         addr1 <= bal;
407         a_sel <= ADDR_INC;
408         abl <= addr_out;
409
410         --TODO: must handle page crossing case...
411         ea_carry <= addr_c;
412
413     elsif (indir_x_n = '0') then
414
415     elsif (indir_y_n = '0') then
416
417         if (clk = '0') then
418         if (exec_cycle = T2) then
419             ---input is IAL.
420             abh <= "00000000";
421             abl <= bal;
422
423             ---save BAL.
424             al_buf_we_n <= '0';
425             al_reg_in <= int_d_bus;
426
427         elsif (exec_cycle = T3) then
428             al_buf_we_n <= '1';
429
430             abh <= "00000000";
431
432             --input is IAL + 1
433             a_sel <= ADDR_INC;
434             addr1 <= bal;
435             abl <= addr_out;
436
437             ---save BAH.
438             ah_buf_we_n <= '0';
439             ah_reg_in <= int_d_bus;
440
441         elsif (exec_cycle = T4) then
442
443             ---add y reg.
444             a_sel <= ADDR_ADC;
445
446             --bal from al_reg.
447             addr1 <= al_reg;
448             addr2 <= index_bus;
449             addr_c_in <= '0';
450             ea_carry <= addr_c;
451
452             --bah from ah_reg
453             abh <= ah_reg;
454             abl <= addr_out;
455
456             ---save the address.
457             al_buf_we_n <= '0';
458             al_reg_in <= addr_out;
459             ah_buf_we_n <= '0';
460             ah_reg_in <= ah_reg;
461         elsif (exec_cycle = T5) then
462
463             if (pg_next_n = '0') then
464                 a_sel <= ADDR_INC;
465                 addr1 <= ah_reg;
466                 ---next page.
467                 abh <= addr_out;
468                 abl <= al_reg;
469             else
470                 abh <= ah_reg;
471                 abl <= al_reg;
472             end if;
473         end if; -- if (exec_cycle = T2) then
474         end if; --if (clk = '0') then
475     else
476         al_buf_we_n <= '1';
477         ah_buf_we_n <= '1';
478
479         abl <= bal;
480         abh <= bah;
481
482         ----addr_back is always bal for jmp/jsr instruction....
483         -----TODO must check later if it's ok.
484         addr_back <= bal;
485     end if; --if (pcl_inc_n = '0') then
486
487     -------------------------------
488     ---- arithmatic operations-----
489     -------------------------------
490     if (arith_en_n = '0') then
491
492         if instruction = conv_std_logic_vector(16#ca#, dsize) then
493             --d_print("dex");
494             sel <= ALU_DEC;
495             d1 <= index_bus;
496             set_nz;
497             output_d_bus;
498
499         elsif instruction = conv_std_logic_vector(16#88#, dsize) then
500             --d_print("dey");
501             sel <= ALU_DEC;
502             d1 <= index_bus;
503             set_nz;
504             output_d_bus;
505
506         elsif instruction = conv_std_logic_vector(16#e8#, dsize) then
507             --d_print("inx");
508             sel <= ALU_INC;
509             d1 <= index_bus;
510             set_nz;
511             output_d_bus;
512
513         elsif instruction = conv_std_logic_vector(16#c8#, dsize) then
514             --d_print("iny");
515             sel <= ALU_INC;
516             d1 <= index_bus;
517             set_nz;
518             output_d_bus;
519
520         elsif instruction = conv_std_logic_vector(16#0a#, dsize) then
521             --d_print("asl");
522             sel <= ALU_ASL;
523             d1 <= acc_out;
524             set_nz;
525             carry_out <= c;
526             output_d_bus;
527
528         elsif instruction = conv_std_logic_vector(16#2a#, dsize) then
529             --rol acc.
530             sel <= ALU_ROL;
531             d1 <= acc_out;
532             set_nz;
533             carry_out <= c;
534             output_d_bus;
535
536         elsif instruction = conv_std_logic_vector(16#4a#, dsize) then
537             --lsr acc.
538             sel <= ALU_LSR;
539             d1 <= acc_out;
540             set_nz;
541             carry_out <= c;
542             output_d_bus;
543
544         elsif instruction = conv_std_logic_vector(16#6a#, dsize) then
545             --ror acc.
546             sel <= ALU_ROR;
547             d1 <= acc_out;
548             set_nz;
549             carry_out <= c;
550             output_d_bus;
551
552         --instruction is aaabbbcc format.
553         elsif instruction (1 downto 0) = "01" then
554             if instruction (7 downto 5) = "000" then
555                 --d_print("ora");
556                 sel <= ALU_OR;
557                 d1 <= acc_out;
558                 d2 <= int_d_bus;
559                 d_oe_n <= '0';
560                 acc_in <= d_out;
561                 set_nz;
562
563             elsif instruction (7 downto 5) = "001" then
564                 --d_print("and");
565                 sel <= ALU_AND;
566                 d1 <= acc_out;
567                 d2 <= int_d_bus;
568                 d_oe_n <= '0';
569                 acc_in <= d_out;
570                 set_nz;
571
572             elsif instruction (7 downto 5) = "010" then
573                 --d_print("eor");
574                 sel <= ALU_EOR;
575                 d1 <= acc_out;
576                 d2 <= int_d_bus;
577                 d_oe_n <= '0';
578                 acc_in <= d_out;
579                 set_nz;
580
581             elsif instruction (7 downto 5) = "011" then
582                 --d_print("adc");
583                 sel <= ALU_ADC;
584                 d1 <= acc_out;
585                 d2 <= int_d_bus;
586                 d_oe_n <= '0';
587
588                 acc_in <= d_out;
589                 set_nz;
590                 carry_out <= c;
591                 overflow <= v;
592
593             elsif instruction (7 downto 5) = "110" then
594                 --d_print("cmp");
595                 --cmpare A - M.
596                 sel <= ALU_CMP;
597                 d1 <= acc_out;
598                 d2 <= int_d_bus;
599                 set_nz;
600                 carry_out <= c;
601
602             elsif instruction (7 downto 5) = "111" then
603                 --d_print("sbc");
604                 sel <= ALU_SBC;
605                 d1 <= acc_out;
606                 d2 <= int_d_bus;
607                 d_oe_n <= '0';
608
609                 acc_in <= d_out;
610                 set_nz;
611                 carry_out <= c;
612                 overflow <= v;
613
614             end if; --if instruction (7 downto 5) = "000" then
615
616         elsif instruction (1 downto 0) = "10" then
617
618             --this group is all memory to memory instruction (except for stx/ldx).
619             --memory to memory operation takes two cycles.
620             --first is write original data 
621             --second is write modified data
622
623             arith_reg_in <= int_d_bus;
624             d1 <= arith_reg_out;
625             int_d_bus <= d_out;
626
627             if (clk = '0') then
628                 --d_print("clk hi");
629                 if (m2m_stat_1 = '0') then
630                     --first cycle. keep input variable.
631                     --d_print("inc first.");
632                     m2m_stat_1 <= '1';
633                     arith_buf_we_n <= '0';
634                     arith_buf_oe_n <= '1';
635                     d_oe_n <= '1';
636
637                 end if;
638             end if;
639
640 --            if (clk'event and clk = '0') then
641 --                if (m2m_stat_2 = '0') then
642 --                    --second cycle read from register, output modified data.
643 --                    --d_print("inc second...");
644 --                    m2m_stat_2 <= '1';
645 --                    arith_buf_we_n <= '1';
646 --                    arith_buf_oe_n <= '0';
647 --                    d_oe_n <= '0';
648 --                end if;
649 --            end if;
650
651
652             if instruction (7 downto 5) = "000" then
653                 --d_print("asl");
654                 sel <= ALU_ASL;
655                 set_nz;
656                 carry_out <= c;
657
658             elsif instruction (7 downto 5) = "001" then
659                 --d_print("rol");
660                 sel <= ALU_ROL;
661                 set_nz;
662                 carry_out <= c;
663
664             elsif instruction (7 downto 5) = "010" then
665                 --d_print("lsr");
666                 sel <= ALU_LSR;
667                 set_nz;
668                 carry_out <= c;
669
670             elsif instruction (7 downto 5) = "011" then
671                 --d_print("ror");
672                 sel <= ALU_ROR;
673                 set_nz;
674                 carry_out <= c;
675
676             elsif instruction (7 downto 5) = "110" then
677                 --d_print("dec");
678                 sel <= ALU_DEC;
679                 set_nz;
680
681             elsif instruction (7 downto 5) = "111" then
682                 --d_print("alu inc");
683                 sel <= ALU_INC;
684                 set_nz;
685
686             end if; --if instruction (7 downto 5) = "000" then
687
688         elsif instruction (1 downto 0) = "00" then
689             if instruction (7 downto 5) = "001" then
690                 --d_print("bit");
691                 sel <= ALU_BIT;
692                 d1 <= acc_out;
693                 d2 <= int_d_bus;
694                 set_nz;
695                 overflow <= v;
696             elsif instruction (7 downto 5) = "110" then
697                 --d_print("cpy");
698                 sel <= ALU_CMP;
699                 d1 <= index_bus;
700                 d2 <= int_d_bus;
701                 set_nz;
702                 carry_out <= c;
703
704             elsif instruction (7 downto 5) = "111" then
705                -- d_print("cpx");
706                 sel <= ALU_CMP;
707                 d1 <= index_bus;
708                 d2 <= int_d_bus;
709                 set_nz;
710                 carry_out <= c;
711
712             end if; --if instruction (7 downto 5) = "001" then
713         end if; --if instruction = conv_std_logic_vector(16#ca#, dsize) 
714     else
715         --d_print("no arith");
716         m2m_stat_1 <= '0';
717         m2m_stat_2 <= '0';
718         d_oe_n <= '1';
719         arith_buf_we_n <= '1';
720         arith_buf_oe_n <= '1';
721         int_d_bus <= (others => 'Z');
722     end if; -- if (arith_en_n = '0') then
723
724     end process;
725
726 end rtl;
727
728 -----------------------------------------
729 ---------- Address calculator------------
730 -----------------------------------------
731
732 library ieee;
733 use ieee.std_logic_1164.all;
734 use ieee.std_logic_unsigned.all;
735
736 entity address_calculator is 
737     generic (   dsize : integer := 8
738             );
739     port ( 
740             sel         : in std_logic_vector (1 downto 0);
741             addr1       : in std_logic_vector (dsize - 1 downto 0);
742             addr2       : in std_logic_vector (dsize - 1 downto 0);
743             addr_out    : out std_logic_vector (dsize - 1 downto 0);
744             carry_in    : in std_logic;
745             carry_out   : out std_logic
746     );
747 end address_calculator;
748
749 architecture rtl of address_calculator is
750
751 constant ADDR_ADC    : std_logic_vector (1 downto 0) := "00";
752 constant ADDR_INC    : std_logic_vector (1 downto 0) := "01";
753 constant ADDR_DEC    : std_logic_vector (1 downto 0) := "10";
754 constant ADDR_SIGNED_ADD : std_logic_vector (1 downto 0) := "11";
755
756 begin
757
758     alu_p : process (sel, addr1, addr2, carry_in)
759     variable res : std_logic_vector (dsize downto 0);
760
761     begin
762     if sel = ADDR_ADC then
763         res := ('0' & addr1) + ('0' & addr2) + carry_in;
764         addr_out <= res(dsize - 1 downto 0);
765         carry_out <= res(dsize);
766
767     elsif sel = ADDR_SIGNED_ADD then
768         res := ('0' & addr1) + ('0' & addr2);
769         addr_out <= res(dsize - 1 downto 0);
770 --        if (addr2(dsize - 1) = '0') then
771 --            ---positive value add.
772 --            if (res(dsize) = '1') then
773 --                carry_out <= '1';
774 --            else
775 --                carry_out <= '0';
776 --            end if;
777 --        else
778 --            ---negative value add.
779 --            if (res(dsize) = '0') then
780 --                carry_out <= '1';
781 --            else
782 --                carry_out <= '0';
783 --            end if;
784 --        end if;
785         -->>>simplified above.
786         if ((addr2(dsize - 1) xor res(dsize)) = '1') then
787             carry_out <= '1';
788         else
789             carry_out <= '0';
790         end if;
791
792     elsif sel = ADDR_INC then
793         res := ('0' & addr1) + "000000001";
794         addr_out <= res(dsize - 1 downto 0);
795         carry_out <= res(dsize);
796     elsif sel = ADDR_DEC then
797         res := ('0' & addr1) - "000000001";
798         addr_out <= res(dsize - 1 downto 0);
799         carry_out <= res(dsize);
800     end if;
801     end process;
802
803 end rtl;
804
805
806 -----------------------------------------
807 ------------- ALU Core -----------------
808 -----------------------------------------
809
810 library ieee;
811 use ieee.std_logic_1164.all;
812 use ieee.std_logic_unsigned.all;
813
814 ----d1 = acc
815 ----d2 = memory
816 entity alu_core is 
817     generic (   dsize : integer := 8
818             );
819     port ( 
820             sel         : in std_logic_vector (3 downto 0);
821             d1          : in std_logic_vector (dsize - 1 downto 0);
822             d2          : in std_logic_vector (dsize - 1 downto 0);
823             d_out       : out std_logic_vector (dsize - 1 downto 0);
824             carry_in    : in std_logic;
825             negative    : out std_logic;
826             zero        : out std_logic;
827             carry_out   : out std_logic;
828             overflow    : out std_logic
829     );
830 end alu_core;
831
832 architecture rtl of alu_core is
833
834 constant ALU_AND    : std_logic_vector (3 downto 0) := "0000";
835 constant ALU_EOR    : std_logic_vector (3 downto 0) := "0001";
836 constant ALU_OR     : std_logic_vector (3 downto 0) := "0010";
837 constant ALU_BIT    : std_logic_vector (3 downto 0) := "0011";
838 constant ALU_ADC    : std_logic_vector (3 downto 0) := "0100";
839 constant ALU_SBC    : std_logic_vector (3 downto 0) := "0101";
840 constant ALU_CMP    : std_logic_vector (3 downto 0) := "0110";
841 constant ALU_ASL    : std_logic_vector (3 downto 0) := "0111";
842 constant ALU_LSR    : std_logic_vector (3 downto 0) := "1000";
843 constant ALU_ROL    : std_logic_vector (3 downto 0) := "1001";
844 constant ALU_ROR    : std_logic_vector (3 downto 0) := "1010";
845 constant ALU_INC    : std_logic_vector (3 downto 0) := "1011";
846 constant ALU_DEC    : std_logic_vector (3 downto 0) := "1100";
847
848 begin
849
850     alu_p : process (sel, d1, d2, carry_in)
851     variable res : std_logic_vector (dsize downto 0);
852
853 procedure set_n (data : in std_logic_vector (dsize - 1 downto 0)) is
854 begin
855     if (data(7) = '1') then
856         negative <= '1';
857     else
858         negative <= '0';
859     end if;
860 end procedure;
861
862 procedure set_z (data : in std_logic_vector (dsize - 1 downto 0)) is
863 begin
864     if  (data = "00000000") then
865         zero <= '1';
866     else
867         zero <= '0';
868     end if;
869 end procedure;
870
871     begin
872     if sel = ALU_AND then
873         res(dsize - 1 downto 0) := d1 and d2;
874         set_n(res(dsize - 1 downto 0));
875         set_z(res(dsize - 1 downto 0));
876         d_out <= res(dsize - 1 downto 0);
877
878     elsif sel = ALU_EOR then
879         res(dsize - 1 downto 0) := d1 xor d2;
880         set_n(res(dsize - 1 downto 0));
881         set_z(res(dsize - 1 downto 0));
882         d_out <= res(dsize - 1 downto 0);
883
884     elsif sel = ALU_OR then
885         res(dsize - 1 downto 0) := d1 or d2;
886         set_n(res(dsize - 1 downto 0));
887         set_z(res(dsize - 1 downto 0));
888         d_out <= res(dsize - 1 downto 0);
889
890     elsif sel = ALU_BIT then
891         --transfer bit 7 and 6  of memory data to n, v flag.
892         negative <= d2(7);
893         overflow <= d2(6);
894         ----zero bit after A and M.
895         res(dsize - 1 downto 0) := d1 and d2;
896         set_z(res(dsize - 1 downto 0));
897
898     elsif sel = ALU_ADC then
899         res := ('0' & d1) + ('0' & d2) + carry_in;
900         d_out <= res(dsize - 1 downto 0);
901         carry_out <= res(dsize);
902         if ((d1(dsize - 1) = d2(dsize - 1)) 
903             and (d1(dsize - 1) /= res(dsize - 1))) then
904             overflow <= '1';
905         else
906             overflow <= '0';
907         end if;
908         set_n(res(dsize - 1 downto 0));
909         set_z(res(dsize - 1 downto 0));
910
911     elsif sel = ALU_SBC then
912         ---A - M - ~C -> A
913         res := ('0' & d1) - ('0' & d2) - not carry_in;
914         d_out <= res(dsize - 1 downto 0);
915
916         --c Set if unsigned borrow not required; cleared if unsigned borrow.
917         carry_out <= not res(dsize);
918         --v Set if signed borrow required; cleared if no signed borrow.
919         if ((d1(dsize - 1) /= d2(dsize - 1)) 
920             and (d1(dsize - 1) /= res(dsize - 1))) then
921             overflow <= '1';
922         else
923             overflow <= '0';
924         end if;
925         set_n(res(dsize - 1 downto 0));
926         set_z(res(dsize - 1 downto 0));
927
928     elsif sel = ALU_CMP then
929         res := ('0' & d1) - ('0' & d2);
930         if (d1 >= d2) then
931             carry_out <= '1';
932         else
933             carry_out <= '0';
934         end if;
935         set_n(res(dsize - 1 downto 0));
936         set_z(res(dsize - 1 downto 0));
937
938     elsif sel = ALU_ASL then
939         res(dsize - 1 downto 1) := d1(dsize - 2 downto 0);
940         res(0) := '0';
941
942         d_out <= res(dsize - 1 downto 0);
943         set_n(res(dsize - 1 downto 0));
944         set_z(res(dsize - 1 downto 0));
945         carry_out <= d1(dsize - 1);
946
947     elsif sel = ALU_LSR then
948         res(dsize - 1) := '0';
949         res(dsize - 2 downto 0) := d1(dsize - 1 downto 1);
950
951         d_out <= res(dsize - 1 downto 0);
952         set_n(res(dsize - 1 downto 0));
953         set_z(res(dsize - 1 downto 0));
954         carry_out <= d1(0);
955
956     elsif sel = ALU_ROL then
957         res(dsize - 1 downto 1) := d1(dsize - 2 downto 0);
958         res(0) := carry_in;
959
960         d_out <= res(dsize - 1 downto 0);
961         set_n(res(dsize - 1 downto 0));
962         set_z(res(dsize - 1 downto 0));
963         carry_out <= d1(7);
964
965     elsif sel = ALU_ROR then
966         res(dsize - 1) := carry_in;
967         res(dsize - 2 downto 0) := d1(dsize - 1 downto 1);
968
969         d_out <= res(dsize - 1 downto 0);
970         set_n(res(dsize - 1 downto 0));
971         set_z(res(dsize - 1 downto 0));
972         carry_out <= d1(0);
973
974     elsif sel = ALU_INC then
975         res := ('0' & d1) + "000000001";
976         d_out <= res(dsize - 1 downto 0);
977         set_n(res(dsize - 1 downto 0));
978         set_z(res(dsize - 1 downto 0));
979
980     elsif sel = ALU_DEC then
981         res := ('0' & d1) - "000000001";
982         d_out <= res(dsize - 1 downto 0);
983         set_n(res(dsize - 1 downto 0));
984         set_z(res(dsize - 1 downto 0));
985
986     end if;
987
988     end process;
989
990 end rtl;
991