1 ----------------------------
2 ---- 6502 ALU implementation
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;
11 generic ( dsize : integer := 8
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;
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;
44 carry_out : out std_logic;
45 overflow : out std_logic
49 architecture rtl of alu is
60 d : in std_logic_vector (dsize - 1 downto 0);
61 q : out std_logic_vector (dsize - 1 downto 0)
65 component d_flip_flop_bit
76 component tri_state_buffer
82 d : in std_logic_vector (dsize - 1 downto 0);
83 q : out std_logic_vector (dsize - 1 downto 0)
87 component address_calculator
88 generic ( dsize : integer := 8
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
101 generic ( dsize : integer := 8
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
116 --------- signals for address calucuration ----------
117 signal al_buf_we_n : std_logic;
118 signal ah_buf_we_n : std_logic;
119 signal tmp_buf_we_n : std_logic;
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 tmp_reg_in : std_logic_vector (dsize - 1 downto 0);
124 signal al_reg : std_logic_vector (dsize - 1 downto 0);
125 signal ah_reg : std_logic_vector (dsize - 1 downto 0);
126 signal tmp_reg : std_logic_vector (dsize - 1 downto 0);
129 signal a_sel : std_logic_vector (1 downto 0);
130 signal addr1 : std_logic_vector (dsize - 1 downto 0);
131 signal addr2 : std_logic_vector (dsize - 1 downto 0);
132 signal addr_out : std_logic_vector (dsize - 1 downto 0);
134 signal addr_c_in : std_logic;
135 signal addr_c : std_logic;
136 signal addr_c_reg : std_logic;
138 signal pcl_carry_reg_in : std_logic;
140 ----------- signals for arithmatic ----------
141 signal sel : std_logic_vector (3 downto 0);
142 signal d1 : std_logic_vector (dsize - 1 downto 0);
143 signal d2 : std_logic_vector (dsize - 1 downto 0);
144 signal d_out : std_logic_vector (dsize - 1 downto 0);
145 signal alu_out : std_logic_vector (dsize - 1 downto 0);
147 signal n : std_logic;
148 signal z : std_logic;
149 signal c : std_logic;
150 signal v : std_logic;
152 signal arith_buf_we_n : std_logic;
153 signal arith_buf_oe_n : std_logic;
154 signal arith_reg_in : std_logic_vector (dsize - 1 downto 0);
155 signal arith_reg : std_logic_vector (dsize - 1 downto 0);
156 signal arith_reg_out : std_logic_vector (dsize - 1 downto 0);
157 signal d_oe_n : std_logic;
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 tmp_dff : d_flip_flop generic map (dsize)
168 port map(clk, '1', '1', tmp_buf_we_n, tmp_reg_in, tmp_reg);
170 --pcl carry flag set.
171 pcl_carry_reg_in <= addr_c when pcl_inc_n = '0' else
174 pch_carry_dff_bit : d_flip_flop_bit
175 port map(clk, '1', '1',
176 '0', pcl_carry_reg_in, pcl_inc_carry);
178 addr_calc_inst : address_calculator generic map (dsize)
179 port map (a_sel, addr1, addr2, addr_out, addr_c_in, addr_c);
181 ea_carry_dff_bit : d_flip_flop_bit
182 port map(clk, '1', '1',
183 '0', addr_c, addr_c_reg);
185 ----------------------------------------
186 -- arithmatic operation instances ----
187 ----------------------------------------
188 arith_dff : d_flip_flop generic map (dsize)
189 port map(clk, '1', '1', arith_buf_we_n, arith_reg_in, arith_reg);
190 arith_buf : tri_state_buffer generic map (dsize)
191 port map (arith_buf_oe_n, arith_reg, arith_reg_out);
193 alu_inst : alu_core generic map (dsize)
194 port map (sel, d1, d2, alu_out, carry_in, n, z, c, v);
195 alu_buf : tri_state_buffer generic map (dsize)
196 port map (d_oe_n, alu_out, d_out);
198 -------------------------------
199 ------ alu main process -------
200 -------------------------------
203 ---for address calucuration
204 pcl_inc_n, pch_inc_n, sp_oe_n, sp_push_n, sp_pop_n,
205 abs_xy_n, pg_next_n, zp_n, zp_xy_n, rel_calc_n,
206 indir_n, indir_x_n, indir_y_n,
209 --for arithmatic operation.
211 instruction, exec_cycle, int_d_bus, acc_out,
215 constant ADDR_ADC : std_logic_vector (1 downto 0) := "00";
216 constant ADDR_INC : std_logic_vector (1 downto 0) := "01";
217 constant ADDR_DEC : std_logic_vector (1 downto 0) := "10";
218 constant ADDR_SIGNED_ADD : std_logic_vector (1 downto 0) := "11";
220 constant ALU_AND : std_logic_vector (3 downto 0) := "0000";
221 constant ALU_EOR : std_logic_vector (3 downto 0) := "0001";
222 constant ALU_OR : std_logic_vector (3 downto 0) := "0010";
223 constant ALU_BIT : std_logic_vector (3 downto 0) := "0011";
224 constant ALU_ADC : std_logic_vector (3 downto 0) := "0100";
225 constant ALU_SBC : std_logic_vector (3 downto 0) := "0101";
226 constant ALU_CMP : std_logic_vector (3 downto 0) := "0110";
227 constant ALU_ASL : std_logic_vector (3 downto 0) := "0111";
228 constant ALU_LSR : std_logic_vector (3 downto 0) := "1000";
229 constant ALU_ROL : std_logic_vector (3 downto 0) := "1001";
230 constant ALU_ROR : std_logic_vector (3 downto 0) := "1010";
231 constant ALU_INC : std_logic_vector (3 downto 0) := "1011";
232 constant ALU_DEC : std_logic_vector (3 downto 0) := "1100";
234 ---for indirect addressing.
235 constant T0 : std_logic_vector (5 downto 0) := "000000";
236 constant T1 : std_logic_vector (5 downto 0) := "000001";
237 constant T2 : std_logic_vector (5 downto 0) := "000010";
238 constant T3 : std_logic_vector (5 downto 0) := "000011";
239 constant T4 : std_logic_vector (5 downto 0) := "000100";
240 constant T5 : std_logic_vector (5 downto 0) := "000101";
242 procedure output_d_bus is
244 arith_buf_we_n <= '0';
245 arith_buf_oe_n <= '0';
247 arith_reg_in <= d_out;
251 int_d_bus <= arith_reg_out;
263 -------------------------------
264 ----- address calcuration -----
265 -------------------------------
266 if (pcl_inc_n = '0') then
270 addr_back <= addr_out;
272 --keep the value in the cycle
275 if (instruction = "01001100") then
276 ---exceptional case: only jmp instruction
287 elsif (pch_inc_n = '0') then
291 addr_back <= addr_out;
293 --inc pch cycle is not fetch cycle.
294 --it is special cycle.
298 elsif (sp_oe_n = '0') then
303 if (sp_push_n /= '0' and sp_pop_n /= '0') then
305 elsif (sp_pop_n = '0') then
309 addr_back <= addr_out;
322 addr_back <= addr_out;
332 elsif (zp_n = '0') then
334 if (zp_xy_n <= '0') then
347 elsif (abs_xy_n = '0') then
348 if (pg_next_n = '0') then
355 ---al is in the al_reg.
364 ---keep al for page crossed case
366 al_reg_in <= addr_out;
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
377 ---forward relative branch
382 ---rel val is on the d_bus.
383 addr_back <= addr_out;
386 --keep the value in the cycle
388 ah_reg_in <= addr_out;
393 a_sel <= ADDR_SIGNED_ADD;
396 ---rel val is on the d_bus.
398 addr_back <= addr_out;
400 ea_carry <= addr_c_reg;
402 --keep the value in the cycle
404 al_reg_in <= addr_out;
408 elsif (indir_n = '0') then
417 elsif (indir_x_n = '0') then
418 if (exec_cycle = T2) then
419 ---input is IAL, but this cycle doesn't do anything....
426 elsif (exec_cycle = T3) then
436 tmp_reg_in <= addr_out;
444 al_reg_in <= int_d_bus;
446 elsif (exec_cycle = T4) then
460 ah_reg_in <= int_d_bus;
461 elsif (exec_cycle = T5 or exec_cycle = T0) then
467 end if; -- if (exec_cycle = T2) then
469 elsif (indir_y_n = '0') then
471 if (exec_cycle = T2) then
478 al_reg_in <= int_d_bus;
481 --get next address (IAL + 1)
485 tmp_reg_in <= addr_out;
487 elsif (exec_cycle = T3) then
498 ah_reg_in <= int_d_bus;
501 elsif (exec_cycle = T4) then
519 al_reg_in <= addr_out;
521 tmp_reg_in <= ah_reg;
522 elsif (exec_cycle = T5 or exec_cycle = T0) then
527 if (pg_next_n = '0') then
542 end if; -- if (exec_cycle = T2) then
552 ----addr_back is always bal for jmp/jsr instruction....
553 -----TODO must check later if it's ok.
555 end if; --if (pcl_inc_n = '0') then
557 -------------------------------
558 ---- arithmatic operations-----
559 -------------------------------
560 if (arith_en_n = '0') then
562 if instruction = conv_std_logic_vector(16#ca#, dsize) then
569 elsif instruction = conv_std_logic_vector(16#88#, dsize) then
576 elsif instruction = conv_std_logic_vector(16#e8#, dsize) then
583 elsif instruction = conv_std_logic_vector(16#c8#, dsize) then
590 elsif instruction = conv_std_logic_vector(16#0a#, dsize) then
598 elsif instruction = conv_std_logic_vector(16#2a#, dsize) then
606 elsif instruction = conv_std_logic_vector(16#4a#, dsize) then
614 elsif instruction = conv_std_logic_vector(16#6a#, dsize) then
622 --instruction is aaabbbcc format.
632 elsif instruction (1 downto 0) = "01" then
633 if instruction (7 downto 5) = "000" then
642 elsif instruction (7 downto 5) = "001" then
651 elsif instruction (7 downto 5) = "010" then
660 elsif instruction (7 downto 5) = "011" then
672 elsif instruction (7 downto 5) = "110" then
681 elsif instruction (7 downto 5) = "111" then
693 end if; --if instruction (7 downto 5) = "000" then
695 elsif instruction (1 downto 0) = "10" then
697 --this group is all memory to memory instruction (except for stx/ldx).
698 --memory to memory operation takes two cycles.
699 --first is write original data
700 --second is write modified data
706 if ((exec_cycle = T2 and instruction (4 downto 2) = "001") or
707 (exec_cycle = T3 and instruction (4 downto 2) = "011") or
708 (exec_cycle = T3 and instruction (4 downto 2) = "101") or
709 (exec_cycle = T4 and instruction (4 downto 2) = "111")) then
710 arith_buf_we_n <= '0';
711 arith_reg_in <= int_d_bus;
713 elsif ((exec_cycle = T3 and instruction (4 downto 2) = "001") or
714 (exec_cycle = T4 and instruction (4 downto 2) = "011") or
715 (exec_cycle = T4 and instruction (4 downto 2) = "101") or
716 (exec_cycle = T5 and instruction (4 downto 2) = "111")) then
717 --first cycle. keep input variable.
718 --d_print("inc first.");
719 arith_buf_we_n <= '1';
721 arith_buf_oe_n <= '1';
726 --second cycle read from register, output modified data.
727 --d_print("inc second...");
728 arith_buf_we_n <= '1';
729 arith_buf_oe_n <= '0';
735 if instruction (7 downto 5) = "000" then
741 elsif instruction (7 downto 5) = "001" then
747 elsif instruction (7 downto 5) = "010" then
753 elsif instruction (7 downto 5) = "011" then
759 elsif instruction (7 downto 5) = "110" then
764 elsif instruction (7 downto 5) = "111" then
765 --d_print("alu inc");
769 end if; --if instruction (7 downto 5) = "000" then
771 elsif instruction (1 downto 0) = "00" then
772 if instruction (7 downto 5) = "001" then
779 elsif instruction (7 downto 5) = "110" then
787 elsif instruction (7 downto 5) = "111" then
795 end if; --if instruction (7 downto 5) = "001" then
796 end if; --if instruction = conv_std_logic_vector(16#ca#, dsize)
798 --d_print("no arith");
800 arith_buf_we_n <= '1';
801 arith_buf_oe_n <= '1';
802 int_d_bus <= (others => 'Z');
803 end if; -- if (arith_en_n = '0') then
809 -----------------------------------------
810 ---------- Address calculator------------
811 -----------------------------------------
814 use ieee.std_logic_1164.all;
815 use ieee.std_logic_unsigned.all;
817 entity address_calculator is
818 generic ( dsize : integer := 8
821 sel : in std_logic_vector (1 downto 0);
822 addr1 : in std_logic_vector (dsize - 1 downto 0);
823 addr2 : in std_logic_vector (dsize - 1 downto 0);
824 addr_out : out std_logic_vector (dsize - 1 downto 0);
825 carry_in : in std_logic;
826 carry_out : out std_logic
828 end address_calculator;
830 architecture rtl of address_calculator is
832 constant ADDR_ADC : std_logic_vector (1 downto 0) := "00";
833 constant ADDR_INC : std_logic_vector (1 downto 0) := "01";
834 constant ADDR_DEC : std_logic_vector (1 downto 0) := "10";
835 constant ADDR_SIGNED_ADD : std_logic_vector (1 downto 0) := "11";
839 alu_p : process (sel, addr1, addr2, carry_in)
840 variable res : std_logic_vector (dsize downto 0);
843 if sel = ADDR_ADC then
844 res := ('0' & addr1) + ('0' & addr2) + carry_in;
845 addr_out <= res(dsize - 1 downto 0);
846 carry_out <= res(dsize);
848 elsif sel = ADDR_SIGNED_ADD then
849 res := ('0' & addr1) + ('0' & addr2);
850 addr_out <= res(dsize - 1 downto 0);
851 -- if (addr2(dsize - 1) = '0') then
852 -- ---positive value add.
853 -- if (res(dsize) = '1') then
859 -- ---negative value add.
860 -- if (res(dsize) = '0') then
866 -->>>simplified above.
867 if ((addr2(dsize - 1) xor res(dsize)) = '1') then
873 elsif sel = ADDR_INC then
874 res := ('0' & addr1) + "000000001";
875 addr_out <= res(dsize - 1 downto 0);
876 carry_out <= res(dsize);
877 elsif sel = ADDR_DEC then
878 res := ('0' & addr1) - "000000001";
879 addr_out <= res(dsize - 1 downto 0);
880 carry_out <= res(dsize);
887 -----------------------------------------
888 ------------- ALU Core -----------------
889 -----------------------------------------
892 use ieee.std_logic_1164.all;
893 use ieee.std_logic_unsigned.all;
898 generic ( dsize : integer := 8
901 sel : in std_logic_vector (3 downto 0);
902 d1 : in std_logic_vector (dsize - 1 downto 0);
903 d2 : in std_logic_vector (dsize - 1 downto 0);
904 d_out : out std_logic_vector (dsize - 1 downto 0);
905 carry_in : in std_logic;
906 negative : out std_logic;
907 zero : out std_logic;
908 carry_out : out std_logic;
909 overflow : out std_logic
913 architecture rtl of alu_core is
915 constant ALU_AND : std_logic_vector (3 downto 0) := "0000";
916 constant ALU_EOR : std_logic_vector (3 downto 0) := "0001";
917 constant ALU_OR : std_logic_vector (3 downto 0) := "0010";
918 constant ALU_BIT : std_logic_vector (3 downto 0) := "0011";
919 constant ALU_ADC : std_logic_vector (3 downto 0) := "0100";
920 constant ALU_SBC : std_logic_vector (3 downto 0) := "0101";
921 constant ALU_CMP : std_logic_vector (3 downto 0) := "0110";
922 constant ALU_ASL : std_logic_vector (3 downto 0) := "0111";
923 constant ALU_LSR : std_logic_vector (3 downto 0) := "1000";
924 constant ALU_ROL : std_logic_vector (3 downto 0) := "1001";
925 constant ALU_ROR : std_logic_vector (3 downto 0) := "1010";
926 constant ALU_INC : std_logic_vector (3 downto 0) := "1011";
927 constant ALU_DEC : std_logic_vector (3 downto 0) := "1100";
931 alu_p : process (sel, d1, d2, carry_in)
932 variable res : std_logic_vector (dsize downto 0);
934 procedure set_n (data : in std_logic_vector (dsize - 1 downto 0)) is
936 if (data(7) = '1') then
943 procedure set_z (data : in std_logic_vector (dsize - 1 downto 0)) is
945 if (data = "00000000") then
953 if sel = ALU_AND then
954 res(dsize - 1 downto 0) := d1 and d2;
955 set_n(res(dsize - 1 downto 0));
956 set_z(res(dsize - 1 downto 0));
957 d_out <= res(dsize - 1 downto 0);
959 elsif sel = ALU_EOR then
960 res(dsize - 1 downto 0) := d1 xor d2;
961 set_n(res(dsize - 1 downto 0));
962 set_z(res(dsize - 1 downto 0));
963 d_out <= res(dsize - 1 downto 0);
965 elsif sel = ALU_OR then
966 res(dsize - 1 downto 0) := d1 or d2;
967 set_n(res(dsize - 1 downto 0));
968 set_z(res(dsize - 1 downto 0));
969 d_out <= res(dsize - 1 downto 0);
971 elsif sel = ALU_BIT then
972 --transfer bit 7 and 6 of memory data to n, v flag.
975 ----zero bit after A and M.
976 res(dsize - 1 downto 0) := d1 and d2;
977 set_z(res(dsize - 1 downto 0));
979 elsif sel = ALU_ADC then
980 res := ('0' & d1) + ('0' & d2) + carry_in;
981 d_out <= res(dsize - 1 downto 0);
982 carry_out <= res(dsize);
983 if ((d1(dsize - 1) = d2(dsize - 1))
984 and (d1(dsize - 1) /= res(dsize - 1))) then
989 set_n(res(dsize - 1 downto 0));
990 set_z(res(dsize - 1 downto 0));
992 elsif sel = ALU_SBC then
994 res := ('0' & d1) - ('0' & d2) - not carry_in;
995 d_out <= res(dsize - 1 downto 0);
997 --c Set if unsigned borrow not required; cleared if unsigned borrow.
998 carry_out <= not res(dsize);
999 --v Set if signed borrow required; cleared if no signed borrow.
1000 if ((d1(dsize - 1) /= d2(dsize - 1))
1001 and (d1(dsize - 1) /= res(dsize - 1))) then
1006 set_n(res(dsize - 1 downto 0));
1007 set_z(res(dsize - 1 downto 0));
1009 elsif sel = ALU_CMP then
1010 res := ('0' & d1) - ('0' & d2);
1016 set_n(res(dsize - 1 downto 0));
1017 set_z(res(dsize - 1 downto 0));
1019 elsif sel = ALU_ASL then
1020 res(dsize - 1 downto 1) := d1(dsize - 2 downto 0);
1023 d_out <= res(dsize - 1 downto 0);
1024 set_n(res(dsize - 1 downto 0));
1025 set_z(res(dsize - 1 downto 0));
1026 carry_out <= d1(dsize - 1);
1028 elsif sel = ALU_LSR then
1029 res(dsize - 1) := '0';
1030 res(dsize - 2 downto 0) := d1(dsize - 1 downto 1);
1032 d_out <= res(dsize - 1 downto 0);
1033 set_n(res(dsize - 1 downto 0));
1034 set_z(res(dsize - 1 downto 0));
1037 elsif sel = ALU_ROL then
1038 res(dsize - 1 downto 1) := d1(dsize - 2 downto 0);
1041 d_out <= res(dsize - 1 downto 0);
1042 set_n(res(dsize - 1 downto 0));
1043 set_z(res(dsize - 1 downto 0));
1046 elsif sel = ALU_ROR then
1047 res(dsize - 1) := carry_in;
1048 res(dsize - 2 downto 0) := d1(dsize - 1 downto 1);
1050 d_out <= res(dsize - 1 downto 0);
1051 set_n(res(dsize - 1 downto 0));
1052 set_z(res(dsize - 1 downto 0));
1055 elsif sel = ALU_INC then
1056 res := ('0' & d1) + "000000001";
1057 d_out <= res(dsize - 1 downto 0);
1058 set_n(res(dsize - 1 downto 0));
1059 set_z(res(dsize - 1 downto 0));
1061 elsif sel = ALU_DEC then
1062 res := ('0' & d1) - "000000001";
1063 d_out <= res(dsize - 1 downto 0);
1064 set_n(res(dsize - 1 downto 0));
1065 set_z(res(dsize - 1 downto 0));