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
117 --------- signals for address calucuration ----------
118 signal al_buf_we_n : std_logic;
119 signal ah_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 al_reg : std_logic_vector (dsize - 1 downto 0);
124 signal ah_reg : std_logic_vector (dsize - 1 downto 0);
127 signal a_sel : std_logic_vector (1 downto 0);
128 signal addr1 : std_logic_vector (dsize - 1 downto 0);
129 signal addr2 : std_logic_vector (dsize - 1 downto 0);
130 signal addr_out : std_logic_vector (dsize - 1 downto 0);
132 signal addr_c_in : std_logic;
133 signal addr_c : 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;
156 signal m2m_stat_1 : std_logic;
157 signal m2m_stat_2 : std_logic;
161 ----------------------------------------
162 -- address calucurator instances ----
163 ----------------------------------------
164 al_dff : d_flip_flop generic map (dsize)
165 port map(clk, '1', '1', al_buf_we_n, al_reg_in, al_reg);
166 ah_dff : d_flip_flop generic map (dsize)
167 port map(clk, '1', '1', ah_buf_we_n, ah_reg_in, ah_reg);
169 --pcl carry flag set.
170 pcl_carry_reg_in <= addr_c when pcl_inc_n = '0' else
173 pch_carry_dff_bit : d_flip_flop_bit
174 port map(clk, '1', '1',
175 '0', pcl_carry_reg_in, pcl_inc_carry);
177 addr_calc_inst : address_calculator generic map (dsize)
178 port map (a_sel, addr1, addr2, addr_out, addr_c_in, addr_c);
181 ----------------------------------------
182 -- arithmatic operation instances ----
183 ----------------------------------------
184 arith_dff : d_flip_flop generic map (dsize)
185 port map(clk, '1', '1', arith_buf_we_n, arith_reg_in, arith_reg);
186 arith_buf : tri_state_buffer generic map (dsize)
187 port map (arith_buf_oe_n, arith_reg, arith_reg_out);
189 alu_inst : alu_core generic map (dsize)
190 port map (sel, d1, d2, alu_out, carry_in, n, z, c, v);
191 alu_buf : tri_state_buffer generic map (dsize)
192 port map (d_oe_n, alu_out, d_out);
194 -------------------------------
195 ------ alu main process -------
196 -------------------------------
199 ---for address calucuration
200 pcl_inc_n, pch_inc_n, sp_oe_n, sp_push_n, sp_pop_n,
201 abs_xy_n, pg_next_n, zp_n, zp_xy_n, rel_calc_n,
202 indir_n, indir_x_n, indir_y_n,
203 index_bus, bal, bah, addr_c_in, addr_out, addr_c,
205 --for arithmatic operation.
207 instruction, exec_cycle, int_d_bus, acc_out,
208 carry_in, n, z, c, v,
209 arith_reg, arith_reg_out, alu_out, d_out
212 constant ADDR_ADC : std_logic_vector (1 downto 0) := "00";
213 constant ADDR_INC : std_logic_vector (1 downto 0) := "01";
214 constant ADDR_DEC : std_logic_vector (1 downto 0) := "10";
215 constant ADDR_SIGNED_ADD : std_logic_vector (1 downto 0) := "11";
217 constant ALU_AND : std_logic_vector (3 downto 0) := "0000";
218 constant ALU_EOR : std_logic_vector (3 downto 0) := "0001";
219 constant ALU_OR : std_logic_vector (3 downto 0) := "0010";
220 constant ALU_BIT : std_logic_vector (3 downto 0) := "0011";
221 constant ALU_ADC : std_logic_vector (3 downto 0) := "0100";
222 constant ALU_SBC : std_logic_vector (3 downto 0) := "0101";
223 constant ALU_CMP : std_logic_vector (3 downto 0) := "0110";
224 constant ALU_ASL : std_logic_vector (3 downto 0) := "0111";
225 constant ALU_LSR : std_logic_vector (3 downto 0) := "1000";
226 constant ALU_ROL : std_logic_vector (3 downto 0) := "1001";
227 constant ALU_ROR : std_logic_vector (3 downto 0) := "1010";
228 constant ALU_INC : std_logic_vector (3 downto 0) := "1011";
229 constant ALU_DEC : std_logic_vector (3 downto 0) := "1100";
231 ---for indirect addressing.
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;
393 --keep the value in the cycle
395 al_reg_in <= addr_out;
403 elsif (indir_n = '0') then
410 --TODO: must handle page crossing case...
413 elsif (indir_x_n = '0') then
415 elsif (indir_y_n = '0') then
418 if (exec_cycle = T2) then
425 al_reg_in <= int_d_bus;
427 elsif (exec_cycle = T3) then
439 ah_reg_in <= int_d_bus;
441 elsif (exec_cycle = T4) then
458 al_reg_in <= addr_out;
461 elsif (exec_cycle = T5) then
463 if (pg_next_n = '0') then
473 end if; -- if (exec_cycle = T2) then
474 end if; --if (clk = '0') then
482 ----addr_back is always bal for jmp/jsr instruction....
483 -----TODO must check later if it's ok.
485 end if; --if (pcl_inc_n = '0') then
487 -------------------------------
488 ---- arithmatic operations-----
489 -------------------------------
490 if (arith_en_n = '0') then
492 if instruction = conv_std_logic_vector(16#ca#, dsize) then
499 elsif instruction = conv_std_logic_vector(16#88#, dsize) then
506 elsif instruction = conv_std_logic_vector(16#e8#, dsize) then
513 elsif instruction = conv_std_logic_vector(16#c8#, dsize) then
520 elsif instruction = conv_std_logic_vector(16#0a#, dsize) then
528 elsif instruction = conv_std_logic_vector(16#2a#, dsize) then
536 elsif instruction = conv_std_logic_vector(16#4a#, dsize) then
544 elsif instruction = conv_std_logic_vector(16#6a#, dsize) then
552 --instruction is aaabbbcc format.
553 elsif instruction (1 downto 0) = "01" then
554 if instruction (7 downto 5) = "000" then
563 elsif instruction (7 downto 5) = "001" then
572 elsif instruction (7 downto 5) = "010" then
581 elsif instruction (7 downto 5) = "011" then
593 elsif instruction (7 downto 5) = "110" then
602 elsif instruction (7 downto 5) = "111" then
614 end if; --if instruction (7 downto 5) = "000" then
616 elsif instruction (1 downto 0) = "10" then
618 --this group is all memory to memory instruction (except for stx/ldx).
619 --memory to memory operation takes two cycles.
620 --first is write original data
621 --second is write modified data
623 arith_reg_in <= int_d_bus;
629 if (m2m_stat_1 = '0') then
630 --first cycle. keep input variable.
631 --d_print("inc first.");
633 arith_buf_we_n <= '0';
634 arith_buf_oe_n <= '1';
640 -- if (clk'event and clk = '0') then
641 -- if (m2m_stat_2 = '0') then
642 -- --second cycle read from register, output modified data.
643 -- --d_print("inc second...");
644 -- m2m_stat_2 <= '1';
645 -- arith_buf_we_n <= '1';
646 -- arith_buf_oe_n <= '0';
652 if instruction (7 downto 5) = "000" then
658 elsif instruction (7 downto 5) = "001" then
664 elsif instruction (7 downto 5) = "010" then
670 elsif instruction (7 downto 5) = "011" then
676 elsif instruction (7 downto 5) = "110" then
681 elsif instruction (7 downto 5) = "111" then
682 --d_print("alu inc");
686 end if; --if instruction (7 downto 5) = "000" then
688 elsif instruction (1 downto 0) = "00" then
689 if instruction (7 downto 5) = "001" then
696 elsif instruction (7 downto 5) = "110" then
704 elsif instruction (7 downto 5) = "111" then
712 end if; --if instruction (7 downto 5) = "001" then
713 end if; --if instruction = conv_std_logic_vector(16#ca#, dsize)
715 --d_print("no arith");
719 arith_buf_we_n <= '1';
720 arith_buf_oe_n <= '1';
721 int_d_bus <= (others => 'Z');
722 end if; -- if (arith_en_n = '0') then
728 -----------------------------------------
729 ---------- Address calculator------------
730 -----------------------------------------
733 use ieee.std_logic_1164.all;
734 use ieee.std_logic_unsigned.all;
736 entity address_calculator is
737 generic ( dsize : integer := 8
740 sel : in std_logic_vector (1 downto 0);
741 addr1 : in std_logic_vector (dsize - 1 downto 0);
742 addr2 : in std_logic_vector (dsize - 1 downto 0);
743 addr_out : out std_logic_vector (dsize - 1 downto 0);
744 carry_in : in std_logic;
745 carry_out : out std_logic
747 end address_calculator;
749 architecture rtl of address_calculator is
751 constant ADDR_ADC : std_logic_vector (1 downto 0) := "00";
752 constant ADDR_INC : std_logic_vector (1 downto 0) := "01";
753 constant ADDR_DEC : std_logic_vector (1 downto 0) := "10";
754 constant ADDR_SIGNED_ADD : std_logic_vector (1 downto 0) := "11";
758 alu_p : process (sel, addr1, addr2, carry_in)
759 variable res : std_logic_vector (dsize downto 0);
762 if sel = ADDR_ADC then
763 res := ('0' & addr1) + ('0' & addr2) + carry_in;
764 addr_out <= res(dsize - 1 downto 0);
765 carry_out <= res(dsize);
767 elsif sel = ADDR_SIGNED_ADD then
768 res := ('0' & addr1) + ('0' & addr2);
769 addr_out <= res(dsize - 1 downto 0);
770 -- if (addr2(dsize - 1) = '0') then
771 -- ---positive value add.
772 -- if (res(dsize) = '1') then
778 -- ---negative value add.
779 -- if (res(dsize) = '0') then
785 -->>>simplified above.
786 if ((addr2(dsize - 1) xor res(dsize)) = '1') then
792 elsif sel = ADDR_INC then
793 res := ('0' & addr1) + "000000001";
794 addr_out <= res(dsize - 1 downto 0);
795 carry_out <= res(dsize);
796 elsif sel = ADDR_DEC then
797 res := ('0' & addr1) - "000000001";
798 addr_out <= res(dsize - 1 downto 0);
799 carry_out <= res(dsize);
806 -----------------------------------------
807 ------------- ALU Core -----------------
808 -----------------------------------------
811 use ieee.std_logic_1164.all;
812 use ieee.std_logic_unsigned.all;
817 generic ( dsize : integer := 8
820 sel : in std_logic_vector (3 downto 0);
821 d1 : in std_logic_vector (dsize - 1 downto 0);
822 d2 : in std_logic_vector (dsize - 1 downto 0);
823 d_out : out std_logic_vector (dsize - 1 downto 0);
824 carry_in : in std_logic;
825 negative : out std_logic;
826 zero : out std_logic;
827 carry_out : out std_logic;
828 overflow : out std_logic
832 architecture rtl of alu_core is
834 constant ALU_AND : std_logic_vector (3 downto 0) := "0000";
835 constant ALU_EOR : std_logic_vector (3 downto 0) := "0001";
836 constant ALU_OR : std_logic_vector (3 downto 0) := "0010";
837 constant ALU_BIT : std_logic_vector (3 downto 0) := "0011";
838 constant ALU_ADC : std_logic_vector (3 downto 0) := "0100";
839 constant ALU_SBC : std_logic_vector (3 downto 0) := "0101";
840 constant ALU_CMP : std_logic_vector (3 downto 0) := "0110";
841 constant ALU_ASL : std_logic_vector (3 downto 0) := "0111";
842 constant ALU_LSR : std_logic_vector (3 downto 0) := "1000";
843 constant ALU_ROL : std_logic_vector (3 downto 0) := "1001";
844 constant ALU_ROR : std_logic_vector (3 downto 0) := "1010";
845 constant ALU_INC : std_logic_vector (3 downto 0) := "1011";
846 constant ALU_DEC : std_logic_vector (3 downto 0) := "1100";
850 alu_p : process (sel, d1, d2, carry_in)
851 variable res : std_logic_vector (dsize downto 0);
853 procedure set_n (data : in std_logic_vector (dsize - 1 downto 0)) is
855 if (data(7) = '1') then
862 procedure set_z (data : in std_logic_vector (dsize - 1 downto 0)) is
864 if (data = "00000000") then
872 if sel = ALU_AND then
873 res(dsize - 1 downto 0) := d1 and d2;
874 set_n(res(dsize - 1 downto 0));
875 set_z(res(dsize - 1 downto 0));
876 d_out <= res(dsize - 1 downto 0);
878 elsif sel = ALU_EOR then
879 res(dsize - 1 downto 0) := d1 xor d2;
880 set_n(res(dsize - 1 downto 0));
881 set_z(res(dsize - 1 downto 0));
882 d_out <= res(dsize - 1 downto 0);
884 elsif sel = ALU_OR then
885 res(dsize - 1 downto 0) := d1 or d2;
886 set_n(res(dsize - 1 downto 0));
887 set_z(res(dsize - 1 downto 0));
888 d_out <= res(dsize - 1 downto 0);
890 elsif sel = ALU_BIT then
891 --transfer bit 7 and 6 of memory data to n, v flag.
894 ----zero bit after A and M.
895 res(dsize - 1 downto 0) := d1 and d2;
896 set_z(res(dsize - 1 downto 0));
898 elsif sel = ALU_ADC then
899 res := ('0' & d1) + ('0' & d2) + carry_in;
900 d_out <= res(dsize - 1 downto 0);
901 carry_out <= res(dsize);
902 if ((d1(dsize - 1) = d2(dsize - 1))
903 and (d1(dsize - 1) /= res(dsize - 1))) then
908 set_n(res(dsize - 1 downto 0));
909 set_z(res(dsize - 1 downto 0));
911 elsif sel = ALU_SBC then
913 res := ('0' & d1) - ('0' & d2) - not carry_in;
914 d_out <= res(dsize - 1 downto 0);
916 --c Set if unsigned borrow not required; cleared if unsigned borrow.
917 carry_out <= not res(dsize);
918 --v Set if signed borrow required; cleared if no signed borrow.
919 if ((d1(dsize - 1) /= d2(dsize - 1))
920 and (d1(dsize - 1) /= res(dsize - 1))) then
925 set_n(res(dsize - 1 downto 0));
926 set_z(res(dsize - 1 downto 0));
928 elsif sel = ALU_CMP then
929 res := ('0' & d1) - ('0' & d2);
935 set_n(res(dsize - 1 downto 0));
936 set_z(res(dsize - 1 downto 0));
938 elsif sel = ALU_ASL then
939 res(dsize - 1 downto 1) := d1(dsize - 2 downto 0);
942 d_out <= res(dsize - 1 downto 0);
943 set_n(res(dsize - 1 downto 0));
944 set_z(res(dsize - 1 downto 0));
945 carry_out <= d1(dsize - 1);
947 elsif sel = ALU_LSR then
948 res(dsize - 1) := '0';
949 res(dsize - 2 downto 0) := d1(dsize - 1 downto 1);
951 d_out <= res(dsize - 1 downto 0);
952 set_n(res(dsize - 1 downto 0));
953 set_z(res(dsize - 1 downto 0));
956 elsif sel = ALU_ROL then
957 res(dsize - 1 downto 1) := d1(dsize - 2 downto 0);
960 d_out <= res(dsize - 1 downto 0);
961 set_n(res(dsize - 1 downto 0));
962 set_z(res(dsize - 1 downto 0));
965 elsif sel = ALU_ROR then
966 res(dsize - 1) := carry_in;
967 res(dsize - 2 downto 0) := d1(dsize - 1 downto 1);
969 d_out <= res(dsize - 1 downto 0);
970 set_n(res(dsize - 1 downto 0));
971 set_z(res(dsize - 1 downto 0));
974 elsif sel = ALU_INC then
975 res := ('0' & d1) + "000000001";
976 d_out <= res(dsize - 1 downto 0);
977 set_n(res(dsize - 1 downto 0));
978 set_z(res(dsize - 1 downto 0));
980 elsif sel = ALU_DEC then
981 res := ('0' & d1) - "000000001";
982 d_out <= res(dsize - 1 downto 0);
983 set_n(res(dsize - 1 downto 0));
984 set_z(res(dsize - 1 downto 0));