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;
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);
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);
131 signal addr_c_in : std_logic;
132 signal addr_c : std_logic;
133 signal addr_c_reg : std_logic;
135 signal pcl_carry_reg_in : std_logic;
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);
144 signal n : std_logic;
145 signal z : std_logic;
146 signal c : std_logic;
147 signal v : std_logic;
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;
157 ----------------------------------------
158 -- address calucurator instances ----
159 ----------------------------------------
160 al_dff : d_flip_flop generic map (dsize)
161 port map(clk, '1', '1', al_buf_we_n, al_reg_in, al_reg);
162 ah_dff : d_flip_flop generic map (dsize)
163 port map(clk, '1', '1', ah_buf_we_n, ah_reg_in, ah_reg);
165 --pcl carry flag set.
166 pcl_carry_reg_in <= addr_c when pcl_inc_n = '0' else
169 pch_carry_dff_bit : d_flip_flop_bit
170 port map(clk, '1', '1',
171 '0', pcl_carry_reg_in, pcl_inc_carry);
173 addr_calc_inst : address_calculator generic map (dsize)
174 port map (a_sel, addr1, addr2, addr_out, addr_c_in, addr_c);
176 ea_carry_dff_bit : d_flip_flop_bit
177 port map(clk, '1', '1',
178 '0', addr_c, addr_c_reg);
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);
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);
193 -------------------------------
194 ------ alu main process -------
195 -------------------------------
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, bah, addr_c_in, addr_out, addr_c,
204 --for arithmatic operation.
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
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";
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";
230 ---for indirect addressing.
231 constant T0 : std_logic_vector (5 downto 0) := "000000";
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";
238 procedure output_d_bus is
240 arith_buf_we_n <= '0';
241 arith_buf_oe_n <= '0';
243 arith_reg_in <= d_out;
247 int_d_bus <= arith_reg_out;
259 -------------------------------
260 ----- address calcuration -----
261 -------------------------------
262 if (pcl_inc_n = '0') then
265 addr_back <= addr_out;
267 --keep the value in the cycle
270 if (instruction = "01001100") then
271 ---exceptional case: only jmp instruction
282 elsif (pch_inc_n = '0') then
285 addr_back <= addr_out;
287 --inc pch cycle is not fetch cycle.
288 --it is special cycle.
292 elsif (sp_oe_n = '0') then
296 if (sp_push_n /= '0' and sp_pop_n /= '0') then
298 elsif (sp_pop_n = '0') then
302 addr_back <= addr_out;
315 addr_back <= addr_out;
325 elsif (zp_n = '0') then
326 if (zp_xy_n <= '0') then
339 elsif (abs_xy_n = '0') then
340 if (pg_next_n = '0') then
347 ---al is in the al_reg.
356 ---keep al for page crossed case
358 al_reg_in <= addr_out;
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
369 ---forward relative branch
374 ---rel val is on the d_bus.
375 addr_back <= addr_out;
378 --keep the value in the cycle
380 ah_reg_in <= addr_out;
385 a_sel <= ADDR_SIGNED_ADD;
388 ---rel val is on the d_bus.
390 addr_back <= addr_out;
392 ea_carry <= addr_c_reg;
394 --keep the value in the cycle
396 al_reg_in <= addr_out;
400 elsif (indir_n = '0') then
407 --TODO: must handle page crossing case...
410 elsif (indir_x_n = '0') then
412 elsif (indir_y_n = '0') then
415 if (exec_cycle = T2) then
422 al_reg_in <= int_d_bus;
424 elsif (exec_cycle = T3) then
436 ah_reg_in <= int_d_bus;
438 elsif (exec_cycle = T4) then
455 al_reg_in <= addr_out;
458 elsif (exec_cycle = T0 and pg_next_n = '0') then
465 end if; -- if (exec_cycle = T2) then
466 end if; --if (clk = '0') then
474 ----addr_back is always bal for jmp/jsr instruction....
475 -----TODO must check later if it's ok.
477 end if; --if (pcl_inc_n = '0') then
479 -------------------------------
480 ---- arithmatic operations-----
481 -------------------------------
482 if (arith_en_n = '0') then
484 if instruction = conv_std_logic_vector(16#ca#, dsize) then
491 elsif instruction = conv_std_logic_vector(16#88#, dsize) then
498 elsif instruction = conv_std_logic_vector(16#e8#, dsize) then
505 elsif instruction = conv_std_logic_vector(16#c8#, dsize) then
512 elsif instruction = conv_std_logic_vector(16#0a#, dsize) then
520 elsif instruction = conv_std_logic_vector(16#2a#, dsize) then
528 elsif instruction = conv_std_logic_vector(16#4a#, dsize) then
536 elsif instruction = conv_std_logic_vector(16#6a#, dsize) then
544 --instruction is aaabbbcc format.
554 elsif instruction (1 downto 0) = "01" then
555 if instruction (7 downto 5) = "000" then
564 elsif instruction (7 downto 5) = "001" then
573 elsif instruction (7 downto 5) = "010" then
582 elsif instruction (7 downto 5) = "011" then
594 elsif instruction (7 downto 5) = "110" then
603 elsif instruction (7 downto 5) = "111" then
615 end if; --if instruction (7 downto 5) = "000" then
617 elsif instruction (1 downto 0) = "10" then
619 --this group is all memory to memory instruction (except for stx/ldx).
620 --memory to memory operation takes two cycles.
621 --first is write original data
622 --second is write modified data
628 if ((exec_cycle = T3 and instruction (4 downto 2) = "001") or
629 (exec_cycle = T4 and instruction (4 downto 2) = "011") or
630 (exec_cycle = T4 and instruction (4 downto 2) = "101") or
631 (exec_cycle = T5 and instruction (4 downto 2) = "111")) then
632 --first cycle. keep input variable.
633 --d_print("inc first.");
634 arith_buf_we_n <= '0';
635 arith_buf_oe_n <= '1';
638 arith_reg_in <= int_d_bus;
641 --second cycle read from register, output modified data.
642 --d_print("inc second...");
643 arith_buf_we_n <= '1';
644 arith_buf_oe_n <= '0';
650 if instruction (7 downto 5) = "000" then
656 elsif instruction (7 downto 5) = "001" then
662 elsif instruction (7 downto 5) = "010" then
668 elsif instruction (7 downto 5) = "011" then
674 elsif instruction (7 downto 5) = "110" then
679 elsif instruction (7 downto 5) = "111" then
680 --d_print("alu inc");
684 end if; --if instruction (7 downto 5) = "000" then
686 elsif instruction (1 downto 0) = "00" then
687 if instruction (7 downto 5) = "001" then
694 elsif instruction (7 downto 5) = "110" then
702 elsif instruction (7 downto 5) = "111" then
710 end if; --if instruction (7 downto 5) = "001" then
711 end if; --if instruction = conv_std_logic_vector(16#ca#, dsize)
713 --d_print("no arith");
715 arith_buf_we_n <= '1';
716 arith_buf_oe_n <= '1';
717 int_d_bus <= (others => 'Z');
718 end if; -- if (arith_en_n = '0') then
724 -----------------------------------------
725 ---------- Address calculator------------
726 -----------------------------------------
729 use ieee.std_logic_1164.all;
730 use ieee.std_logic_unsigned.all;
732 entity address_calculator is
733 generic ( dsize : integer := 8
736 sel : in std_logic_vector (1 downto 0);
737 addr1 : in std_logic_vector (dsize - 1 downto 0);
738 addr2 : in std_logic_vector (dsize - 1 downto 0);
739 addr_out : out std_logic_vector (dsize - 1 downto 0);
740 carry_in : in std_logic;
741 carry_out : out std_logic
743 end address_calculator;
745 architecture rtl of address_calculator is
747 constant ADDR_ADC : std_logic_vector (1 downto 0) := "00";
748 constant ADDR_INC : std_logic_vector (1 downto 0) := "01";
749 constant ADDR_DEC : std_logic_vector (1 downto 0) := "10";
750 constant ADDR_SIGNED_ADD : std_logic_vector (1 downto 0) := "11";
754 alu_p : process (sel, addr1, addr2, carry_in)
755 variable res : std_logic_vector (dsize downto 0);
758 if sel = ADDR_ADC then
759 res := ('0' & addr1) + ('0' & addr2) + carry_in;
760 addr_out <= res(dsize - 1 downto 0);
761 carry_out <= res(dsize);
763 elsif sel = ADDR_SIGNED_ADD then
764 res := ('0' & addr1) + ('0' & addr2);
765 addr_out <= res(dsize - 1 downto 0);
766 -- if (addr2(dsize - 1) = '0') then
767 -- ---positive value add.
768 -- if (res(dsize) = '1') then
774 -- ---negative value add.
775 -- if (res(dsize) = '0') then
781 -->>>simplified above.
782 if ((addr2(dsize - 1) xor res(dsize)) = '1') then
788 elsif sel = ADDR_INC then
789 res := ('0' & addr1) + "000000001";
790 addr_out <= res(dsize - 1 downto 0);
791 carry_out <= res(dsize);
792 elsif sel = ADDR_DEC then
793 res := ('0' & addr1) - "000000001";
794 addr_out <= res(dsize - 1 downto 0);
795 carry_out <= res(dsize);
802 -----------------------------------------
803 ------------- ALU Core -----------------
804 -----------------------------------------
807 use ieee.std_logic_1164.all;
808 use ieee.std_logic_unsigned.all;
813 generic ( dsize : integer := 8
816 sel : in std_logic_vector (3 downto 0);
817 d1 : in std_logic_vector (dsize - 1 downto 0);
818 d2 : in std_logic_vector (dsize - 1 downto 0);
819 d_out : out std_logic_vector (dsize - 1 downto 0);
820 carry_in : in std_logic;
821 negative : out std_logic;
822 zero : out std_logic;
823 carry_out : out std_logic;
824 overflow : out std_logic
828 architecture rtl of alu_core is
830 constant ALU_AND : std_logic_vector (3 downto 0) := "0000";
831 constant ALU_EOR : std_logic_vector (3 downto 0) := "0001";
832 constant ALU_OR : std_logic_vector (3 downto 0) := "0010";
833 constant ALU_BIT : std_logic_vector (3 downto 0) := "0011";
834 constant ALU_ADC : std_logic_vector (3 downto 0) := "0100";
835 constant ALU_SBC : std_logic_vector (3 downto 0) := "0101";
836 constant ALU_CMP : std_logic_vector (3 downto 0) := "0110";
837 constant ALU_ASL : std_logic_vector (3 downto 0) := "0111";
838 constant ALU_LSR : std_logic_vector (3 downto 0) := "1000";
839 constant ALU_ROL : std_logic_vector (3 downto 0) := "1001";
840 constant ALU_ROR : std_logic_vector (3 downto 0) := "1010";
841 constant ALU_INC : std_logic_vector (3 downto 0) := "1011";
842 constant ALU_DEC : std_logic_vector (3 downto 0) := "1100";
846 alu_p : process (sel, d1, d2, carry_in)
847 variable res : std_logic_vector (dsize downto 0);
849 procedure set_n (data : in std_logic_vector (dsize - 1 downto 0)) is
851 if (data(7) = '1') then
858 procedure set_z (data : in std_logic_vector (dsize - 1 downto 0)) is
860 if (data = "00000000") then
868 if sel = ALU_AND then
869 res(dsize - 1 downto 0) := d1 and d2;
870 set_n(res(dsize - 1 downto 0));
871 set_z(res(dsize - 1 downto 0));
872 d_out <= res(dsize - 1 downto 0);
874 elsif sel = ALU_EOR then
875 res(dsize - 1 downto 0) := d1 xor d2;
876 set_n(res(dsize - 1 downto 0));
877 set_z(res(dsize - 1 downto 0));
878 d_out <= res(dsize - 1 downto 0);
880 elsif sel = ALU_OR then
881 res(dsize - 1 downto 0) := d1 or d2;
882 set_n(res(dsize - 1 downto 0));
883 set_z(res(dsize - 1 downto 0));
884 d_out <= res(dsize - 1 downto 0);
886 elsif sel = ALU_BIT then
887 --transfer bit 7 and 6 of memory data to n, v flag.
890 ----zero bit after A and M.
891 res(dsize - 1 downto 0) := d1 and d2;
892 set_z(res(dsize - 1 downto 0));
894 elsif sel = ALU_ADC then
895 res := ('0' & d1) + ('0' & d2) + carry_in;
896 d_out <= res(dsize - 1 downto 0);
897 carry_out <= res(dsize);
898 if ((d1(dsize - 1) = d2(dsize - 1))
899 and (d1(dsize - 1) /= res(dsize - 1))) then
904 set_n(res(dsize - 1 downto 0));
905 set_z(res(dsize - 1 downto 0));
907 elsif sel = ALU_SBC then
909 res := ('0' & d1) - ('0' & d2) - not carry_in;
910 d_out <= res(dsize - 1 downto 0);
912 --c Set if unsigned borrow not required; cleared if unsigned borrow.
913 carry_out <= not res(dsize);
914 --v Set if signed borrow required; cleared if no signed borrow.
915 if ((d1(dsize - 1) /= d2(dsize - 1))
916 and (d1(dsize - 1) /= res(dsize - 1))) then
921 set_n(res(dsize - 1 downto 0));
922 set_z(res(dsize - 1 downto 0));
924 elsif sel = ALU_CMP then
925 res := ('0' & d1) - ('0' & d2);
931 set_n(res(dsize - 1 downto 0));
932 set_z(res(dsize - 1 downto 0));
934 elsif sel = ALU_ASL then
935 res(dsize - 1 downto 1) := d1(dsize - 2 downto 0);
938 d_out <= res(dsize - 1 downto 0);
939 set_n(res(dsize - 1 downto 0));
940 set_z(res(dsize - 1 downto 0));
941 carry_out <= d1(dsize - 1);
943 elsif sel = ALU_LSR then
944 res(dsize - 1) := '0';
945 res(dsize - 2 downto 0) := d1(dsize - 1 downto 1);
947 d_out <= res(dsize - 1 downto 0);
948 set_n(res(dsize - 1 downto 0));
949 set_z(res(dsize - 1 downto 0));
952 elsif sel = ALU_ROL then
953 res(dsize - 1 downto 1) := d1(dsize - 2 downto 0);
956 d_out <= res(dsize - 1 downto 0);
957 set_n(res(dsize - 1 downto 0));
958 set_z(res(dsize - 1 downto 0));
961 elsif sel = ALU_ROR then
962 res(dsize - 1) := carry_in;
963 res(dsize - 2 downto 0) := d1(dsize - 1 downto 1);
965 d_out <= res(dsize - 1 downto 0);
966 set_n(res(dsize - 1 downto 0));
967 set_z(res(dsize - 1 downto 0));
970 elsif sel = ALU_INC then
971 res := ('0' & d1) + "000000001";
972 d_out <= res(dsize - 1 downto 0);
973 set_n(res(dsize - 1 downto 0));
974 set_z(res(dsize - 1 downto 0));
976 elsif sel = ALU_DEC then
977 res := ('0' & d1) - "000000001";
978 d_out <= res(dsize - 1 downto 0);
979 set_n(res(dsize - 1 downto 0));
980 set_z(res(dsize - 1 downto 0));