1 ----------------------------
2 ---- 6502 address calrucator
3 ----------------------------
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;
10 entity address_calcurator is
11 generic ( dsize : integer := 8
14 trig_clk : in std_logic;
17 instruction : in std_logic_vector (dsize - 1 downto 0);
18 exec_cycle : in std_logic_vector (5 downto 0);
21 pcl_inc_n : in std_logic;
22 sp_oe_n : in std_logic;
23 sp_push_n : in std_logic;
24 sp_pop_n : in std_logic;
25 abs_xy_n : in std_logic;
26 pg_next_n : in std_logic;
28 zp_xy_n : in std_logic;
29 rel_calc_n : in std_logic;
30 indir_n : in std_logic;
31 indir_x_n : in std_logic;
32 indir_y_n : in std_logic;
35 index_bus : in std_logic_vector (dsize - 1 downto 0);
36 bal : in std_logic_vector (dsize - 1 downto 0);
37 bah : in std_logic_vector (dsize - 1 downto 0);
38 int_d_bus : in std_logic_vector (dsize - 1 downto 0);
39 addr_back_l : out std_logic_vector (dsize - 1 downto 0);
40 addr_back_h : out std_logic_vector (dsize - 1 downto 0);
41 abl : out std_logic_vector (dsize - 1 downto 0);
42 abh : out std_logic_vector (dsize - 1 downto 0);
43 ea_carry : out std_logic
45 end address_calcurator;
47 architecture rtl of address_calcurator is
58 d : in std_logic_vector (dsize - 1 downto 0);
59 q : out std_logic_vector (dsize - 1 downto 0)
63 component d_flip_flop_bit
74 component tri_state_buffer
80 d : in std_logic_vector (dsize - 1 downto 0);
81 q : out std_logic_vector (dsize - 1 downto 0)
86 generic ( dsize : integer := 8
89 sel : in std_logic_vector (1 downto 0);
90 addr1 : in std_logic_vector (dsize - 1 downto 0);
91 addr2 : in std_logic_vector (dsize - 1 downto 0);
92 addr_out : out std_logic_vector (dsize - 1 downto 0);
93 carry_in : in std_logic;
94 carry_out : out std_logic
99 constant ADDR_ADC : std_logic_vector (1 downto 0) := "00";
100 constant ADDR_INC : std_logic_vector (1 downto 0) := "01";
101 constant ADDR_DEC : std_logic_vector (1 downto 0) := "10";
102 constant ADDR_SIGNED_ADD : std_logic_vector (1 downto 0) := "11";
104 ---for indirect addressing.
105 constant T0 : std_logic_vector (5 downto 0) := "000000";
106 constant T1 : std_logic_vector (5 downto 0) := "000001";
107 constant T2 : std_logic_vector (5 downto 0) := "000010";
108 constant T3 : std_logic_vector (5 downto 0) := "000011";
109 constant T4 : std_logic_vector (5 downto 0) := "000100";
110 constant T5 : std_logic_vector (5 downto 0) := "000101";
113 --------- signals for address calucuration ----------
114 signal al_buf_we_n : std_logic;
115 signal ah_buf_we_n : std_logic;
116 signal tmp_buf_we_n : std_logic;
118 signal al_reg_in : std_logic_vector (dsize - 1 downto 0);
119 signal ah_reg_in : std_logic_vector (dsize - 1 downto 0);
120 signal tmp_reg_in : std_logic_vector (dsize - 1 downto 0);
121 signal al_reg : std_logic_vector (dsize - 1 downto 0);
122 signal ah_reg : std_logic_vector (dsize - 1 downto 0);
123 signal tmp_reg : std_logic_vector (dsize - 1 downto 0);
125 signal a_sel : std_logic_vector (1 downto 0);
126 signal addr1 : std_logic_vector (dsize - 1 downto 0);
127 signal addr2 : std_logic_vector (dsize - 1 downto 0);
128 signal addr_out : std_logic_vector (dsize - 1 downto 0);
130 signal addr_c_in : std_logic;
131 signal addr_c : std_logic;
132 signal addr_c_reg : std_logic;
135 ----work registers...
136 al_dff : d_flip_flop generic map (dsize)
137 port map(trig_clk, '1', '1', al_buf_we_n, al_reg_in, al_reg);
138 ah_dff : d_flip_flop generic map (dsize)
139 port map(trig_clk, '1', '1', ah_buf_we_n, ah_reg_in, ah_reg);
140 tmp_dff : d_flip_flop generic map (dsize)
141 port map(trig_clk, '1', '1', tmp_buf_we_n, tmp_reg_in, tmp_reg);
142 ea_carry_dff_bit : d_flip_flop_bit
143 port map(trig_clk, '1', '1', '0', addr_c, addr_c_reg);
145 ----------------------------------------
146 -- address calucurator instances ----
147 ----------------------------------------
148 addr_calc_inst : addr_alu generic map (dsize)
149 port map (a_sel, addr1, addr2, addr_out, addr_c_in, addr_c);
151 ------------------------------------------------
152 ----- address calcuration state machine...-----
153 ------------------------------------------------
154 alu_addr_p : process (
155 pcl_inc_n, sp_oe_n, sp_pop_n, sp_push_n,
156 zp_n, zp_xy_n, abs_xy_n, pg_next_n, rel_calc_n,
157 int_d_bus(7), indir_n, indir_x_n, exec_cycle,
162 if (pcl_inc_n = '0') then
166 addr_back_l <= addr_out;
167 addr_back_h <= bah + addr_c;
171 elsif (sp_oe_n = '0') then
176 if (sp_push_n /= '0' and sp_pop_n /= '0') then
178 elsif (sp_pop_n = '0') then
182 addr_back_l <= addr_out;
188 addr_back_l <= addr_out;
191 elsif (zp_n = '0') then
193 if (zp_xy_n <= '0') then
206 elsif (abs_xy_n = '0') then
207 if (pg_next_n = '0') then
214 ---al is in the al_reg.
223 ---keep al for page crossed case
225 al_reg_in <= addr_out;
230 elsif (rel_calc_n = '0') then
231 if (pg_next_n = '0') then
232 if (int_d_bus(7) = '1') then
233 ---backward relative branch
236 ---forward relative branch
241 ---rel val is on the d_bus.
242 addr_back_h <= addr_out;
245 --keep the value in the cycle
247 ah_reg_in <= addr_out;
252 a_sel <= ADDR_SIGNED_ADD;
255 ---rel val is on the d_bus.
257 addr_back_l <= addr_out;
259 ea_carry <= addr_c_reg;
261 --keep the value in the cycle
263 al_reg_in <= addr_out;
267 elsif (indir_n = '0') then
276 elsif (indir_x_n = '0') then
277 if (exec_cycle = T2) then
278 ---input is IAL, but this cycle doesn't do anything....
285 elsif (exec_cycle = T3) then
295 tmp_reg_in <= addr_out;
303 al_reg_in <= int_d_bus;
305 elsif (exec_cycle = T4) then
319 ah_reg_in <= int_d_bus;
320 elsif (exec_cycle = T5 or exec_cycle = T0) then
326 end if; -- if (exec_cycle = T2) then
328 elsif (indir_y_n = '0') then
330 if (exec_cycle = T2) then
337 al_reg_in <= int_d_bus;
340 --get next address (IAL + 1)
344 tmp_reg_in <= addr_out;
346 elsif (exec_cycle = T3) then
357 ah_reg_in <= int_d_bus;
360 elsif (exec_cycle = T4) then
378 al_reg_in <= addr_out;
380 tmp_reg_in <= ah_reg;
381 elsif (exec_cycle = T5 or exec_cycle = T0) then
386 if (pg_next_n = '0') then
401 end if; -- if (exec_cycle = T2) then
411 ----addr_back is always bal for jmp/jsr instruction....
412 -----TODO must check later if it's ok.
415 end if; --if (pcl_inc_n = '0') then
424 ----------------------------
426 ----------------------------
428 use ieee.std_logic_1164.all;
429 use ieee.std_logic_unsigned.all;
430 use ieee.std_logic_arith.conv_std_logic_vector;
431 use work.motonesfpga_common.all;
434 generic ( dsize : integer := 8
437 set_clk : in std_logic;
438 trig_clk : in std_logic;
439 instruction : in std_logic_vector (dsize - 1 downto 0);
440 exec_cycle : in std_logic_vector (5 downto 0);
441 arith_en_n : in std_logic;
442 int_d_bus : inout std_logic_vector (dsize - 1 downto 0);
443 acc_in : out std_logic_vector (dsize - 1 downto 0);
444 acc_out : in std_logic_vector (dsize - 1 downto 0);
445 index_bus : in std_logic_vector (dsize - 1 downto 0);
446 carry_in : in std_logic;
447 negative : out std_logic;
448 zero : out std_logic;
449 carry_out : out std_logic;
450 overflow : out std_logic
454 architecture rtl of alu is
457 generic ( dsize : integer := 8
460 sel : in std_logic_vector (3 downto 0);
461 d1 : in std_logic_vector (dsize - 1 downto 0);
462 d2 : in std_logic_vector (dsize - 1 downto 0);
463 d_out : out std_logic_vector (dsize - 1 downto 0);
464 carry_in : in std_logic;
465 negative : out std_logic;
466 zero : out std_logic;
467 carry_out : out std_logic;
468 overflow : out std_logic
472 component d_flip_flop
478 res_n : in std_logic;
479 set_n : in std_logic;
481 d : in std_logic_vector (dsize - 1 downto 0);
482 q : out std_logic_vector (dsize - 1 downto 0)
486 component tri_state_buffer
492 d : in std_logic_vector (dsize - 1 downto 0);
493 q : out std_logic_vector (dsize - 1 downto 0)
497 constant ALU_AND : std_logic_vector (3 downto 0) := "0000";
498 constant ALU_EOR : std_logic_vector (3 downto 0) := "0001";
499 constant ALU_OR : std_logic_vector (3 downto 0) := "0010";
500 constant ALU_BIT : std_logic_vector (3 downto 0) := "0011";
501 constant ALU_ADC : std_logic_vector (3 downto 0) := "0100";
502 constant ALU_SBC : std_logic_vector (3 downto 0) := "0101";
503 constant ALU_CMP : std_logic_vector (3 downto 0) := "0110";
504 constant ALU_ASL : std_logic_vector (3 downto 0) := "0111";
505 constant ALU_LSR : std_logic_vector (3 downto 0) := "1000";
506 constant ALU_ROL : std_logic_vector (3 downto 0) := "1001";
507 constant ALU_ROR : std_logic_vector (3 downto 0) := "1010";
508 constant ALU_INC : std_logic_vector (3 downto 0) := "1011";
509 constant ALU_DEC : std_logic_vector (3 downto 0) := "1100";
511 constant T0 : std_logic_vector (5 downto 0) := "000000";
512 constant T1 : std_logic_vector (5 downto 0) := "000001";
513 constant T2 : std_logic_vector (5 downto 0) := "000010";
514 constant T3 : std_logic_vector (5 downto 0) := "000011";
515 constant T4 : std_logic_vector (5 downto 0) := "000100";
516 constant T5 : std_logic_vector (5 downto 0) := "000101";
518 ----------- signals for arithmatic ----------
519 signal sel : std_logic_vector (3 downto 0);
520 signal d1 : std_logic_vector (dsize - 1 downto 0);
521 signal d2 : std_logic_vector (dsize - 1 downto 0);
522 signal d_out : std_logic_vector (dsize - 1 downto 0);
523 signal alu_out : std_logic_vector (dsize - 1 downto 0);
525 signal n : std_logic;
526 signal z : std_logic;
527 signal c : std_logic;
528 signal v : std_logic;
530 signal arith_buf_we_n : std_logic;
531 signal arith_buf_oe_n : std_logic;
532 signal arith_reg_in : std_logic_vector (dsize - 1 downto 0);
533 signal arith_reg : std_logic_vector (dsize - 1 downto 0);
534 signal arith_reg_out : std_logic_vector (dsize - 1 downto 0);
535 signal d_oe_n : std_logic;
538 ----------------------------------------
539 -- arithmatic operation instances ----
540 ----------------------------------------
541 arith_dff : d_flip_flop generic map (dsize)
542 port map(trig_clk, '1', '1', arith_buf_we_n, arith_reg_in, arith_reg);
543 arith_buf : tri_state_buffer generic map (dsize)
544 port map (arith_buf_oe_n, arith_reg, arith_reg_out);
546 alu_inst : alu_core generic map (dsize)
547 port map (sel, d1, d2, alu_out, carry_in, n, z, c, v);
548 alu_buf : tri_state_buffer generic map (dsize)
549 port map (d_oe_n, alu_out, d_out);
551 alu_arith_p : process (
553 instruction, exec_cycle, int_d_bus, acc_out,
556 --data calcuration follows the bus input...
558 procedure output_d_bus is
560 arith_buf_we_n <= '0';
561 arith_buf_oe_n <= '0';
563 arith_reg_in <= d_out;
564 if (set_clk = '0') then
567 int_d_bus <= arith_reg_out;
578 if (arith_en_n = '0') then
580 if instruction = conv_std_logic_vector(16#ca#, dsize) then
587 elsif instruction = conv_std_logic_vector(16#88#, dsize) then
594 elsif instruction = conv_std_logic_vector(16#e8#, dsize) then
601 elsif instruction = conv_std_logic_vector(16#c8#, dsize) then
608 elsif instruction = conv_std_logic_vector(16#0a#, dsize) then
616 elsif instruction = conv_std_logic_vector(16#2a#, dsize) then
624 elsif instruction = conv_std_logic_vector(16#4a#, dsize) then
632 elsif instruction = conv_std_logic_vector(16#6a#, dsize) then
640 --instruction is aaabbbcc format.
650 elsif instruction (1 downto 0) = "01" then
651 if instruction (7 downto 5) = "000" then
660 elsif instruction (7 downto 5) = "001" then
669 elsif instruction (7 downto 5) = "010" then
678 elsif instruction (7 downto 5) = "011" then
690 elsif instruction (7 downto 5) = "110" then
699 elsif instruction (7 downto 5) = "111" then
711 end if; --if instruction (7 downto 5) = "000" then
713 elsif instruction (1 downto 0) = "10" then
715 --this group is all memory to memory instruction (except for stx/ldx).
716 --memory to memory operation takes two cycles.
717 --first is write original data
718 --second is write modified data
724 if ((exec_cycle = T2 and instruction (4 downto 2) = "001") or
725 (exec_cycle = T3 and instruction (4 downto 2) = "011") or
726 (exec_cycle = T3 and instruction (4 downto 2) = "101") or
727 (exec_cycle = T4 and instruction (4 downto 2) = "111")) then
728 arith_buf_we_n <= '0';
729 arith_reg_in <= int_d_bus;
731 elsif ((exec_cycle = T3 and instruction (4 downto 2) = "001") or
732 (exec_cycle = T4 and instruction (4 downto 2) = "011") or
733 (exec_cycle = T4 and instruction (4 downto 2) = "101") or
734 (exec_cycle = T5 and instruction (4 downto 2) = "111")) then
735 --first cycle. keep input variable.
736 --d_print("inc first.");
737 arith_buf_we_n <= '1';
739 arith_buf_oe_n <= '1';
744 --second cycle read from register, output modified data.
745 --d_print("inc second...");
746 arith_buf_we_n <= '1';
747 arith_buf_oe_n <= '0';
753 if instruction (7 downto 5) = "000" then
759 elsif instruction (7 downto 5) = "001" then
765 elsif instruction (7 downto 5) = "010" then
771 elsif instruction (7 downto 5) = "011" then
777 elsif instruction (7 downto 5) = "110" then
782 elsif instruction (7 downto 5) = "111" then
783 --d_print("alu inc");
787 end if; --if instruction (7 downto 5) = "000" then
789 elsif instruction (1 downto 0) = "00" then
790 if instruction (7 downto 5) = "001" then
797 elsif instruction (7 downto 5) = "110" then
805 elsif instruction (7 downto 5) = "111" then
813 end if; --if instruction (7 downto 5) = "001" then
814 end if; --if instruction = conv_std_logic_vector(16#ca#, dsize)
816 --d_print("no arith");
818 arith_buf_we_n <= '1';
819 arith_buf_oe_n <= '1';
820 int_d_bus <= (others => 'Z');
821 end if; -- if (arith_en_n = '0') then
827 -----------------------------------------
828 ------- Address calcuration core -----
829 -----------------------------------------
832 use ieee.std_logic_1164.all;
833 use ieee.std_logic_unsigned.all;
836 generic ( dsize : integer := 8
839 sel : in std_logic_vector (1 downto 0);
840 addr1 : in std_logic_vector (dsize - 1 downto 0);
841 addr2 : in std_logic_vector (dsize - 1 downto 0);
842 addr_out : out std_logic_vector (dsize - 1 downto 0);
843 carry_in : in std_logic;
844 carry_out : out std_logic
848 architecture rtl of addr_alu is
850 constant ADDR_ADC : std_logic_vector (1 downto 0) := "00";
851 constant ADDR_INC : std_logic_vector (1 downto 0) := "01";
852 constant ADDR_DEC : std_logic_vector (1 downto 0) := "10";
853 constant ADDR_SIGNED_ADD : std_logic_vector (1 downto 0) := "11";
857 alu_p : process (sel, addr1, addr2, carry_in)
858 variable res : std_logic_vector (dsize downto 0);
861 if sel = ADDR_ADC then
862 res := ('0' & addr1) + ('0' & addr2) + carry_in;
863 addr_out <= res(dsize - 1 downto 0);
864 carry_out <= res(dsize);
866 elsif sel = ADDR_SIGNED_ADD then
867 res := ('0' & addr1) + ('0' & addr2);
868 addr_out <= res(dsize - 1 downto 0);
869 -->>>simplified above.
870 if ((addr2(dsize - 1) xor res(dsize)) = '1') then
876 elsif sel = ADDR_INC then
877 res := ('0' & addr1) + "000000001";
878 addr_out <= res(dsize - 1 downto 0);
879 carry_out <= res(dsize);
880 elsif sel = ADDR_DEC then
881 res := ('0' & addr1) - "000000001";
882 addr_out <= res(dsize - 1 downto 0);
883 carry_out <= res(dsize);
890 -----------------------------------------
891 ------------ ALU Core -----------------
892 -----------------------------------------
895 use ieee.std_logic_1164.all;
896 use ieee.std_logic_unsigned.all;
901 generic ( dsize : integer := 8
904 sel : in std_logic_vector (3 downto 0);
905 d1 : in std_logic_vector (dsize - 1 downto 0);
906 d2 : in std_logic_vector (dsize - 1 downto 0);
907 d_out : out std_logic_vector (dsize - 1 downto 0);
908 carry_in : in std_logic;
909 negative : out std_logic;
910 zero : out std_logic;
911 carry_out : out std_logic;
912 overflow : out std_logic
916 architecture rtl of alu_core is
918 constant ALU_AND : std_logic_vector (3 downto 0) := "0000";
919 constant ALU_EOR : std_logic_vector (3 downto 0) := "0001";
920 constant ALU_OR : std_logic_vector (3 downto 0) := "0010";
921 constant ALU_BIT : std_logic_vector (3 downto 0) := "0011";
922 constant ALU_ADC : std_logic_vector (3 downto 0) := "0100";
923 constant ALU_SBC : std_logic_vector (3 downto 0) := "0101";
924 constant ALU_CMP : std_logic_vector (3 downto 0) := "0110";
925 constant ALU_ASL : std_logic_vector (3 downto 0) := "0111";
926 constant ALU_LSR : std_logic_vector (3 downto 0) := "1000";
927 constant ALU_ROL : std_logic_vector (3 downto 0) := "1001";
928 constant ALU_ROR : std_logic_vector (3 downto 0) := "1010";
929 constant ALU_INC : std_logic_vector (3 downto 0) := "1011";
930 constant ALU_DEC : std_logic_vector (3 downto 0) := "1100";
934 alu_p : process (sel, d1, d2, carry_in)
935 variable res : std_logic_vector (dsize downto 0);
937 procedure set_n (data : in std_logic_vector (dsize - 1 downto 0)) is
939 if (data(7) = '1') then
946 procedure set_z (data : in std_logic_vector (dsize - 1 downto 0)) is
948 if (data = "00000000") then
956 if sel = ALU_AND then
957 res(dsize - 1 downto 0) := d1 and d2;
958 set_n(res(dsize - 1 downto 0));
959 set_z(res(dsize - 1 downto 0));
960 d_out <= res(dsize - 1 downto 0);
962 elsif sel = ALU_EOR then
963 res(dsize - 1 downto 0) := d1 xor d2;
964 set_n(res(dsize - 1 downto 0));
965 set_z(res(dsize - 1 downto 0));
966 d_out <= res(dsize - 1 downto 0);
968 elsif sel = ALU_OR then
969 res(dsize - 1 downto 0) := d1 or d2;
970 set_n(res(dsize - 1 downto 0));
971 set_z(res(dsize - 1 downto 0));
972 d_out <= res(dsize - 1 downto 0);
974 elsif sel = ALU_BIT then
975 --transfer bit 7 and 6 of memory data to n, v flag.
978 ----zero bit after A and M.
979 res(dsize - 1 downto 0) := d1 and d2;
980 set_z(res(dsize - 1 downto 0));
982 elsif sel = ALU_ADC then
983 res := ('0' & d1) + ('0' & d2) + carry_in;
984 d_out <= res(dsize - 1 downto 0);
985 carry_out <= res(dsize);
986 if ((d1(dsize - 1) = d2(dsize - 1))
987 and (d1(dsize - 1) /= res(dsize - 1))) then
992 set_n(res(dsize - 1 downto 0));
993 set_z(res(dsize - 1 downto 0));
995 elsif sel = ALU_SBC then
997 res := ('0' & d1) - ('0' & d2) - not carry_in;
998 d_out <= res(dsize - 1 downto 0);
1000 --c Set if unsigned borrow not required; cleared if unsigned borrow.
1001 carry_out <= not res(dsize);
1002 --v Set if signed borrow required; cleared if no signed borrow.
1003 if ((d1(dsize - 1) /= d2(dsize - 1))
1004 and (d1(dsize - 1) /= res(dsize - 1))) then
1009 set_n(res(dsize - 1 downto 0));
1010 set_z(res(dsize - 1 downto 0));
1012 elsif sel = ALU_CMP then
1013 res := ('0' & d1) - ('0' & d2);
1019 set_n(res(dsize - 1 downto 0));
1020 set_z(res(dsize - 1 downto 0));
1022 elsif sel = ALU_ASL then
1023 res(dsize - 1 downto 1) := d1(dsize - 2 downto 0);
1026 d_out <= res(dsize - 1 downto 0);
1027 set_n(res(dsize - 1 downto 0));
1028 set_z(res(dsize - 1 downto 0));
1029 carry_out <= d1(dsize - 1);
1031 elsif sel = ALU_LSR then
1032 res(dsize - 1) := '0';
1033 res(dsize - 2 downto 0) := d1(dsize - 1 downto 1);
1035 d_out <= res(dsize - 1 downto 0);
1036 set_n(res(dsize - 1 downto 0));
1037 set_z(res(dsize - 1 downto 0));
1040 elsif sel = ALU_ROL then
1041 res(dsize - 1 downto 1) := d1(dsize - 2 downto 0);
1044 d_out <= res(dsize - 1 downto 0);
1045 set_n(res(dsize - 1 downto 0));
1046 set_z(res(dsize - 1 downto 0));
1049 elsif sel = ALU_ROR then
1050 res(dsize - 1) := carry_in;
1051 res(dsize - 2 downto 0) := d1(dsize - 1 downto 1);
1053 d_out <= res(dsize - 1 downto 0);
1054 set_n(res(dsize - 1 downto 0));
1055 set_z(res(dsize - 1 downto 0));
1058 elsif sel = ALU_INC then
1059 res := ('0' & d1) + "000000001";
1060 d_out <= res(dsize - 1 downto 0);
1061 set_n(res(dsize - 1 downto 0));
1062 set_z(res(dsize - 1 downto 0));
1064 elsif sel = ALU_DEC then
1065 res := ('0' & d1) - "000000001";
1066 d_out <= res(dsize - 1 downto 0);
1067 set_n(res(dsize - 1 downto 0));
1068 set_z(res(dsize - 1 downto 0));