OSDN Git Service

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