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
14 set_clk : in std_logic;
15 trig_clk : in std_logic;
16 pcl_inc_n : in std_logic;
17 sp_oe_n : in std_logic;
18 sp_push_n : in std_logic;
19 sp_pop_n : in std_logic;
20 abs_xy_n : in std_logic;
21 pg_next_n : in std_logic;
23 zp_xy_n : in std_logic;
24 rel_calc_n : in std_logic;
25 indir_n : in std_logic;
26 indir_x_n : in std_logic;
27 indir_y_n : in std_logic;
28 ba_out_n : in std_logic;
29 arith_en_n : in std_logic;
30 instruction : in std_logic_vector (dsize - 1 downto 0);
31 exec_cycle : in std_logic_vector (5 downto 0);
32 int_d_bus : inout std_logic_vector (dsize - 1 downto 0);
33 acc_out : in std_logic_vector (dsize - 1 downto 0);
34 index_bus : in std_logic_vector (dsize - 1 downto 0);
35 bal : in std_logic_vector (dsize - 1 downto 0);
36 bah : in std_logic_vector (dsize - 1 downto 0);
37 addr_back : out std_logic_vector (dsize - 1 downto 0);
38 acc_in : out std_logic_vector (dsize - 1 downto 0);
39 abl : out std_logic_vector (dsize - 1 downto 0);
40 abh : out std_logic_vector (dsize - 1 downto 0);
41 ea_carry : out std_logic;
42 carry_in : in std_logic;
43 negative : out std_logic;
45 carry_out : out std_logic;
46 overflow : out std_logic
50 architecture rtl of alu is
61 d : in std_logic_vector (dsize - 1 downto 0);
62 q : out std_logic_vector (dsize - 1 downto 0)
66 component d_flip_flop_bit
77 component tri_state_buffer
83 d : in std_logic_vector (dsize - 1 downto 0);
84 q : out std_logic_vector (dsize - 1 downto 0)
88 component address_calculator
89 generic ( dsize : integer := 8
92 sel : in std_logic_vector (1 downto 0);
93 addr1 : in std_logic_vector (dsize - 1 downto 0);
94 addr2 : in std_logic_vector (dsize - 1 downto 0);
95 addr_out : out std_logic_vector (dsize - 1 downto 0);
96 carry_in : in std_logic;
97 carry_out : out std_logic
102 generic ( dsize : integer := 8
105 sel : in std_logic_vector (3 downto 0);
106 d1 : in std_logic_vector (dsize - 1 downto 0);
107 d2 : in std_logic_vector (dsize - 1 downto 0);
108 d_out : out std_logic_vector (dsize - 1 downto 0);
109 carry_in : in std_logic;
110 negative : out std_logic;
111 zero : out std_logic;
112 carry_out : out std_logic;
113 overflow : out std_logic
117 constant ADDR_ADC : std_logic_vector (1 downto 0) := "00";
118 constant ADDR_INC : std_logic_vector (1 downto 0) := "01";
119 constant ADDR_DEC : std_logic_vector (1 downto 0) := "10";
120 constant ADDR_SIGNED_ADD : std_logic_vector (1 downto 0) := "11";
122 constant ALU_AND : std_logic_vector (3 downto 0) := "0000";
123 constant ALU_EOR : std_logic_vector (3 downto 0) := "0001";
124 constant ALU_OR : std_logic_vector (3 downto 0) := "0010";
125 constant ALU_BIT : std_logic_vector (3 downto 0) := "0011";
126 constant ALU_ADC : std_logic_vector (3 downto 0) := "0100";
127 constant ALU_SBC : std_logic_vector (3 downto 0) := "0101";
128 constant ALU_CMP : std_logic_vector (3 downto 0) := "0110";
129 constant ALU_ASL : std_logic_vector (3 downto 0) := "0111";
130 constant ALU_LSR : std_logic_vector (3 downto 0) := "1000";
131 constant ALU_ROL : std_logic_vector (3 downto 0) := "1001";
132 constant ALU_ROR : std_logic_vector (3 downto 0) := "1010";
133 constant ALU_INC : std_logic_vector (3 downto 0) := "1011";
134 constant ALU_DEC : std_logic_vector (3 downto 0) := "1100";
136 ---for indirect addressing.
137 constant T0 : std_logic_vector (5 downto 0) := "000000";
138 constant T1 : std_logic_vector (5 downto 0) := "000001";
139 constant T2 : std_logic_vector (5 downto 0) := "000010";
140 constant T3 : std_logic_vector (5 downto 0) := "000011";
141 constant T4 : std_logic_vector (5 downto 0) := "000100";
142 constant T5 : std_logic_vector (5 downto 0) := "000101";
145 --------- signals for address calucuration ----------
146 signal al_buf_we_n : std_logic;
147 signal ah_buf_we_n : std_logic;
148 signal tmp_buf_we_n : std_logic;
150 signal al_reg_in : std_logic_vector (dsize - 1 downto 0);
151 signal ah_reg_in : std_logic_vector (dsize - 1 downto 0);
152 signal tmp_reg_in : std_logic_vector (dsize - 1 downto 0);
153 signal al_reg : std_logic_vector (dsize - 1 downto 0);
154 signal ah_reg : std_logic_vector (dsize - 1 downto 0);
155 signal tmp_reg : std_logic_vector (dsize - 1 downto 0);
157 signal a_sel : std_logic_vector (1 downto 0);
158 signal addr1 : std_logic_vector (dsize - 1 downto 0);
159 signal addr2 : std_logic_vector (dsize - 1 downto 0);
160 signal addr_out : std_logic_vector (dsize - 1 downto 0);
162 signal addr_c_in : std_logic;
163 signal addr_c : std_logic;
164 signal addr_c_reg : std_logic;
166 ----------- signals for arithmatic ----------
167 signal sel : std_logic_vector (3 downto 0);
168 signal d1 : std_logic_vector (dsize - 1 downto 0);
169 signal d2 : std_logic_vector (dsize - 1 downto 0);
170 signal d_out : std_logic_vector (dsize - 1 downto 0);
171 signal alu_out : std_logic_vector (dsize - 1 downto 0);
173 signal n : std_logic;
174 signal z : std_logic;
175 signal c : std_logic;
176 signal v : std_logic;
178 signal arith_buf_we_n : std_logic;
179 signal arith_buf_oe_n : std_logic;
180 signal arith_reg_in : std_logic_vector (dsize - 1 downto 0);
181 signal arith_reg : std_logic_vector (dsize - 1 downto 0);
182 signal arith_reg_out : std_logic_vector (dsize - 1 downto 0);
183 signal d_oe_n : std_logic;
186 ----------------------------------------
187 -- address calucurator instances ----
188 ----------------------------------------
189 al_dff : d_flip_flop generic map (dsize)
190 port map(trig_clk, '1', '1', al_buf_we_n, al_reg_in, al_reg);
191 ah_dff : d_flip_flop generic map (dsize)
192 port map(trig_clk, '1', '1', ah_buf_we_n, ah_reg_in, ah_reg);
193 tmp_dff : d_flip_flop generic map (dsize)
194 port map(trig_clk, '1', '1', tmp_buf_we_n, tmp_reg_in, tmp_reg);
196 addr_calc_inst : address_calculator generic map (dsize)
197 port map (a_sel, addr1, addr2, addr_out, addr_c_in, addr_c);
199 ea_carry_dff_bit : d_flip_flop_bit
200 port map(trig_clk, '1', '1',
201 '0', addr_c, addr_c_reg);
203 ----------------------------------------
204 -- arithmatic operation instances ----
205 ----------------------------------------
206 arith_dff : d_flip_flop generic map (dsize)
207 port map(trig_clk, '1', '1', arith_buf_we_n, arith_reg_in, arith_reg);
208 arith_buf : tri_state_buffer generic map (dsize)
209 port map (arith_buf_oe_n, arith_reg, arith_reg_out);
211 alu_inst : alu_core generic map (dsize)
212 port map (sel, d1, d2, alu_out, carry_in, n, z, c, v);
213 alu_buf : tri_state_buffer generic map (dsize)
214 port map (d_oe_n, alu_out, d_out);
216 -------------------------------
217 ----- address calcuration -----
218 -------------------------------
219 alu_addr_p : process (
220 pcl_inc_n, sp_oe_n, sp_pop_n, sp_push_n,
221 zp_n, zp_xy_n, abs_xy_n, pg_next_n, rel_calc_n,
222 int_d_bus(7), indir_n, indir_x_n, exec_cycle,
227 if (pcl_inc_n = '0') then
231 addr_back <= addr_out;
236 elsif (sp_oe_n = '0') then
241 if (sp_push_n /= '0' and sp_pop_n /= '0') then
243 elsif (sp_pop_n = '0') then
247 addr_back <= addr_out;
253 addr_back <= addr_out;
256 elsif (zp_n = '0') then
258 if (zp_xy_n <= '0') then
271 elsif (abs_xy_n = '0') then
272 if (pg_next_n = '0') then
279 ---al is in the al_reg.
288 ---keep al for page crossed case
290 al_reg_in <= addr_out;
295 elsif (rel_calc_n = '0') then
296 if (pg_next_n = '0') then
297 if (int_d_bus(7) = '1') then
298 ---backward relative branch
301 ---forward relative branch
306 ---rel val is on the d_bus.
307 addr_back <= addr_out;
310 --keep the value in the cycle
312 ah_reg_in <= addr_out;
317 a_sel <= ADDR_SIGNED_ADD;
320 ---rel val is on the d_bus.
322 addr_back <= addr_out;
324 ea_carry <= addr_c_reg;
326 --keep the value in the cycle
328 al_reg_in <= addr_out;
332 elsif (indir_n = '0') then
341 elsif (indir_x_n = '0') then
342 if (exec_cycle = T2) then
343 ---input is IAL, but this cycle doesn't do anything....
350 elsif (exec_cycle = T3) then
360 tmp_reg_in <= addr_out;
368 al_reg_in <= int_d_bus;
370 elsif (exec_cycle = T4) then
384 ah_reg_in <= int_d_bus;
385 elsif (exec_cycle = T5 or exec_cycle = T0) then
391 end if; -- if (exec_cycle = T2) then
393 elsif (indir_y_n = '0') then
395 if (exec_cycle = T2) then
402 al_reg_in <= int_d_bus;
405 --get next address (IAL + 1)
409 tmp_reg_in <= addr_out;
411 elsif (exec_cycle = T3) then
422 ah_reg_in <= int_d_bus;
425 elsif (exec_cycle = T4) then
443 al_reg_in <= addr_out;
445 tmp_reg_in <= ah_reg;
446 elsif (exec_cycle = T5 or exec_cycle = T0) then
451 if (pg_next_n = '0') then
466 end if; -- if (exec_cycle = T2) then
467 elsif (ba_out_n = '0') then
476 abl <= (others => 'Z');
477 abh <= (others => 'Z');
478 addr_back <= (others => 'Z');
479 end if; --if (pcl_inc_n = '0') then
483 -------------------------------
484 ---- arithmatic operations-----
485 -------------------------------
486 alu_arith_p : process (
488 instruction, exec_cycle, int_d_bus, acc_out,
491 --data calcuration follows the bus input...
493 procedure output_d_bus is
495 arith_buf_we_n <= '0';
496 arith_buf_oe_n <= '0';
498 arith_reg_in <= d_out;
499 if (set_clk = '0') then
502 int_d_bus <= arith_reg_out;
513 if (arith_en_n = '0') then
515 if instruction = conv_std_logic_vector(16#ca#, dsize) then
522 elsif instruction = conv_std_logic_vector(16#88#, dsize) then
529 elsif instruction = conv_std_logic_vector(16#e8#, dsize) then
536 elsif instruction = conv_std_logic_vector(16#c8#, dsize) then
543 elsif instruction = conv_std_logic_vector(16#0a#, dsize) then
551 elsif instruction = conv_std_logic_vector(16#2a#, dsize) then
559 elsif instruction = conv_std_logic_vector(16#4a#, dsize) then
567 elsif instruction = conv_std_logic_vector(16#6a#, dsize) then
575 --instruction is aaabbbcc format.
585 elsif instruction (1 downto 0) = "01" then
586 if instruction (7 downto 5) = "000" then
595 elsif instruction (7 downto 5) = "001" then
604 elsif instruction (7 downto 5) = "010" then
613 elsif instruction (7 downto 5) = "011" then
625 elsif instruction (7 downto 5) = "110" then
634 elsif instruction (7 downto 5) = "111" then
646 end if; --if instruction (7 downto 5) = "000" then
648 elsif instruction (1 downto 0) = "10" then
650 --this group is all memory to memory instruction (except for stx/ldx).
651 --memory to memory operation takes two cycles.
652 --first is write original data
653 --second is write modified data
659 if ((exec_cycle = T2 and instruction (4 downto 2) = "001") or
660 (exec_cycle = T3 and instruction (4 downto 2) = "011") or
661 (exec_cycle = T3 and instruction (4 downto 2) = "101") or
662 (exec_cycle = T4 and instruction (4 downto 2) = "111")) then
663 arith_buf_we_n <= '0';
664 arith_reg_in <= int_d_bus;
666 elsif ((exec_cycle = T3 and instruction (4 downto 2) = "001") or
667 (exec_cycle = T4 and instruction (4 downto 2) = "011") or
668 (exec_cycle = T4 and instruction (4 downto 2) = "101") or
669 (exec_cycle = T5 and instruction (4 downto 2) = "111")) then
670 --first cycle. keep input variable.
671 --d_print("inc first.");
672 arith_buf_we_n <= '1';
674 arith_buf_oe_n <= '1';
679 --second cycle read from register, output modified data.
680 --d_print("inc second...");
681 arith_buf_we_n <= '1';
682 arith_buf_oe_n <= '0';
688 if instruction (7 downto 5) = "000" then
694 elsif instruction (7 downto 5) = "001" then
700 elsif instruction (7 downto 5) = "010" then
706 elsif instruction (7 downto 5) = "011" then
712 elsif instruction (7 downto 5) = "110" then
717 elsif instruction (7 downto 5) = "111" then
718 --d_print("alu inc");
722 end if; --if instruction (7 downto 5) = "000" then
724 elsif instruction (1 downto 0) = "00" then
725 if instruction (7 downto 5) = "001" then
732 elsif instruction (7 downto 5) = "110" then
740 elsif instruction (7 downto 5) = "111" then
748 end if; --if instruction (7 downto 5) = "001" then
749 end if; --if instruction = conv_std_logic_vector(16#ca#, dsize)
751 --d_print("no arith");
753 arith_buf_we_n <= '1';
754 arith_buf_oe_n <= '1';
755 int_d_bus <= (others => 'Z');
756 end if; -- if (arith_en_n = '0') then
762 -----------------------------------------
763 ---------- Address calculator------------
764 -----------------------------------------
767 use ieee.std_logic_1164.all;
768 use ieee.std_logic_unsigned.all;
770 entity address_calculator is
771 generic ( dsize : integer := 8
774 sel : in std_logic_vector (1 downto 0);
775 addr1 : in std_logic_vector (dsize - 1 downto 0);
776 addr2 : in std_logic_vector (dsize - 1 downto 0);
777 addr_out : out std_logic_vector (dsize - 1 downto 0);
778 carry_in : in std_logic;
779 carry_out : out std_logic
781 end address_calculator;
783 architecture rtl of address_calculator is
785 constant ADDR_ADC : std_logic_vector (1 downto 0) := "00";
786 constant ADDR_INC : std_logic_vector (1 downto 0) := "01";
787 constant ADDR_DEC : std_logic_vector (1 downto 0) := "10";
788 constant ADDR_SIGNED_ADD : std_logic_vector (1 downto 0) := "11";
792 alu_p : process (sel, addr1, addr2, carry_in)
793 variable res : std_logic_vector (dsize downto 0);
796 if sel = ADDR_ADC then
797 res := ('0' & addr1) + ('0' & addr2) + carry_in;
798 addr_out <= res(dsize - 1 downto 0);
799 carry_out <= res(dsize);
801 elsif sel = ADDR_SIGNED_ADD then
802 res := ('0' & addr1) + ('0' & addr2);
803 addr_out <= res(dsize - 1 downto 0);
804 -->>>simplified above.
805 if ((addr2(dsize - 1) xor res(dsize)) = '1') then
811 elsif sel = ADDR_INC then
812 res := ('0' & addr1) + "000000001";
813 addr_out <= res(dsize - 1 downto 0);
814 carry_out <= res(dsize);
815 elsif sel = ADDR_DEC then
816 res := ('0' & addr1) - "000000001";
817 addr_out <= res(dsize - 1 downto 0);
818 carry_out <= res(dsize);
825 -----------------------------------------
826 ------------- ALU Core -----------------
827 -----------------------------------------
830 use ieee.std_logic_1164.all;
831 use ieee.std_logic_unsigned.all;
836 generic ( dsize : integer := 8
839 sel : in std_logic_vector (3 downto 0);
840 d1 : in std_logic_vector (dsize - 1 downto 0);
841 d2 : in std_logic_vector (dsize - 1 downto 0);
842 d_out : out std_logic_vector (dsize - 1 downto 0);
843 carry_in : in std_logic;
844 negative : out std_logic;
845 zero : out std_logic;
846 carry_out : out std_logic;
847 overflow : out std_logic
851 architecture rtl of alu_core is
853 constant ALU_AND : std_logic_vector (3 downto 0) := "0000";
854 constant ALU_EOR : std_logic_vector (3 downto 0) := "0001";
855 constant ALU_OR : std_logic_vector (3 downto 0) := "0010";
856 constant ALU_BIT : std_logic_vector (3 downto 0) := "0011";
857 constant ALU_ADC : std_logic_vector (3 downto 0) := "0100";
858 constant ALU_SBC : std_logic_vector (3 downto 0) := "0101";
859 constant ALU_CMP : std_logic_vector (3 downto 0) := "0110";
860 constant ALU_ASL : std_logic_vector (3 downto 0) := "0111";
861 constant ALU_LSR : std_logic_vector (3 downto 0) := "1000";
862 constant ALU_ROL : std_logic_vector (3 downto 0) := "1001";
863 constant ALU_ROR : std_logic_vector (3 downto 0) := "1010";
864 constant ALU_INC : std_logic_vector (3 downto 0) := "1011";
865 constant ALU_DEC : std_logic_vector (3 downto 0) := "1100";
869 alu_p : process (sel, d1, d2, carry_in)
870 variable res : std_logic_vector (dsize downto 0);
872 procedure set_n (data : in std_logic_vector (dsize - 1 downto 0)) is
874 if (data(7) = '1') then
881 procedure set_z (data : in std_logic_vector (dsize - 1 downto 0)) is
883 if (data = "00000000") then
891 if sel = ALU_AND then
892 res(dsize - 1 downto 0) := d1 and d2;
893 set_n(res(dsize - 1 downto 0));
894 set_z(res(dsize - 1 downto 0));
895 d_out <= res(dsize - 1 downto 0);
897 elsif sel = ALU_EOR then
898 res(dsize - 1 downto 0) := d1 xor d2;
899 set_n(res(dsize - 1 downto 0));
900 set_z(res(dsize - 1 downto 0));
901 d_out <= res(dsize - 1 downto 0);
903 elsif sel = ALU_OR then
904 res(dsize - 1 downto 0) := d1 or d2;
905 set_n(res(dsize - 1 downto 0));
906 set_z(res(dsize - 1 downto 0));
907 d_out <= res(dsize - 1 downto 0);
909 elsif sel = ALU_BIT then
910 --transfer bit 7 and 6 of memory data to n, v flag.
913 ----zero bit after A and M.
914 res(dsize - 1 downto 0) := d1 and d2;
915 set_z(res(dsize - 1 downto 0));
917 elsif sel = ALU_ADC then
918 res := ('0' & d1) + ('0' & d2) + carry_in;
919 d_out <= res(dsize - 1 downto 0);
920 carry_out <= res(dsize);
921 if ((d1(dsize - 1) = d2(dsize - 1))
922 and (d1(dsize - 1) /= res(dsize - 1))) then
927 set_n(res(dsize - 1 downto 0));
928 set_z(res(dsize - 1 downto 0));
930 elsif sel = ALU_SBC then
932 res := ('0' & d1) - ('0' & d2) - not carry_in;
933 d_out <= res(dsize - 1 downto 0);
935 --c Set if unsigned borrow not required; cleared if unsigned borrow.
936 carry_out <= not res(dsize);
937 --v Set if signed borrow required; cleared if no signed borrow.
938 if ((d1(dsize - 1) /= d2(dsize - 1))
939 and (d1(dsize - 1) /= res(dsize - 1))) then
944 set_n(res(dsize - 1 downto 0));
945 set_z(res(dsize - 1 downto 0));
947 elsif sel = ALU_CMP then
948 res := ('0' & d1) - ('0' & d2);
954 set_n(res(dsize - 1 downto 0));
955 set_z(res(dsize - 1 downto 0));
957 elsif sel = ALU_ASL then
958 res(dsize - 1 downto 1) := d1(dsize - 2 downto 0);
961 d_out <= res(dsize - 1 downto 0);
962 set_n(res(dsize - 1 downto 0));
963 set_z(res(dsize - 1 downto 0));
964 carry_out <= d1(dsize - 1);
966 elsif sel = ALU_LSR then
967 res(dsize - 1) := '0';
968 res(dsize - 2 downto 0) := d1(dsize - 1 downto 1);
970 d_out <= res(dsize - 1 downto 0);
971 set_n(res(dsize - 1 downto 0));
972 set_z(res(dsize - 1 downto 0));
975 elsif sel = ALU_ROL then
976 res(dsize - 1 downto 1) := d1(dsize - 2 downto 0);
979 d_out <= res(dsize - 1 downto 0);
980 set_n(res(dsize - 1 downto 0));
981 set_z(res(dsize - 1 downto 0));
984 elsif sel = ALU_ROR then
985 res(dsize - 1) := carry_in;
986 res(dsize - 2 downto 0) := d1(dsize - 1 downto 1);
988 d_out <= res(dsize - 1 downto 0);
989 set_n(res(dsize - 1 downto 0));
990 set_z(res(dsize - 1 downto 0));
993 elsif sel = ALU_INC then
994 res := ('0' & d1) + "000000001";
995 d_out <= res(dsize - 1 downto 0);
996 set_n(res(dsize - 1 downto 0));
997 set_z(res(dsize - 1 downto 0));
999 elsif sel = ALU_DEC then
1000 res := ('0' & d1) - "000000001";
1001 d_out <= res(dsize - 1 downto 0);
1002 set_n(res(dsize - 1 downto 0));
1003 set_z(res(dsize - 1 downto 0));