From 1575d4f53805f177474b5bb96daebede9b2dfb73 Mon Sep 17 00:00:00 2001 From: root Date: Wed, 24 Feb 2021 23:45:58 +0000 Subject: base --- de1/fpga-bbc-pq/master/cpu-core-fixes.patch | 3881 +++++++++++++++++++++++++++ 1 file changed, 3881 insertions(+) create mode 100644 de1/fpga-bbc-pq/master/cpu-core-fixes.patch (limited to 'de1/fpga-bbc-pq/master/cpu-core-fixes.patch') diff --git a/de1/fpga-bbc-pq/master/cpu-core-fixes.patch b/de1/fpga-bbc-pq/master/cpu-core-fixes.patch new file mode 100644 index 0000000..4319a09 --- /dev/null +++ b/de1/fpga-bbc-pq/master/cpu-core-fixes.patch @@ -0,0 +1,3881 @@ +diff --git a/T65/T65.vhd b/T65/T65.vhd +index 09253fe..bea8434 100644 +--- a/T65/T65.vhd ++++ b/T65/T65.vhd +@@ -1,7 +1,20 @@ + -- **** + -- T65(b) core. In an effort to merge and maintain bug fixes .... + -- ++-- Ver 303 ost(ML) July 2014 ++-- (Sorry for some scratchpad comments that may make little sense) ++-- Mods and some 6502 undocumented instructions. + -- ++-- Not correct opcodes acc. to Lorenz tests (incomplete list): ++-- NOPN (nop) ++-- NOPZX (nop + byte 172) ++-- NOPAX (nop + word da ... da: byte 0) ++-- ASOZ (byte $07 + byte 172) ++-- ++-- Wolfgang April 2014 ++-- Ver 303 Bugfixes for NMI from foft ++-- Ver 302 Bugfix for BRK command ++-- Wolfgang January 2014 + -- Ver 301 more merging + -- Ver 300 Bugfixes by ehenciak added, started tidyup *bust* + -- MikeJ March 2005 +@@ -69,345 +82,376 @@ library IEEE; + -- ehenciak 2-23-2005 : Added the enable signal so that one doesn't have to use + -- the ready signal to limit the CPU. + entity T65 is +- port( +- Mode : in std_logic_vector(1 downto 0); -- "00" => 6502, "01" => 65C02, "10" => 65C816 +- Res_n : in std_logic; +- Enable : in std_logic; +- Clk : in std_logic; +- Rdy : in std_logic; +- Abort_n : in std_logic; +- IRQ_n : in std_logic; +- NMI_n : in std_logic; +- SO_n : in std_logic; +- R_W_n : out std_logic; +- Sync : out std_logic; +- EF : out std_logic; +- MF : out std_logic; +- XF : out std_logic; +- ML_n : out std_logic; +- VP_n : out std_logic; +- VDA : out std_logic; +- VPA : out std_logic; +- A : out std_logic_vector(23 downto 0); +- DI : in std_logic_vector(7 downto 0); +- DO : out std_logic_vector(7 downto 0) +- ); ++ port( ++ Mode : in std_logic_vector(1 downto 0); -- "00" => 6502, "01" => 65C02, "10" => 65C816 ++ Res_n : in std_logic; ++ Enable : in std_logic; ++ Clk : in std_logic; ++ Rdy : in std_logic; ++ Abort_n : in std_logic; ++ IRQ_n : in std_logic; ++ NMI_n : in std_logic; ++ SO_n : in std_logic; ++ R_W_n : out std_logic; ++ Sync : out std_logic; ++ EF : out std_logic; ++ MF : out std_logic; ++ XF : out std_logic; ++ ML_n : out std_logic; ++ VP_n : out std_logic; ++ VDA : out std_logic; ++ VPA : out std_logic; ++ A : out std_logic_vector(23 downto 0); ++ DI : in std_logic_vector(7 downto 0);--NOTE:Make sure DI equals DO when writing. This is important for DCP/DCM undoc instruction. TODO:convert to inout ++ DO : out std_logic_vector(7 downto 0); ++ -- 6502 registers (MSB) PC, SP, P, Y, X, A (LSB) ++ Regs : out std_logic_vector(63 downto 0) ++ ); + end T65; + + architecture rtl of T65 is + +- -- Registers +- signal ABC, X, Y, D : std_logic_vector(15 downto 0); +- signal P, AD, DL : std_logic_vector(7 downto 0) := x"00"; +- signal BAH : std_logic_vector(7 downto 0); +- signal BAL : std_logic_vector(8 downto 0); +- signal PBR : std_logic_vector(7 downto 0); +- signal DBR : std_logic_vector(7 downto 0); +- signal PC : unsigned(15 downto 0); +- signal S : unsigned(15 downto 0); +- signal EF_i : std_logic; +- signal MF_i : std_logic; +- signal XF_i : std_logic; +- +- signal IR : std_logic_vector(7 downto 0); +- signal MCycle : std_logic_vector(2 downto 0); +- +- signal Mode_r : std_logic_vector(1 downto 0); +- signal ALU_Op_r : std_logic_vector(3 downto 0); +- signal Write_Data_r : std_logic_vector(2 downto 0); +- signal Set_Addr_To_r : std_logic_vector(1 downto 0); +- signal PCAdder : unsigned(8 downto 0); +- +- signal RstCycle : std_logic; +- signal IRQCycle : std_logic; +- signal NMICycle : std_logic; +- +- signal B_o : std_logic; +- signal SO_n_o : std_logic; +- signal IRQ_n_o : std_logic; +- signal NMI_n_o : std_logic; +- signal NMIAct : std_logic; +- +- signal Break : std_logic; +- +- -- ALU signals +- signal BusA : std_logic_vector(7 downto 0); +- signal BusA_r : std_logic_vector(7 downto 0); +- signal BusB : std_logic_vector(7 downto 0); +- signal ALU_Q : std_logic_vector(7 downto 0); +- signal P_Out : std_logic_vector(7 downto 0); +- +- -- Micro code outputs +- signal LCycle : std_logic_vector(2 downto 0); +- signal ALU_Op : std_logic_vector(3 downto 0); +- signal Set_BusA_To : std_logic_vector(2 downto 0); +- signal Set_Addr_To : std_logic_vector(1 downto 0); +- signal Write_Data : std_logic_vector(2 downto 0); +- signal Jump : std_logic_vector(1 downto 0); +- signal BAAdd : std_logic_vector(1 downto 0); +- signal BreakAtNA : std_logic; +- signal ADAdd : std_logic; +- signal AddY : std_logic; +- signal PCAdd : std_logic; +- signal Inc_S : std_logic; +- signal Dec_S : std_logic; +- signal LDA : std_logic; +- signal LDP : std_logic; +- signal LDX : std_logic; +- signal LDY : std_logic; +- signal LDS : std_logic; +- signal LDDI : std_logic; +- signal LDALU : std_logic; +- signal LDAD : std_logic; +- signal LDBAL : std_logic; +- signal LDBAH : std_logic; +- signal SaveP : std_logic; +- signal Write : std_logic; +- +- signal really_rdy : std_logic; +- signal R_W_n_i : std_logic; ++ -- Registers ++ signal ABC, X, Y, D : std_logic_vector(15 downto 0); ++ signal P, AD, DL : std_logic_vector(7 downto 0) := x"00"; ++ signal PwithB : std_logic_vector(7 downto 0);--ML:New way to push P with correct B state to stack ++ signal BAH : std_logic_vector(7 downto 0); ++ signal BAL : std_logic_vector(8 downto 0); ++ signal PBR : std_logic_vector(7 downto 0); ++ signal DBR : std_logic_vector(7 downto 0); ++ signal PC : unsigned(15 downto 0); ++ signal S : unsigned(15 downto 0); ++ signal EF_i : std_logic; ++ signal MF_i : std_logic; ++ signal XF_i : std_logic; ++ ++ signal IR : std_logic_vector(7 downto 0); ++ signal MCycle : std_logic_vector(2 downto 0); ++ ++ signal Mode_r : std_logic_vector(1 downto 0); ++ signal ALU_Op_r : T_ALU_Op; ++ signal Write_Data_r : T_Write_Data; ++ signal Set_Addr_To_r : T_Set_Addr_To; ++ signal PCAdder : unsigned(8 downto 0); ++ ++ signal RstCycle : std_logic; ++ signal IRQCycle : std_logic; ++ signal NMICycle : std_logic; ++ ++ signal SO_n_o : std_logic; ++ signal IRQ_n_o : std_logic; ++ signal NMI_n_o : std_logic; ++ signal NMIAct : std_logic; ++ ++ signal Break : std_logic; ++ ++ -- ALU signals ++ signal BusA : std_logic_vector(7 downto 0); ++ signal BusA_r : std_logic_vector(7 downto 0); ++ signal BusB : std_logic_vector(7 downto 0); ++ signal ALU_Q : std_logic_vector(7 downto 0); ++ signal P_Out : std_logic_vector(7 downto 0); ++ ++ -- Micro code outputs ++ signal LCycle : std_logic_vector(2 downto 0); ++ signal ALU_Op : T_ALU_Op; ++ signal Set_BusA_To : T_Set_BusA_To; ++ signal Set_Addr_To : T_Set_Addr_To; ++ signal Write_Data : T_Write_Data; ++ signal Jump : std_logic_vector(1 downto 0); ++ signal BAAdd : std_logic_vector(1 downto 0); ++ signal BreakAtNA : std_logic; ++ signal ADAdd : std_logic; ++ signal AddY : std_logic; ++ signal PCAdd : std_logic; ++ signal Inc_S : std_logic; ++ signal Dec_S : std_logic; ++ signal LDA : std_logic; ++ signal LDP : std_logic; ++ signal LDX : std_logic; ++ signal LDY : std_logic; ++ signal LDS : std_logic; ++ signal LDDI : std_logic; ++ signal LDALU : std_logic; ++ signal LDAD : std_logic; ++ signal LDBAL : std_logic; ++ signal LDBAH : std_logic; ++ signal SaveP : std_logic; ++ signal Write : std_logic; ++ signal ALUmore : std_logic; ++ ++ signal really_rdy : std_logic; ++ signal R_W_n_i : std_logic; ++ signal R_W_n_i_d : std_logic; ++ ++ signal NMIActClear : std_logic; -- MWW hack + + begin +- -- ehenciak : gate Rdy with read/write to make an "OK, it's +- -- really OK to stop the processor now if Rdy is +- -- deasserted" signal +- really_rdy <= Rdy or not(R_W_n_i); +- +- -- ehenciak : Drive R_W_n_i off chip. +- R_W_n <= R_W_n_i; +- +- Sync <= '1' when MCycle = "000" else '0'; +- EF <= EF_i; +- MF <= MF_i; +- XF <= XF_i; +- ML_n <= '0' when IR(7 downto 6) /= "10" and IR(2 downto 1) = "11" and MCycle(2 downto 1) /= "00" else '1'; +- VP_n <= '0' when IRQCycle = '1' and (MCycle = "101" or MCycle = "110") else '1'; +- VDA <= '1' when Set_Addr_To_r /= "00" else '0'; -- Incorrect !!!!!!!!!!!! +- VPA <= '1' when Jump(1) = '0' else '0'; -- Incorrect !!!!!!!!!!!! +- +- mcode : T65_MCode +- port map( +- Mode => Mode_r, +- IR => IR, +- MCycle => MCycle, +- P => P, +- LCycle => LCycle, +- ALU_Op => ALU_Op, +- Set_BusA_To => Set_BusA_To, +- Set_Addr_To => Set_Addr_To, +- Write_Data => Write_Data, +- Jump => Jump, +- BAAdd => BAAdd, +- BreakAtNA => BreakAtNA, +- ADAdd => ADAdd, +- AddY => AddY, +- PCAdd => PCAdd, +- Inc_S => Inc_S, +- Dec_S => Dec_S, +- LDA => LDA, +- LDP => LDP, +- LDX => LDX, +- LDY => LDY, +- LDS => LDS, +- LDDI => LDDI, +- LDALU => LDALU, +- LDAD => LDAD, +- LDBAL => LDBAL, +- LDBAH => LDBAH, +- SaveP => SaveP, +- Write => Write +- ); +- +- alu : T65_ALU +- port map( +- Mode => Mode_r, +- Op => ALU_Op_r, +- BusA => BusA_r, +- BusB => BusB, +- P_In => P, +- P_Out => P_Out, +- Q => ALU_Q +- ); +- +- process (Res_n, Clk) +- begin +- if Res_n = '0' then +- PC <= (others => '0'); -- Program Counter +- IR <= "00000000"; +- S <= (others => '0'); -- Dummy !!!!!!!!!!!!!!!!!!!!! +- D <= (others => '0'); +- PBR <= (others => '0'); +- DBR <= (others => '0'); +- +- Mode_r <= (others => '0'); +- ALU_Op_r <= "1100"; +- Write_Data_r <= "000"; +- Set_Addr_To_r <= "00"; +- +- R_W_n_i <= '1'; +- EF_i <= '1'; +- MF_i <= '1'; +- XF_i <= '1'; +- +- elsif Clk'event and Clk = '1' then +- if (Enable = '1') then +- if (really_rdy = '1') then +- R_W_n_i <= not Write or RstCycle; +- +- D <= (others => '1'); -- Dummy +- PBR <= (others => '1'); -- Dummy +- DBR <= (others => '1'); -- Dummy +- EF_i <= '0'; -- Dummy +- MF_i <= '0'; -- Dummy +- XF_i <= '0'; -- Dummy +- +- if MCycle = "000" then +- Mode_r <= Mode; +- +- if IRQCycle = '0' and NMICycle = '0' then +- PC <= PC + 1; +- end if; +- +- if IRQCycle = '1' or NMICycle = '1' then +- IR <= "00000000"; +- else +- IR <= DI; +- end if; +- end if; +- +- ALU_Op_r <= ALU_Op; +- Write_Data_r <= Write_Data; +- if Break = '1' then +- Set_Addr_To_r <= "00"; +- else +- Set_Addr_To_r <= Set_Addr_To; +- end if; +- +- if Inc_S = '1' then +- S <= S + 1; +- end if; +- if Dec_S = '1' and RstCycle = '0' then +- S <= S - 1; +- end if; +- if LDS = '1' then +- S(7 downto 0) <= unsigned(ALU_Q); +- end if; +- +- if IR = "00000000" and MCycle = "001" and IRQCycle = '0' and NMICycle = '0' then +- PC <= PC + 1; +- end if; +- -- +- -- jump control logic +- -- +- case Jump is +- when "01" => +- PC <= PC + 1; +- +- when "10" => +- PC <= unsigned(DI & DL); +- +- when "11" => +- if PCAdder(8) = '1' then +- if DL(7) = '0' then +- PC(15 downto 8) <= PC(15 downto 8) + 1; +- else +- PC(15 downto 8) <= PC(15 downto 8) - 1; +- end if; +- end if; +- PC(7 downto 0) <= PCAdder(7 downto 0); +- +- when others => null; +- end case; +- end if; +- end if; +- end if; +- end process; +- +- PCAdder <= resize(PC(7 downto 0),9) + resize(unsigned(DL(7) & DL),9) when PCAdd = '1' +- else "0" & PC(7 downto 0); +- +- process (Clk) +- begin +- if Clk'event and Clk = '1' then +- if (Enable = '1') then +- if (really_rdy = '1') then +- if MCycle = "000" then +- if LDA = '1' then +- ABC(7 downto 0) <= ALU_Q; +- end if; +- if LDX = '1' then +- X(7 downto 0) <= ALU_Q; +- end if; +- if LDY = '1' then +- Y(7 downto 0) <= ALU_Q; +- end if; +- if (LDA or LDX or LDY) = '1' then +- P <= P_Out; +- end if; +- end if; +- if SaveP = '1' then +- P <= P_Out; +- end if; +- if LDP = '1' then +- P <= ALU_Q; +- end if; +- if IR(4 downto 0) = "11000" then +- case IR(7 downto 5) is +- when "000" => +- P(Flag_C) <= '0'; +- when "001" => +- P(Flag_C) <= '1'; +- when "010" => +- P(Flag_I) <= '0'; +- when "011" => +- P(Flag_I) <= '1'; +- when "101" => +- P(Flag_V) <= '0'; +- when "110" => +- P(Flag_D) <= '0'; +- when "111" => +- P(Flag_D) <= '1'; +- when others => +- end case; +- end if; +- +- --if IR = "00000000" and MCycle = "011" and RstCycle = '0' and NMICycle = '0' and IRQCycle = '0' then +- -- P(Flag_B) <= '1'; +- --end if; +- --if IR = "00000000" and MCycle = "100" and RstCycle = '0' and (NMICycle = '1' or IRQCycle = '1') then +- -- P(Flag_I) <= '1'; +- -- P(Flag_B) <= B_o; +- --end if; +- +- -- B=1 always on the 6502 +- P(Flag_B) <= '1'; +- if IR = "00000000" and RstCycle = '0' and (NMICycle = '1' or IRQCycle = '1') then +- if MCycle = "011" then +- -- B=0 in *copy* of P pushed onto the stack +- P(Flag_B) <= '0'; +- elsif MCycle = "100" then +- P(Flag_I) <= '1'; ++ -- workaround for ready-handling ++ -- ehenciak : Drive R_W_n_i off chip. ++ R_W_n <= R_W_n_i; ++ ++ -- ehenciak : gate Rdy with read/write to make an "OK, it's ++ -- really OK to stop the processor now if Rdy is ++ -- deasserted" signal ++ really_rdy <= Rdy or not(R_W_n_i); ++ ---- ++ ++ Sync <= '1' when MCycle = "000" else '0'; ++ EF <= EF_i; ++ MF <= MF_i; ++ XF <= XF_i; ++ ML_n <= '0' when IR(7 downto 6) /= "10" and IR(2 downto 1) = "11" and MCycle(2 downto 1) /= "00" else '1'; ++ VP_n <= '0' when IRQCycle = '1' and (MCycle = "101" or MCycle = "110") else '1'; ++ VDA <= '1' when Set_Addr_To_r /= Set_Addr_To_PBR else '0'; -- Incorrect !!!!!!!!!!!! ++ VPA <= '1' when Jump(1) = '0' else '0'; -- Incorrect !!!!!!!!!!!! ++ ++ Regs <= std_logic_vector(PC) & std_logic_vector(S)& P & Y(7 downto 0) & X(7 downto 0) & ABC(7 downto 0); ++ ++ mcode : T65_MCode ++ port map( ++--inputs ++ Mode => Mode_r, ++ IR => IR, ++ MCycle => MCycle, ++ P => P, ++--outputs ++ LCycle => LCycle, ++ ALU_Op => ALU_Op, ++ Set_BusA_To => Set_BusA_To, ++ Set_Addr_To => Set_Addr_To, ++ Write_Data => Write_Data, ++ Jump => Jump, ++ BAAdd => BAAdd, ++ BreakAtNA => BreakAtNA, ++ ADAdd => ADAdd, ++ AddY => AddY, ++ PCAdd => PCAdd, ++ Inc_S => Inc_S, ++ Dec_S => Dec_S, ++ LDA => LDA, ++ LDP => LDP, ++ LDX => LDX, ++ LDY => LDY, ++ LDS => LDS, ++ LDDI => LDDI, ++ LDALU => LDALU, ++ LDAD => LDAD, ++ LDBAL => LDBAL, ++ LDBAH => LDBAH, ++ SaveP => SaveP, ++ ALUmore => ALUmore, ++ Write => Write ++ ); ++ ++ alu : T65_ALU ++ port map( ++ Mode => Mode_r, ++ Op => ALU_Op_r, ++ BusA => BusA_r, ++ BusB => BusB, ++ P_In => P, ++ P_Out => P_Out, ++ Q => ALU_Q ++ ); ++ ++ ++ process (Res_n, Clk) ++ begin ++ if Res_n = '0' then ++ PC <= (others => '0'); -- Program Counter ++ IR <= "00000000"; ++ S <= (others => '0'); -- Dummy !!!!!!!!!!!!!!!!!!!!! ++ D <= (others => '0'); ++ PBR <= (others => '0'); ++ DBR <= (others => '0'); ++ ++ Mode_r <= (others => '0'); ++ ALU_Op_r <= ALU_OP_BIT; ++ Write_Data_r <= Write_Data_DL; ++ Set_Addr_To_r <= Set_Addr_To_PBR; ++ ++ R_W_n_i <= '1'; ++ EF_i <= '1'; ++ MF_i <= '1'; ++ XF_i <= '1'; ++ ++ elsif Clk'event and Clk = '1' then ++ if (Enable = '1') then ++ if (really_rdy = '1') then ++ R_W_n_i <= not Write or RstCycle; ++ ++ D <= (others => '1'); -- Dummy ++ PBR <= (others => '1'); -- Dummy ++ DBR <= (others => '1'); -- Dummy ++ EF_i <= '0'; -- Dummy ++ MF_i <= '0'; -- Dummy ++ XF_i <= '0'; -- Dummy ++ ++ if MCycle = "000" then ++ Mode_r <= Mode; ++ ++ if IRQCycle = '0' and NMICycle = '0' then ++ PC <= PC + 1; ++ end if; ++ ++ if IRQCycle = '1' or NMICycle = '1' then ++ IR <= "00000000"; ++ else ++ IR <= DI; ++ end if; ++ end if; ++ ++ ALU_Op_r <= ALU_Op; ++ Write_Data_r <= Write_Data; ++ if Break = '1' then ++ Set_Addr_To_r <= Set_Addr_To_PBR; ++ else ++ Set_Addr_To_r <= Set_Addr_To; ++ end if; ++ ++ if Inc_S = '1' then ++ S <= S + 1; ++ end if; ++ if Dec_S = '1' and RstCycle = '0' then ++ S <= S - 1; ++ end if; ++ if LDS = '1' then ++ S(7 downto 0) <= unsigned(ALU_Q); ++ end if; ++ ++ if IR = "00000000" and MCycle = "001" and IRQCycle = '0' and NMICycle = '0' then ++ PC <= PC + 1; + end if; +- end if; +- +- if SO_n_o = '1' and SO_n = '0' then +- P(Flag_V) <= '1'; +- end if; +- if RstCycle = '1' and Mode_r /= "00" then +- P(Flag_1) <= '1'; +- P(Flag_D) <= '0'; +- P(Flag_I) <= '1'; +- end if; +- P(Flag_1) <= '1'; +- +- B_o <= P(Flag_B); +- SO_n_o <= SO_n; +- IRQ_n_o <= IRQ_n; +- NMI_n_o <= NMI_n; +- end if; +- end if; +- end if; +- end process; ++ -- ++ -- jump control logic ++ -- ++ case Jump is ++ when "01" => ++ PC <= PC + 1; ++ ++ when "10" => ++ PC <= unsigned(DI & DL); ++ ++ when "11" => ++ if PCAdder(8) = '1' then ++ if DL(7) = '0' then ++ PC(15 downto 8) <= PC(15 downto 8) + 1; ++ else ++ PC(15 downto 8) <= PC(15 downto 8) - 1; ++ end if; ++ end if; ++ PC(7 downto 0) <= PCAdder(7 downto 0); ++ ++ when others => null; ++ end case; ++ end if; ++ end if; ++ end if; ++ end process; ++ ++ PCAdder <= resize(PC(7 downto 0),9) + resize(unsigned(DL(7) & DL),9) when PCAdd = '1' ++ else "0" & PC(7 downto 0); ++ ++ process (Res_n, Clk) ++ variable tmpP:std_logic_vector(7 downto 0);--ML:Lets try to handle loading P at mcycle=0 and set/clk flags at same cycle ++ begin ++ if Res_n = '0' then ++ P <= x"00"; -- ensure we have nothing set on reset (e.g. B flag!) ++ elsif Clk'event and Clk = '1' then ++ tmpP:=P; ++ if (Enable = '1') then ++ if (really_rdy = '1') then ++ if MCycle = "000" then ++ if LDA = '1' then ++ ABC(7 downto 0) <= ALU_Q; ++ end if; ++ if LDX = '1' then ++ X(7 downto 0) <= ALU_Q; ++ end if; ++ if LDY = '1' then ++ Y(7 downto 0) <= ALU_Q; ++ end if; ++ if (LDA or LDX or LDY) = '1' then ++-- P <= P_Out;-- Replaced with: ++ tmpP:=P_Out; ++ end if; ++ end if; ++ if SaveP = '1' then ++-- P <= P_Out;-- Replaced with: ++ tmpP:=P_Out; ++ end if; ++ if LDP = '1' then ++-- P <= ALU_Q;-- Replaced with: --ML:no need anymore: AND x"EF"; -- NEVER set B on RTI and PLP ++ tmpP:=ALU_Q; ++ end if; ++ if IR(4 downto 0) = "11000" then ++ case IR(7 downto 5) is ++ when "000" =>--0x18(clc) ++-- P(Flag_C) <= '0';-- Replaced with: ++ tmpP(Flag_C) := '0'; ++ when "001" =>--0x38(sec) ++-- P(Flag_C) <= '1'; ++ tmpP(Flag_C) := '1'; ++ when "010" =>--0x58(cli) ++-- P(Flag_I) <= '0'; ++ tmpP(Flag_I) := '0'; ++ when "011" =>--0x78(sei) ++-- P(Flag_I) <= '1'; ++ tmpP(Flag_I) := '1'; ++ when "101" =>--0xb8(clv) ++-- P(Flag_V) <= '0'; ++ tmpP(Flag_V) := '0'; ++ when "110" =>--0xd8(cld) ++-- P(Flag_D) <= '0'; ++ tmpP(Flag_D) := '0'; ++ when "111" =>--0xf8(sed) ++-- P(Flag_D) <= '1'; ++ tmpP(Flag_D) := '1'; ++ when others => ++ end case; ++ end if; ++ --ML:Removed change of B flag, its constant '1' in P ++ --ML:The B flag appears to be locked to '1', but when pushed to stack, the SR data on the stack has the B flag cleared on interrupts, set on BRK instr. ++ --ML:The state of the B flag on warm reset apparently is unchanged (not confirmed, please do if you know) ++ --ML:The state of the B flag on cold reset is uncertain, but my guess would be set, unless it can be used to detect cold from warm reset. ++ --Since we cant (well, won't) simulate B=0 on cold reset, we just behave as if it was constant 1. ++-- P(Flag_B) <= '1'; ++ tmpP(Flag_B) := '1'; ++-- if IR = "00000000" and MCycle = "011" and RstCycle = '0' and NMICycle = '0' and IRQCycle = '0' then -- BRK ++-- P(Flag_B) <= '1'; ++-- elsif IR = "00001000" then -- PHP ++-- P(Flag_B) <= '1'; ++-- else ++-- P(Flag_B) <= '0'; --> not the best way, but we keep B zero except for BRK and PHP opcodes ++-- end if; ++ if IR = "00000000" and MCycle = "100" and RstCycle = '0' then --and (NMICycle = '1' or IRQCycle = '1') then ++ --This should happen after P has been pushed to stack ++-- P(Flag_I) <= '1'; ++ tmpP(Flag_I) := '1'; ++ end if; ++ if SO_n_o = '1' and SO_n = '0' then ++-- P(Flag_V) <= '1'; ++ tmpP(Flag_V) := '1'; ++ end if; ++ if RstCycle = '1' then ++-- P(Flag_I) <= '0'; ++-- P(Flag_D) <= '0'; ++ tmpP(Flag_I) := '1'; ++ tmpP(Flag_D) := '0'; ++ end if; ++-- P(Flag_1) <= '1'; ++ tmpP(Flag_1) := '1'; ++ ++ P<=tmpP;--new way ++ ++ SO_n_o <= SO_n; ++ IRQ_n_o <= IRQ_n; ++ end if; ++ NMI_n_o <= NMI_n; -- MWW: detect nmi even if not rdy ++ end if; ++ end if; ++ end process; + + --------------------------------------------------------------------------- + -- +@@ -415,109 +459,125 @@ begin + -- + --------------------------------------------------------------------------- + +- process (Res_n, Clk) +- begin +- if Res_n = '0' then +- BusA_r <= (others => '0'); +- BusB <= (others => '0'); +- AD <= (others => '0'); +- BAL <= (others => '0'); +- BAH <= (others => '0'); +- DL <= (others => '0'); +- elsif Clk'event and Clk = '1' then +- if (Enable = '1') then +- if (Rdy = '1') then +- BusA_r <= BusA; +- BusB <= DI; +- +- case BAAdd is +- when "01" => +- -- BA Inc +- AD <= std_logic_vector(unsigned(AD) + 1); +- BAL <= std_logic_vector(unsigned(BAL) + 1); +- when "10" => +- -- BA Add +- BAL <= std_logic_vector(resize(unsigned(BAL(7 downto 0)),9) + resize(unsigned(BusA),9)); +- when "11" => +- -- BA Adj +- if BAL(8) = '1' then +- BAH <= std_logic_vector(unsigned(BAH) + 1); +- end if; +- when others => +- end case; +- +- -- ehenciak : modified to use Y register as well (bugfix) +- if ADAdd = '1' then +- if (AddY = '1') then +- AD <= std_logic_vector(unsigned(AD) + unsigned(Y(7 downto 0))); +- else +- AD <= std_logic_vector(unsigned(AD) + unsigned(X(7 downto 0))); +- end if; +- end if; +- +- if IR = "00000000" then +- BAL <= (others => '1'); +- BAH <= (others => '1'); +- if RstCycle = '1' then +- BAL(2 downto 0) <= "100"; +- elsif NMICycle = '1' then +- BAL(2 downto 0) <= "010"; +- else +- BAL(2 downto 0) <= "110"; +- end if; +- if Set_addr_To_r = "11" then +- BAL(0) <= '1'; +- end if; +- end if; +- +- +- if LDDI = '1' then +- DL <= DI; +- end if; +- if LDALU = '1' then +- DL <= ALU_Q; +- end if; +- if LDAD = '1' then +- AD <= DI; +- end if; +- if LDBAL = '1' then +- BAL(7 downto 0) <= DI; +- end if; +- if LDBAH = '1' then +- BAH <= DI; +- end if; +- end if; +- end if; +- end if; +- end process; +- +- Break <= (BreakAtNA and not BAL(8)) or (PCAdd and not PCAdder(8)); +- +- +- with Set_BusA_To select +- BusA <= DI when "000", +- ABC(7 downto 0) when "001", +- X(7 downto 0) when "010", +- Y(7 downto 0) when "011", +- std_logic_vector(S(7 downto 0)) when "100", +- P when "101", +- (others => '-') when others; +- +- with Set_Addr_To_r select +- A <= "0000000000000001" & std_logic_vector(S(7 downto 0)) when "01", +- DBR & "00000000" & AD when "10", +- "00000000" & BAH & BAL(7 downto 0) when "11", +- PBR & std_logic_vector(PC(15 downto 8)) & std_logic_vector(PCAdder(7 downto 0)) when others; +- +- with Write_Data_r select +- DO <= DL when "000", +- ABC(7 downto 0) when "001", +- X(7 downto 0) when "010", +- Y(7 downto 0) when "011", +- std_logic_vector(S(7 downto 0)) when "100", +- P when "101", +- std_logic_vector(PC(7 downto 0)) when "110", +- std_logic_vector(PC(15 downto 8)) when others; ++ process (Res_n, Clk) ++ begin ++ if Res_n = '0' then ++ BusA_r <= (others => '0'); ++ BusB <= (others => '0'); ++ AD <= (others => '0'); ++ BAL <= (others => '0'); ++ BAH <= (others => '0'); ++ DL <= (others => '0'); ++ elsif Clk'event and Clk = '1' then ++ if (Enable = '1') then ++ if (really_rdy = '1') then ++ --if (Rdy = '1') then ++ BusA_r <= BusA; ++ if ALUmore='1' then ++ BusB <= ALU_Q; ++ else ++ BusB <= DI; ++ end if; ++ ++ case BAAdd is ++ when "01" => ++ -- BA Inc ++ AD <= std_logic_vector(unsigned(AD) + 1); ++ BAL <= std_logic_vector(unsigned(BAL) + 1); ++ when "10" => ++ -- BA Add ++ BAL <= std_logic_vector(resize(unsigned(BAL(7 downto 0)),9) + resize(unsigned(BusA),9)); ++ when "11" => ++ -- BA Adj ++ if BAL(8) = '1' then ++ BAH <= std_logic_vector(unsigned(BAH) + 1); ++ end if; ++ when others => ++ end case; ++ ++ -- ehenciak : modified to use Y register as well (bugfix) ++ if ADAdd = '1' then ++ if (AddY = '1') then ++ AD <= std_logic_vector(unsigned(AD) + unsigned(Y(7 downto 0))); ++ else ++ AD <= std_logic_vector(unsigned(AD) + unsigned(X(7 downto 0))); ++ end if; ++ end if; ++ ++ NMIActClear <= '0'; ++ if IR = "00000000" then ++ BAL <= (others => '1'); ++ BAH <= (others => '1'); ++ if RstCycle = '1' then ++ BAL(2 downto 0) <= "100"; ++ elsif NMICycle = '1' then ++ BAL(2 downto 0) <= "010"; ++ elsif NMIAct = '1' then -- MWW, force this to be changed by NMI, even if in midstream IRQ/brk ++ BAL(2 downto 0) <= "010"; ++ NMIActClear <= '1'; ++ else ++ BAL(2 downto 0) <= "110"; ++ end if; ++ if Set_addr_To_r = Set_Addr_To_BA then ++ BAL(0) <= '1'; ++ end if; ++ end if; ++ ++ ++ if LDDI = '1' then ++ DL <= DI; ++ end if; ++ if LDALU = '1' then ++ DL <= ALU_Q; ++ end if; ++ if LDAD = '1' then ++ AD <= DI; ++ end if; ++ if LDBAL = '1' then ++ BAL(7 downto 0) <= DI; ++ end if; ++ if LDBAH = '1' then ++ BAH <= DI; ++ end if; ++ end if; ++ end if; ++ end if; ++ end process; ++ ++ Break <= (BreakAtNA and not BAL(8)) or (PCAdd and not PCAdder(8)); ++ ++ with Set_BusA_To select ++ BusA <= ++ DI when Set_BusA_To_DI, ++ ABC(7 downto 0) when Set_BusA_To_ABC, ++ X(7 downto 0) when Set_BusA_To_X, ++ Y(7 downto 0) when Set_BusA_To_Y, ++ std_logic_vector(S(7 downto 0)) when Set_BusA_To_S, ++ P when Set_BusA_To_P, ++ (others => '-') when Set_BusA_To_DONTCARE;--Can probably remove this ++ ++ with Set_Addr_To_r select ++ A <= ++ "0000000000000001" & std_logic_vector(S(7 downto 0)) when Set_Addr_To_S, ++ DBR & "00000000" & AD when Set_Addr_To_AD, ++ "00000000" & BAH & BAL(7 downto 0) when Set_Addr_To_BA, ++ PBR & std_logic_vector(PC(15 downto 8)) & std_logic_vector(PCAdder(7 downto 0)) when Set_Addr_To_PBR; ++ ++ --ML:This is the P that gets pushed on stack with correct B flag. I'm not sure if NMI also clears B, but I guess it does. ++ PwithB<=(P and x"ef") when (IRQCycle='1' or NMICycle='1') else P; ++ ++ with Write_Data_r select ++ DO <= ++ DL when Write_Data_DL, ++ ABC(7 downto 0) when Write_Data_ABC, ++ X(7 downto 0) when Write_Data_X, ++ Y(7 downto 0) when Write_Data_Y, ++ std_logic_vector(S(7 downto 0)) when Write_Data_S, ++ PwithB when Write_Data_P, ++ std_logic_vector(PC(7 downto 0)) when Write_Data_PCL, ++ std_logic_vector(PC(15 downto 8)) when Write_Data_PCH, ++ (others=>'-') when Write_Data_DONTCARE;--Can probably remove this ++ + + ------------------------------------------------------------------------- + -- +@@ -525,40 +585,44 @@ begin + -- + ------------------------------------------------------------------------- + +- process (Res_n, Clk) +- begin +- if Res_n = '0' then +- MCycle <= "001"; +- RstCycle <= '1'; +- IRQCycle <= '0'; +- NMICycle <= '0'; +- NMIAct <= '0'; +- elsif Clk'event and Clk = '1' then +- if (Enable = '1') then +- if (really_rdy = '1') then +- if MCycle = LCycle or Break = '1' then +- MCycle <= "000"; +- RstCycle <= '0'; +- IRQCycle <= '0'; +- NMICycle <= '0'; +- if NMIAct = '1' then +- NMICycle <= '1'; +- elsif IRQ_n_o = '0' and P(Flag_I) = '0' then +- IRQCycle <= '1'; +- end if; +- else +- MCycle <= std_logic_vector(unsigned(MCycle) + 1); +- end if; +- +- if NMICycle = '1' then +- NMIAct <= '0'; +- end if; +- if NMI_n_o = '1' and NMI_n = '0' then +- NMIAct <= '1'; +- end if; +- end if; +- end if; +- end if; +- end process; ++ process (Res_n, Clk) ++ begin ++ if Res_n = '0' then ++ MCycle <= "001"; ++ RstCycle <= '1'; ++ IRQCycle <= '0'; ++ NMICycle <= '0'; ++ NMIAct <= '0'; ++ elsif Clk'event and Clk = '1' then ++ if (Enable = '1') then ++ if (really_rdy = '1') then ++ if (NMIActClear = '1') then ++ NMIAct <= '0'; ++ end if; ++ ++ if MCycle = LCycle or Break = '1' then ++ MCycle <= "000"; ++ RstCycle <= '0'; ++ IRQCycle <= '0'; ++ NMICycle <= '0'; ++ if NMIAct = '1' then ++ NMICycle <= '1'; ++ elsif IRQ_n_o = '0' and P(Flag_I) = '0' then ++ IRQCycle <= '1'; ++ end if; ++ else ++ MCycle <= std_logic_vector(unsigned(MCycle) + 1); ++ end if; ++ ++ if NMICycle = '1' then ++ NMIAct <= '0'; ++ end if; ++ end if; ++ if NMI_n_o = '1' and NMI_n = '0' then -- MWW: detect nmi even if not rdy ++ NMIAct <= '1'; ++ end if; ++ end if; ++ end if; ++ end process; + + end; +diff --git a/T65/T65_ALU.vhd b/T65/T65_ALU.vhd +index b1f6d63..49ae4a1 100644 +--- a/T65/T65_ALU.vhd ++++ b/T65/T65_ALU.vhd +@@ -2,6 +2,8 @@ + -- T65(b) core. In an effort to merge and maintain bug fixes .... + -- + -- ++-- Ver 303 ost(ML) July 2014 ++-- ALU opcodes to vhdl types + -- Ver 300 Bugfixes by ehenciak added + -- MikeJ March 2005 + -- Latest version from www.fpgaarcade.com (original www.opencores.org) +@@ -62,199 +64,201 @@ use IEEE.numeric_std.all; + use work.T65_Pack.all; + + entity T65_ALU is +- port( +- Mode : in std_logic_vector(1 downto 0); -- "00" => 6502, "01" => 65C02, "10" => 65816 +- Op : in std_logic_vector(3 downto 0); +- BusA : in std_logic_vector(7 downto 0); +- BusB : in std_logic_vector(7 downto 0); +- P_In : in std_logic_vector(7 downto 0); +- P_Out : out std_logic_vector(7 downto 0); +- Q : out std_logic_vector(7 downto 0) +- ); ++ port( ++ Mode : in std_logic_vector(1 downto 0); -- "00" => 6502, "01" => 65C02, "10" => 65816 ++ Op : in T_ALU_OP; ++ BusA : in std_logic_vector(7 downto 0); ++ BusB : in std_logic_vector(7 downto 0); ++ P_In : in std_logic_vector(7 downto 0); ++ P_Out : out std_logic_vector(7 downto 0); ++ Q : out std_logic_vector(7 downto 0) ++ ); + end T65_ALU; + + architecture rtl of T65_ALU is + +- -- AddSub variables (temporary signals) +- signal ADC_Z : std_logic; +- signal ADC_C : std_logic; +- signal ADC_V : std_logic; +- signal ADC_N : std_logic; +- signal ADC_Q : std_logic_vector(7 downto 0); +- signal SBC_Z : std_logic; +- signal SBC_C : std_logic; +- signal SBC_V : std_logic; +- signal SBC_N : std_logic; +- signal SBC_Q : std_logic_vector(7 downto 0); ++ -- AddSub variables (temporary signals) ++ signal ADC_Z : std_logic; ++ signal ADC_C : std_logic; ++ signal ADC_V : std_logic; ++ signal ADC_N : std_logic; ++ signal ADC_Q : std_logic_vector(7 downto 0); ++ signal SBC_Z : std_logic; ++ signal SBC_C : std_logic; ++ signal SBC_V : std_logic; ++ signal SBC_N : std_logic; ++ signal SBC_Q : std_logic_vector(7 downto 0); + + begin + +- process (P_In, BusA, BusB) +- variable AL : unsigned(6 downto 0); +- variable AH : unsigned(6 downto 0); +- variable C : std_logic; +- begin +- AL := resize(unsigned(BusA(3 downto 0) & P_In(Flag_C)), 7) + resize(unsigned(BusB(3 downto 0) & "1"), 7); +- AH := resize(unsigned(BusA(7 downto 4) & AL(5)), 7) + resize(unsigned(BusB(7 downto 4) & "1"), 7); ++ process (P_In, BusA, BusB) ++ variable AL : unsigned(6 downto 0); ++ variable AH : unsigned(6 downto 0); ++ variable C : std_logic; ++ begin ++ AL := resize(unsigned(BusA(3 downto 0) & P_In(Flag_C)), 7) + resize(unsigned(BusB(3 downto 0) & "1"), 7); ++ AH := resize(unsigned(BusA(7 downto 4) & AL(5)), 7) + resize(unsigned(BusB(7 downto 4) & "1"), 7); + + -- pragma translate_off +- if is_x(std_logic_vector(AL)) then AL := "0000000"; end if; +- if is_x(std_logic_vector(AH)) then AH := "0000000"; end if; ++ if is_x(std_logic_vector(AL)) then AL := "0000000"; end if; ++ if is_x(std_logic_vector(AH)) then AH := "0000000"; end if; + -- pragma translate_on + +- if AL(4 downto 1) = 0 and AH(4 downto 1) = 0 then +- ADC_Z <= '1'; +- else +- ADC_Z <= '0'; +- end if; ++ if AL(4 downto 1) = 0 and AH(4 downto 1) = 0 then ++ ADC_Z <= '1'; ++ else ++ ADC_Z <= '0'; ++ end if; + +- if AL(5 downto 1) > 9 and P_In(Flag_D) = '1' then +- AL(6 downto 1) := AL(6 downto 1) + 6; +- end if; ++ if AL(5 downto 1) > 9 and P_In(Flag_D) = '1' then ++ AL(6 downto 1) := AL(6 downto 1) + 6; ++ end if; + +- C := AL(6) or AL(5); +- AH := resize(unsigned(BusA(7 downto 4) & C), 7) + resize(unsigned(BusB(7 downto 4) & "1"), 7); ++ C := AL(6) or AL(5); ++ AH := resize(unsigned(BusA(7 downto 4) & C), 7) + resize(unsigned(BusB(7 downto 4) & "1"), 7); + +- ADC_N <= AH(4); +- ADC_V <= (AH(4) xor BusA(7)) and not (BusA(7) xor BusB(7)); ++ ADC_N <= AH(4); ++ ADC_V <= (AH(4) xor BusA(7)) and not (BusA(7) xor BusB(7)); + + -- pragma translate_off +- if is_x(std_logic_vector(AH)) then AH := "0000000"; end if; ++ if is_x(std_logic_vector(AH)) then AH := "0000000"; end if; + -- pragma translate_on + +- if AH(5 downto 1) > 9 and P_In(Flag_D) = '1' then +- AH(6 downto 1) := AH(6 downto 1) + 6; +- end if; ++ if AH(5 downto 1) > 9 and P_In(Flag_D) = '1' then ++ AH(6 downto 1) := AH(6 downto 1) + 6; ++ end if; + +- ADC_C <= AH(6) or AH(5); ++ ADC_C <= AH(6) or AH(5); + +- ADC_Q <= std_logic_vector(AH(4 downto 1) & AL(4 downto 1)); +- end process; ++ ADC_Q <= std_logic_vector(AH(4 downto 1) & AL(4 downto 1)); ++ end process; + +- process (Op, P_In, BusA, BusB) +- variable AL : unsigned(6 downto 0); +- variable AH : unsigned(5 downto 0); +- variable C : std_logic; +- begin +- C := P_In(Flag_C) or not Op(0); +- AL := resize(unsigned(BusA(3 downto 0) & C), 7) - resize(unsigned(BusB(3 downto 0) & "1"), 6); +- AH := resize(unsigned(BusA(7 downto 4) & "0"), 6) - resize(unsigned(BusB(7 downto 4) & AL(5)), 6); ++ process (Op, P_In, BusA, BusB) ++ variable AL : unsigned(6 downto 0); ++ variable AH : unsigned(5 downto 0); ++ variable C : std_logic; ++ variable CT : std_logic; ++ begin ++ CT:='0'; ++ if( Op=ALU_OP_AND or --"0001" These OpCodes used to have LSB set ++ Op=ALU_OP_ADC or --"0011" ++ Op=ALU_OP_EQ2 or --"0101" ++ Op=ALU_OP_SBC or --"0111" ++ Op=ALU_OP_ROL or --"1001" ++ Op=ALU_OP_ROR or --"1011" ++ Op=ALU_OP_EQ3 or --"1101" ++ Op=ALU_OP_INC --"1111" ++ ) then ++ CT:='1'; ++ end if; ++ ++ C := P_In(Flag_C) or not CT;--was: or not Op(0); ++ AL := resize(unsigned(BusA(3 downto 0) & C), 7) - resize(unsigned(BusB(3 downto 0) & "1"), 6); ++ AH := resize(unsigned(BusA(7 downto 4) & "0"), 6) - resize(unsigned(BusB(7 downto 4) & AL(5)), 6); + + -- pragma translate_off +- if is_x(std_logic_vector(AL)) then AL := "0000000"; end if; +- if is_x(std_logic_vector(AH)) then AH := "000000"; end if; ++ if is_x(std_logic_vector(AL)) then AL := "0000000"; end if; ++ if is_x(std_logic_vector(AH)) then AH := "000000"; end if; + -- pragma translate_on + +- if AL(4 downto 1) = 0 and AH(4 downto 1) = 0 then +- SBC_Z <= '1'; +- else +- SBC_Z <= '0'; +- end if; ++ if AL(4 downto 1) = 0 and AH(4 downto 1) = 0 then ++ SBC_Z <= '1'; ++ else ++ SBC_Z <= '0'; ++ end if; + +- SBC_C <= not AH(5); +- SBC_V <= (AH(4) xor BusA(7)) and (BusA(7) xor BusB(7)); +- SBC_N <= AH(4); ++ SBC_C <= not AH(5); ++ SBC_V <= (AH(4) xor BusA(7)) and (BusA(7) xor BusB(7)); ++ SBC_N <= AH(4); + +- if P_In(Flag_D) = '1' then +- if AL(5) = '1' then +- AL(5 downto 1) := AL(5 downto 1) - 6; +- end if; +- AH := resize(unsigned(BusA(7 downto 4) & "0"), 6) - resize(unsigned(BusB(7 downto 4) & AL(6)), 6); +- if AH(5) = '1' then +- AH(5 downto 1) := AH(5 downto 1) - 6; +- end if; +- end if; ++ if P_In(Flag_D) = '1' then ++ if AL(5) = '1' then ++ AL(5 downto 1) := AL(5 downto 1) - 6; ++ end if; ++ AH := resize(unsigned(BusA(7 downto 4) & "0"), 6) - resize(unsigned(BusB(7 downto 4) & AL(6)), 6); ++ if AH(5) = '1' then ++ AH(5 downto 1) := AH(5 downto 1) - 6; ++ end if; ++ end if; + +- SBC_Q <= std_logic_vector(AH(4 downto 1) & AL(4 downto 1)); +- end process; ++ SBC_Q <= std_logic_vector(AH(4 downto 1) & AL(4 downto 1)); ++ end process; + +- process (Op, P_In, BusA, BusB, +- ADC_Z, ADC_C, ADC_V, ADC_N, ADC_Q, +- SBC_Z, SBC_C, SBC_V, SBC_N, SBC_Q) +- variable Q_t : std_logic_vector(7 downto 0); +- begin +- -- ORA, AND, EOR, ADC, NOP, LD, CMP, SBC +- -- ASL, ROL, LSR, ROR, BIT, LD, DEC, INC +- P_Out <= P_In; +- Q_t := BusA; +- case Op(3 downto 0) is +- when "0000" => +- -- ORA +- Q_t := BusA or BusB; +- when "0001" => +- -- AND +- Q_t := BusA and BusB; +- when "0010" => +- -- EOR +- Q_t := BusA xor BusB; +- when "0011" => +- -- ADC +- P_Out(Flag_V) <= ADC_V; +- P_Out(Flag_C) <= ADC_C; +- Q_t := ADC_Q; +- when "0101" | "1101" => +- -- LDA +- when "0110" => +- -- CMP +- P_Out(Flag_C) <= SBC_C; +- when "0111" => +- -- SBC +- P_Out(Flag_V) <= SBC_V; +- P_Out(Flag_C) <= SBC_C; +- Q_t := SBC_Q; +- when "1000" => +- -- ASL +- Q_t := BusA(6 downto 0) & "0"; +- P_Out(Flag_C) <= BusA(7); +- when "1001" => +- -- ROL +- Q_t := BusA(6 downto 0) & P_In(Flag_C); +- P_Out(Flag_C) <= BusA(7); +- when "1010" => +- -- LSR +- Q_t := "0" & BusA(7 downto 1); +- P_Out(Flag_C) <= BusA(0); +- when "1011" => +- -- ROR +- Q_t := P_In(Flag_C) & BusA(7 downto 1); +- P_Out(Flag_C) <= BusA(0); +- when "1100" => +- -- BIT +- P_Out(Flag_V) <= BusB(6); +- when "1110" => +- -- DEC +- Q_t := std_logic_vector(unsigned(BusA) - 1); +- when "1111" => +- -- INC +- Q_t := std_logic_vector(unsigned(BusA) + 1); +- when others => +- end case; ++ process (Op, P_In, BusA, BusB, ++ ADC_Z, ADC_C, ADC_V, ADC_N, ADC_Q, ++ SBC_Z, SBC_C, SBC_V, SBC_N, SBC_Q) ++ variable Q_t : std_logic_vector(7 downto 0); ++ begin ++ -- ORA, AND, EOR, ADC, NOP, LD, CMP, SBC ++ -- ASL, ROL, LSR, ROR, BIT, LD, DEC, INC ++ P_Out <= P_In; ++ Q_t := BusA; ++ case Op is ++ when ALU_OP_OR=> ++ Q_t := BusA or BusB; ++ when ALU_OP_AND=> ++ Q_t := BusA and BusB; ++ when ALU_OP_EOR=> ++ Q_t := BusA xor BusB; ++ when ALU_OP_ADC=> ++ P_Out(Flag_V) <= ADC_V; ++ P_Out(Flag_C) <= ADC_C; ++ Q_t := ADC_Q; ++ when ALU_OP_EQ2|ALU_OP_EQ3=> ++ -- LDA ++ when ALU_OP_CMP=> ++ P_Out(Flag_C) <= SBC_C; ++ when ALU_OP_SBC=> ++ P_Out(Flag_V) <= SBC_V; ++ P_Out(Flag_C) <= SBC_C; ++ Q_t := SBC_Q; ++ when ALU_OP_ASL=> ++ Q_t := BusA(6 downto 0) & "0"; ++ P_Out(Flag_C) <= BusA(7); ++ when ALU_OP_ROL=> ++ Q_t := BusA(6 downto 0) & P_In(Flag_C); ++ P_Out(Flag_C) <= BusA(7); ++ when ALU_OP_LSR=> ++ Q_t := "0" & BusA(7 downto 1); ++ P_Out(Flag_C) <= BusA(0); ++ when ALU_OP_ROR=> ++ Q_t := P_In(Flag_C) & BusA(7 downto 1); ++ P_Out(Flag_C) <= BusA(0); ++ when ALU_OP_BIT=> ++ P_Out(Flag_V) <= BusB(6); ++ when ALU_OP_DEC=> ++ Q_t := std_logic_vector(unsigned(BusA) - 1); ++ when ALU_OP_INC=> ++ Q_t := std_logic_vector(unsigned(BusA) + 1); ++ when others => ++ --EQ1,EQ2,EQ3 passes BusA to Q_t ++ end case; + +- case Op(3 downto 0) is +- when "0011" => +- P_Out(Flag_N) <= ADC_N; +- P_Out(Flag_Z) <= ADC_Z; +- when "0110" | "0111" => +- P_Out(Flag_N) <= SBC_N; +- P_Out(Flag_Z) <= SBC_Z; +- when "0100" => +- when "1100" => +- P_Out(Flag_N) <= BusB(7); +- if (BusA and BusB) = "00000000" then +- P_Out(Flag_Z) <= '1'; +- else +- P_Out(Flag_Z) <= '0'; +- end if; +- when others => +- P_Out(Flag_N) <= Q_t(7); +- if Q_t = "00000000" then +- P_Out(Flag_Z) <= '1'; +- else +- P_Out(Flag_Z) <= '0'; +- end if; +- end case; ++ case Op is ++ when ALU_OP_ADC=> ++ P_Out(Flag_N) <= ADC_N; ++ P_Out(Flag_Z) <= ADC_Z; ++ when ALU_OP_CMP|ALU_OP_SBC=> ++ P_Out(Flag_N) <= SBC_N; ++ P_Out(Flag_Z) <= SBC_Z; ++ when ALU_OP_EQ1=> ++ when ALU_OP_BIT=> ++ P_Out(Flag_N) <= BusB(7); ++ if (BusA and BusB) = "00000000" then ++ P_Out(Flag_Z) <= '1'; ++ else ++ P_Out(Flag_Z) <= '0'; ++ end if; ++ when others => ++ P_Out(Flag_N) <= Q_t(7); ++ if Q_t = "00000000" then ++ P_Out(Flag_Z) <= '1'; ++ else ++ P_Out(Flag_Z) <= '0'; ++ end if; ++ end case; + +- Q <= Q_t; +- end process; ++ Q <= Q_t; ++ end process; + + end; +diff --git a/T65/T65_MCode.vhd b/T65/T65_MCode.vhd +index 6c6c864..bfc4005 100644 +--- a/T65/T65_MCode.vhd ++++ b/T65/T65_MCode.vhd +@@ -2,9 +2,17 @@ + -- T65(b) core. In an effort to merge and maintain bug fixes .... + -- + -- ++-- Ver 303 ost(ML) July 2014 ++-- (Sorry for some scratchpad comments that may make little sense) ++-- Mods and some 6502 undocumented instructions. ++-- Undoc opcodes learnt from: ++-- "Extra Instructions Of The 65XX Series CPU" ++-- By: Adam Vardy (abe0084@infonet.st-johns.nf.ca) ++-- [File created: 22, Aug. 1995... 27, Sept. 1996] + -- Ver 302 minor timing fixes + -- Ver 301 Jump timing fixed + -- Ver 300 Bugfixes by ehenciak added ++-- Wolfgang January 2014 + -- MikeJ March 2005 + -- Latest version from www.fpgaarcade.com (original www.opencores.org) + -- +@@ -65,988 +73,1324 @@ + library IEEE; + use IEEE.std_logic_1164.all; + use IEEE.numeric_std.all; ++use ieee.std_logic_unsigned.all; + use work.T65_Pack.all; + + entity T65_MCode is +- port( +- Mode : in std_logic_vector(1 downto 0); -- "00" => 6502, "01" => 65C02, "10" => 65816 +- IR : in std_logic_vector(7 downto 0); +- MCycle : in std_logic_vector(2 downto 0); +- P : in std_logic_vector(7 downto 0); +- LCycle : out std_logic_vector(2 downto 0); +- ALU_Op : out std_logic_vector(3 downto 0); +- Set_BusA_To : out std_logic_vector(2 downto 0); -- DI,A,X,Y,S,P +- Set_Addr_To : out std_logic_vector(1 downto 0); -- PC Adder,S,AD,BA +- Write_Data : out std_logic_vector(2 downto 0); -- DL,A,X,Y,S,P,PCL,PCH +- Jump : out std_logic_vector(1 downto 0); -- PC,++,DIDL,Rel +- BAAdd : out std_logic_vector(1 downto 0); -- None,DB Inc,BA Add,BA Adj +- BreakAtNA : out std_logic; +- ADAdd : out std_logic; +- AddY : out std_logic; +- PCAdd : out std_logic; +- Inc_S : out std_logic; +- Dec_S : out std_logic; +- LDA : out std_logic; +- LDP : out std_logic; +- LDX : out std_logic; +- LDY : out std_logic; +- LDS : out std_logic; +- LDDI : out std_logic; +- LDALU : out std_logic; +- LDAD : out std_logic; +- LDBAL : out std_logic; +- LDBAH : out std_logic; +- SaveP : out std_logic; +- Write : out std_logic +- ); ++ port( ++ Mode : in std_logic_vector(1 downto 0); -- "00" => 6502, "01" => 65C02, "10" => 65816 ++ IR : in std_logic_vector(7 downto 0); ++ MCycle : in std_logic_vector(2 downto 0); ++ P : in std_logic_vector(7 downto 0); ++ LCycle : out std_logic_vector(2 downto 0); ++ ALU_Op : out T_ALU_Op; ++ Set_BusA_To : out T_Set_BusA_To;-- DI,A,X,Y,S,P ++ Set_Addr_To : out T_Set_Addr_To;-- PC Adder,S,AD,BA ++ Write_Data : out T_Write_Data;-- DL,A,X,Y,S,P,PCL,PCH,A&X ++ Jump : out std_logic_vector(1 downto 0); -- PC,++,DIDL,Rel ++ BAAdd : out std_logic_vector(1 downto 0); -- None,DB Inc,BA Add,BA Adj ++ BreakAtNA : out std_logic; ++ ADAdd : out std_logic; ++ AddY : out std_logic; ++ PCAdd : out std_logic; ++ Inc_S : out std_logic; ++ Dec_S : out std_logic; ++ LDA : out std_logic; ++ LDP : out std_logic; ++ LDX : out std_logic; ++ LDY : out std_logic; ++ LDS : out std_logic; ++ LDDI : out std_logic; ++ LDALU : out std_logic; ++ LDAD : out std_logic; ++ LDBAL : out std_logic; ++ LDBAH : out std_logic; ++ SaveP : out std_logic; ++ ALUmore : out std_logic; ++ Write : out std_logic ++ ); + end T65_MCode; + + architecture rtl of T65_MCode is + +- signal Branch : std_logic; ++ signal Branch : std_logic; ++ --ML:I need the Lcycle locally, so I made it a signal. ++ signal tLcycle:std_logic_vector(Lcycle'range); ++ signal tALUmore:std_logic; ++ ++ --Some simulation debug values. Put an unique number for each assignment and identify it in simulation. ++ signal dbg_Set_BusA_To :integer:=0; --sim debug value to find where Set_BusA_To gets set. ++ signal dbg_LCycle :integer:=0; --sim debug value to fin where tLCycle gets set. ++ signal dbg_Set_Addr_To :integer:=0; --sim debug value to fin where Set_Addr_To gets set. + + begin + +- with IR(7 downto 5) select +- Branch <= not P(Flag_N) when "000", +- P(Flag_N) when "001", +- not P(Flag_V) when "010", +- P(Flag_V) when "011", +- not P(Flag_C) when "100", +- P(Flag_C) when "101", +- not P(Flag_Z) when "110", +- P(Flag_Z) when others; ++ with IR(7 downto 5) select ++ Branch <= not P(Flag_N) when "000", ++ P(Flag_N) when "001", ++ not P(Flag_V) when "010", ++ P(Flag_V) when "011", ++ not P(Flag_C) when "100", ++ P(Flag_C) when "101", ++ not P(Flag_Z) when "110", ++ P(Flag_Z) when others; + +- process (IR, MCycle, P, Branch, Mode) +- begin +- LCycle <= "001"; +- Set_BusA_To <= "001"; -- A +- Set_Addr_To <= (others => '0'); +- Write_Data <= (others => '0'); +- Jump <= (others => '0'); +- BAAdd <= "00"; +- BreakAtNA <= '0'; +- ADAdd <= '0'; +- PCAdd <= '0'; +- Inc_S <= '0'; +- Dec_S <= '0'; +- LDA <= '0'; +- LDP <= '0'; +- LDX <= '0'; +- LDY <= '0'; +- LDS <= '0'; +- LDDI <= '0'; +- LDALU <= '0'; +- LDAD <= '0'; +- LDBAL <= '0'; +- LDBAH <= '0'; +- SaveP <= '0'; +- Write <= '0'; +- AddY <= '0'; ++ LCycle<=tLCycle; ++ ALUmore<=tALUmore; + +- case IR(7 downto 5) is +- when "100" => +- --{{{ +- case IR(1 downto 0) is +- when "00" => +- Set_BusA_To <= "011"; -- Y +- Write_Data <= "011"; -- Y +- when "10" => +- Set_BusA_To <= "010"; -- X +- Write_Data <= "010"; -- X +- when others => +- Write_Data <= "001"; -- A +- end case; +- --}}} +- when "101" => +- --{{{ +- case IR(1 downto 0) is +- when "00" => +- if IR(4) /= '1' or IR(2) /= '0' then +- LDY <= '1'; +- end if; +- when "10" => +- LDX <= '1'; +- when others => +- LDA <= '1'; +- end case; +- Set_BusA_To <= "000"; -- DI +- --}}} +- when "110" => +- --{{{ +- case IR(1 downto 0) is +- when "00" => +- if IR(4) = '0' then +- LDY <= '1'; +- end if; +- Set_BusA_To <= "011"; -- Y +- when others => +- Set_BusA_To <= "001"; -- A +- end case; +- --}}} +- when "111" => +- --{{{ +- case IR(1 downto 0) is +- when "00" => +- if IR(4) = '0' then +- LDX <= '1'; +- end if; +- Set_BusA_To <= "010"; -- X +- when others => +- Set_BusA_To <= "001"; -- A +- end case; +- --}}} +- when others => +- end case; ++ process (IR, MCycle, P, Branch, Mode,tALUmore) ++ begin ++ tLCycle <= "001"; ++ Set_BusA_To <= Set_BusA_To_ABC; ++ Set_Addr_To <= Set_Addr_To_PBR; ++ Write_Data <= Write_Data_DL; ++ Jump <= (others => '0'); ++ BAAdd <= "00"; ++ BreakAtNA <= '0'; ++ ADAdd <= '0'; ++ PCAdd <= '0'; ++ Inc_S <= '0'; ++ Dec_S <= '0'; ++ LDA <= '0'; ++ LDP <= '0'; ++ LDX <= '0'; ++ LDY <= '0'; ++ LDS <= '0'; ++ LDDI <= '0'; ++ LDALU <= '0'; ++ LDAD <= '0'; ++ LDBAL <= '0'; ++ LDBAH <= '0'; ++ SaveP <= '0'; ++ Write <= '0'; ++ AddY <= '0'; ++ tALUmore <='0'; ++ ++ case IR(7 downto 5) is ++ when "100" =>--covers 8x,9x ++ --{{{ ++ case IR(1 downto 0) is ++ when "00" => ++ Set_BusA_To <= Set_BusA_To_Y; ++ dbg_Set_BusA_To<=1; ++ Write_Data <= Write_Data_Y; ++ when "10" => ++ Set_BusA_To <= Set_BusA_To_X; ++ dbg_Set_BusA_To<=2; ++ Write_Data <= Write_Data_X; ++ when others => ++ Write_Data <= Write_Data_ABC; ++ end case; ++ --}}} ++ when "101" =>--covers ax,bx ++ --{{{ ++ case IR(1 downto 0) is ++ when "00" => ++ if IR(4) /= '1' or IR(2) /= '0' then--only for ax or b4,bc ++ LDY <= '1'; ++ end if; ++ when "10" => ++ LDX <= '1'; ++ when "11" =>--undoc (beware OAL(ab),LAS(bb)=>Dont know what will happen) ++ LDX<='1'; ++ LDA<='1'; ++ when others => ++ LDA <= '1'; ++ end case; ++ Set_BusA_To <= Set_BusA_To_DI; ++ dbg_Set_BusA_To<=4; ++ --}}} ++ when "110" =>--covers cx,dx ++ --{{{ ++ case IR(1 downto 0) is ++ when "00" => ++ if IR(4) = '0' then--only for cx ++ LDY <= '1'; ++ end if; ++ Set_BusA_To <= Set_BusA_To_Y; ++ dbg_Set_BusA_To<=5; ++ when others => ++ Set_BusA_To <= Set_BusA_To_ABC; ++ dbg_Set_BusA_To<=6; ++ end case; ++ --}}} ++ when "111" =>--covers ex,fx ++ --{{{ ++ case IR(1 downto 0) is ++ when "00" => ++ if IR(4) = '0' then--only ex ++ LDX <= '1'; ++ end if; ++ Set_BusA_To <= Set_BusA_To_X; ++ dbg_Set_BusA_To<=7; ++ when others => ++ Set_BusA_To <= Set_BusA_To_ABC; ++ dbg_Set_BusA_To<=8; ++ end case; ++ --}}} ++ when others => ++ end case; + +- if IR(7 downto 6) /= "10" and IR(1 downto 0) = "10" then +- Set_BusA_To <= "000"; -- DI +- end if; ++-- if IR(7 downto 6) /= "10" and IR(1 downto 0) = "10" then--covers 0x-7x,cx-fx x=2,6,a,e ++ if IR(7 downto 6) /= "10" and IR(1) = '1' and (mode="00" or IR(0)='0') then--covers 0x-7x,cx-fx x=2,3,6,7,a,b,e,f, for 6502 undocs ++-- if Mode="00" and IR(0)='1' and ((IR(3 downto 2)="11" and MCycle = "101") or (IR(3 downto 2)="01" and MCycle = "100"))then ++ --if Mode="00" and IR(0)='1' and MCycle+1 = tLCycle then ++ if tALUmore='1' then ++ Set_BusA_To <= Set_BusA_To_ABC;--For added compare to DCP/DCM ++ dbg_Set_BusA_To<=99; ++ else ++ Set_BusA_To <= Set_BusA_To_DI; ++ dbg_Set_BusA_To<=9; ++ end if; ++ end if; + +- case IR(4 downto 0) is +- when "00000" | "01000" | "01010" | "11000" | "11010" => +- --{{{ +- -- Implied +- case IR is +- when "00000000" => +- -- BRK +- LCycle <= "110"; +- case to_integer(unsigned(MCycle)) is +- when 1 => +- Set_Addr_To <= "01"; -- S +- Write_Data <= "111"; -- PCH +- Write <= '1'; +- when 2 => +- Dec_S <= '1'; +- Set_Addr_To <= "01"; -- S +- Write_Data <= "110"; -- PCL +- Write <= '1'; +- when 3 => +- Dec_S <= '1'; +- Set_Addr_To <= "01"; -- S +- Write_Data <= "101"; -- P +- Write <= '1'; +- when 4 => +- Dec_S <= '1'; +- Set_Addr_To <= "11"; -- BA +- when 5 => +- LDDI <= '1'; +- Set_Addr_To <= "11"; -- BA +- when 6 => +- Jump <= "10"; -- DIDL +- when others => +- end case; +- when "00100000" => +- -- JSR +- LCycle <= "101"; +- case to_integer(unsigned(MCycle)) is +- when 1 => +- Jump <= "01"; +- LDDI <= '1'; +- Set_Addr_To <= "01"; -- S +- when 2 => +- Set_Addr_To <= "01"; -- S +- Write_Data <= "111"; -- PCH +- Write <= '1'; +- when 3 => +- Dec_S <= '1'; +- Set_Addr_To <= "01"; -- S +- Write_Data <= "110"; -- PCL +- Write <= '1'; +- when 4 => +- Dec_S <= '1'; +- when 5 => +- Jump <= "10"; -- DIDL +- when others => +- end case; +- when "01000000" => +- -- RTI +- LCycle <= "101"; +- case to_integer(unsigned(MCycle)) is +- when 1 => +- Set_Addr_To <= "01"; -- S +- when 2 => +- Inc_S <= '1'; +- Set_Addr_To <= "01"; -- S +- when 3 => +- Inc_S <= '1'; +- Set_Addr_To <= "01"; -- S +- Set_BusA_To <= "000"; -- DI +- when 4 => +- LDP <= '1'; +- Inc_S <= '1'; +- LDDI <= '1'; +- Set_Addr_To <= "01"; -- S +- when 5 => +- Jump <= "10"; -- DIDL +- when others => +- end case; +- when "01100000" => +- -- RTS +- LCycle <= "101"; +- case to_integer(unsigned(MCycle)) is +- when 1 => +- Set_Addr_To <= "01"; -- S +- when 2 => +- Inc_S <= '1'; +- Set_Addr_To <= "01"; -- S +- when 3 => +- Inc_S <= '1'; +- LDDI <= '1'; +- Set_Addr_To <= "01"; -- S +- when 4 => +- Jump <= "10"; -- DIDL +- when 5 => +- Jump <= "01"; +- when others => +- end case; +- when "00001000" | "01001000" | "01011010" | "11011010" => +- -- PHP, PHA, PHY*, PHX* +- LCycle <= "010"; +- if Mode = "00" and IR(1) = '1' then +- LCycle <= "001"; +- end if; +- case to_integer(unsigned(MCycle)) is +- when 1 => +- case IR(7 downto 4) is +- when "0000" => +- Write_Data <= "101"; -- P +- when "0100" => +- Write_Data <= "001"; -- A +- when "0101" => +- Write_Data <= "011"; -- Y +- when "1101" => +- Write_Data <= "010"; -- X +- when others => +- end case; +- Write <= '1'; +- Set_Addr_To <= "01"; -- S +- when 2 => +- Dec_S <= '1'; +- when others => +- end case; +- when "00101000" | "01101000" | "01111010" | "11111010" => +- -- PLP, PLA, PLY*, PLX* +- LCycle <= "011"; +- if Mode = "00" and IR(1) = '1' then +- LCycle <= "001"; +- end if; +- case IR(7 downto 4) is +- when "0010" => +- LDP <= '1'; +- when "0110" => +- LDA <= '1'; +- when "0111" => +- if Mode /= "00" then +- LDY <= '1'; +- end if; +- when "1111" => +- if Mode /= "00" then +- LDX <= '1'; +- end if; +- when others => +- end case; +- case to_integer(unsigned(MCycle)) is +- when 0 => +- SaveP <= '1'; +- when 1 => +- Set_Addr_To <= "01"; -- S +- when 2 => +- Inc_S <= '1'; +- Set_Addr_To <= "01"; -- S +- when 3 => +- Set_BusA_To <= "000"; -- DI +- when others => +- end case; +- when "10100000" | "11000000" | "11100000" => +- -- LDY, CPY, CPX +- -- Immediate +- case to_integer(unsigned(MCycle)) is +- when 0 => +- when 1 => +- Jump <= "01"; +- when others => +- end case; +- when "10001000" => +- -- DEY +- LDY <= '1'; +- case to_integer(unsigned(MCycle)) is +- when 0 => +- when 1 => +- Set_BusA_To <= "011"; -- Y +- when others => +- end case; +- when "11001010" => +- -- DEX +- LDX <= '1'; +- case to_integer(unsigned(MCycle)) is +- when 0 => +- when 1 => +- Set_BusA_To <= "010"; -- X +- when others => +- end case; +- when "00011010" | "00111010" => +- -- INC*, DEC* +- if Mode /= "00" then +- LDA <= '1'; -- A +- end if; +- case to_integer(unsigned(MCycle)) is +- when 0 => +- when 1 => +- Set_BusA_To <= "100"; -- S +- when others => +- end case; +- when "00001010" | "00101010" | "01001010" | "01101010" => +- -- ASL, ROL, LSR, ROR +- LDA <= '1'; -- A +- Set_BusA_To <= "001"; -- A +- case to_integer(unsigned(MCycle)) is +- when 0 => +- when 1 => +- when others => +- end case; +- when "10001010" | "10011000" => +- -- TYA, TXA +- LDA <= '1'; -- A +- case to_integer(unsigned(MCycle)) is +- when 0 => +- when 1 => +- when others => +- end case; +- when "10101010" | "10101000" => +- -- TAX, TAY +- case to_integer(unsigned(MCycle)) is +- when 0 => +- when 1 => +- Set_BusA_To <= "001"; -- A +- when others => +- end case; +- when "10011010" => +- -- TXS +- case to_integer(unsigned(MCycle)) is +- when 0 => +- LDS <= '1'; +- when 1 => +- when others => +- end case; +- when "10111010" => +- -- TSX +- LDX <= '1'; +- case to_integer(unsigned(MCycle)) is +- when 0 => +- when 1 => +- Set_BusA_To <= "100"; -- S +- when others => +- end case; ++ case IR(4 downto 0) is ++ when "00000" | "01000" | "01010" | "11000" | "11010" => ++ --{{{ ++ -- Implied ++ case IR is ++ when "00000000" => ++ -- BRK ++ tLCycle <= "110"; ++ dbg_LCycle<=1; ++ case to_integer(unsigned(MCycle)) is ++ when 1 => ++ Set_Addr_To <= Set_Addr_To_S; ++ dbg_Set_Addr_To<=1; ++ Write_Data <= Write_Data_PCH; ++ Write <= '1'; ++ when 2 => ++ Dec_S <= '1'; ++ Set_Addr_To <= Set_Addr_To_S; ++ dbg_Set_Addr_To<=2; ++ Write_Data <= Write_Data_PCL; ++ Write <= '1'; ++ when 3 => ++ Dec_S <= '1'; ++ Set_Addr_To <= Set_Addr_To_S; ++ dbg_Set_Addr_To<=3; ++ Write_Data <= Write_Data_P; ++ Write <= '1'; ++ when 4 => ++ Dec_S <= '1'; ++ Set_Addr_To <= Set_Addr_To_BA; ++ dbg_Set_Addr_To<=4; ++ when 5 => ++ LDDI <= '1'; ++ Set_Addr_To <= Set_Addr_To_BA; ++ dbg_Set_Addr_To<=5; ++ when 6 => ++ Jump <= "10"; -- DIDL ++ when others => ++ end case; ++ when "00100000" => ++ -- JSR ++ tLCycle <= "101"; ++ dbg_LCycle<=2; ++ case to_integer(unsigned(MCycle)) is ++ when 1 => ++ Jump <= "01"; ++ LDDI <= '1'; ++ Set_Addr_To <= Set_Addr_To_S; ++ dbg_Set_Addr_To<=6; ++ when 2 => ++ Set_Addr_To <= Set_Addr_To_S; ++ dbg_Set_Addr_To<=7; ++ Write_Data <= Write_Data_PCH; ++ Write <= '1'; ++ when 3 => ++ Dec_S <= '1'; ++ Set_Addr_To <= Set_Addr_To_S; ++ dbg_Set_Addr_To<=8; ++ Write_Data <= Write_Data_PCL; ++ Write <= '1'; ++ when 4 => ++ Dec_S <= '1'; ++ when 5 => ++ Jump <= "10"; -- DIDL ++ when others => ++ end case; ++ when "01000000" => ++ -- RTI ++ tLCycle <= "101"; ++ dbg_LCycle<=3; ++ case to_integer(unsigned(MCycle)) is ++ when 1 => ++ Set_Addr_To <= Set_Addr_To_S; ++ dbg_Set_Addr_To<=9; ++ when 2 => ++ Inc_S <= '1'; ++ Set_Addr_To <= Set_Addr_To_S; ++ dbg_Set_Addr_To<=10; ++ when 3 => ++ Inc_S <= '1'; ++ Set_Addr_To <= Set_Addr_To_S; ++ dbg_Set_Addr_To<=11; ++ Set_BusA_To <= Set_BusA_To_DI; ++ dbg_Set_BusA_To<=10; ++ when 4 => ++ LDP <= '1'; ++ Inc_S <= '1'; ++ LDDI <= '1'; ++ Set_Addr_To <= Set_Addr_To_S; ++ dbg_Set_Addr_To<=12; ++ when 5 => ++ Jump <= "10"; -- DIDL ++ when others => ++ end case; ++ when "01100000" => ++ -- RTS ++ tLCycle <= "101"; ++ dbg_LCycle<=4; ++ case to_integer(unsigned(MCycle)) is ++ when 1 => ++ Set_Addr_To <= Set_Addr_To_S; ++ dbg_Set_Addr_To<=13; ++ when 2 => ++ Inc_S <= '1'; ++ Set_Addr_To <= Set_Addr_To_S; ++ dbg_Set_Addr_To<=14; ++ when 3 => ++ Inc_S <= '1'; ++ LDDI <= '1'; ++ Set_Addr_To <= Set_Addr_To_S; ++ dbg_Set_Addr_To<=15; ++ when 4 => ++ Jump <= "10"; -- DIDL ++ when 5 => ++ Jump <= "01"; ++ when others => ++ end case; ++ when "00001000" | "01001000" | "01011010" | "11011010" => ++ -- PHP, PHA, PHY*, PHX* ++ tLCycle <= "010"; ++ dbg_LCycle<=5; ++ if Mode = "00" and IR(1) = '1' then--2 cycle nop ++ tLCycle <= "001"; ++ dbg_LCycle<=6; ++ end if; ++ case to_integer(unsigned(MCycle)) is ++ when 1 => ++ if mode/="00" or IR(1)='0' then --wrong on 6502 ++ Write <= '1'; ++ case IR(7 downto 4) is ++ when "0000" => ++ Write_Data <= Write_Data_P; ++ when "0100" => ++ Write_Data <= Write_Data_ABC; ++ when "0101" => --not correct unsupporte ++ if Mode /= "00" then ++ Write_Data <= Write_Data_Y; ++ else ++ Write <= '0'; ++ end if; ++ when "1101" => ++ if Mode /= "00" then ++ Write_Data <= Write_Data_X; ++ else ++ Write <= '0'; ++ end if; ++ when others => ++ end case; ++ Set_Addr_To <= Set_Addr_To_S; ++ dbg_Set_Addr_To<=16; ++ end if; ++ when 2 => ++ Dec_S <= '1'; ++ when others => ++ end case; ++ when "00101000" | "01101000" | "01111010" | "11111010" => ++ -- PLP, PLA, PLY*, PLX* ++ tLCycle <= "011"; ++ dbg_LCycle<=7; ++ if Mode = "00" and IR(1) = '1' then--2 cycle nop ++ tLCycle <= "001"; ++ dbg_LCycle<=8; ++ end if; ++ case IR(7 downto 4) is ++ when "0010" =>--plp ++ LDP <= '1'; ++ when "0110" =>--pla ++ LDA <= '1'; ++ when "0111" =>--ply not for 6502 ++ if Mode /= "00" then ++ LDY <= '1'; ++ end if; ++ when "1111" =>--plx not for 6502 ++ if Mode /= "00" then ++ LDX <= '1'; ++ end if; ++ when others => ++ end case; + +- -- when "00011000" | "00111000" | "01011000" | "01111000" | "10111000" | "11011000" | "11111000" | "11001000" | "11101000" => +- -- -- CLC, SEC, CLI, SEI, CLV, CLD, SED, INY, INX +- -- case to_integer(unsigned(MCycle)) is +- -- when 1 => +- -- when others => +- -- end case; +- when others => +- case to_integer(unsigned(MCycle)) is +- when 0 => +- when others => +- end case; +- end case; +- --}}} ++ case to_integer(unsigned(MCycle)) is ++ when 0 => ++ if Mode /= "00" or IR(1) = '0' then--wrong on 6502 ++ SaveP <= '1'; ++ end if; ++ when 1 => ++ if Mode /= "00" or IR(1) = '0' then--wrong on 6502 ++ Set_Addr_To <= Set_Addr_To_S; ++ dbg_Set_Addr_To<=17; ++ -- MWW This is wrong, ALU_OP is not populated yet, so previous op's P_out can be saved (This was caused by ROL followed by PLA - THE ISSUE MAY BE DEEPER!) ++ --SaveP <= '1'; --MWW ++ LDP <= '0';--MWW ++ end if; ++ when 2 => ++ Inc_S <= '1'; ++ Set_Addr_To <= Set_Addr_To_S; ++ dbg_Set_Addr_To<=18; ++ --SaveP <= '1';--MWW ++ LDP <= '0'; --MWW ++ when 3 => ++ Set_BusA_To <= Set_BusA_To_DI; ++ dbg_Set_BusA_To<=11; ++ when others => ++ end case; ++ when "10100000" | "11000000" | "11100000" => ++ -- LDY, CPY, CPX ++ -- Immediate ++ case to_integer(unsigned(MCycle)) is ++ when 0 => ++ when 1 => ++ Jump <= "01"; ++ when others => ++ end case; ++ when "10001000" => ++ -- DEY ++ LDY <= '1'; ++ case to_integer(unsigned(MCycle)) is ++ when 0 => ++ when 1 => ++ Set_BusA_To <= Set_BusA_To_Y; ++ dbg_Set_BusA_To<=12; ++ when others => ++ end case; ++ when "11001010" => ++ -- DEX ++ LDX <= '1'; ++ case to_integer(unsigned(MCycle)) is ++ when 0 => ++ when 1 => ++ Set_BusA_To <= Set_BusA_To_X; ++ dbg_Set_BusA_To<=13; ++ when others => ++ end case; ++ when "00011010" | "00111010" => ++ -- INC*, DEC* ++ if Mode /= "00" then ++ LDA <= '1'; -- A ++ else ++ tLCycle <= "001";--undoc 2 cycle nop..can I just load tLCycle counter like this? ++ dbg_LCycle<=9; ++ end if; ++ case to_integer(unsigned(MCycle)) is ++ when 0 => ++ when 1 => ++ Set_BusA_To <= Set_BusA_To_S; ++ dbg_Set_BusA_To<=14; ++ when others => ++ end case; ++ when "00001010" | "00101010" | "01001010" | "01101010" => ++ -- ASL, ROL, LSR, ROR ++ LDA <= '1'; -- A ++ Set_BusA_To <= Set_BusA_To_ABC; ++ dbg_Set_BusA_To<=15; ++ case to_integer(unsigned(MCycle)) is ++ when 0 => ++ when 1 => ++ when others => ++ end case; ++ when "10001010" | "10011000" => ++ -- TYA, TXA ++ LDA <= '1'; -- A ++ case to_integer(unsigned(MCycle)) is ++ when 0 => ++ when 1 => ++ when others => ++ end case; ++ when "10101010" | "10101000" => ++ -- TAX, TAY ++ case to_integer(unsigned(MCycle)) is ++ when 0 => ++ when 1 => ++ Set_BusA_To <= Set_BusA_To_ABC; ++ dbg_Set_BusA_To<=16; ++ when others => ++ end case; ++ when "10011010" => ++ -- TXS ++ case to_integer(unsigned(MCycle)) is ++ when 0 => ++ LDS <= '1'; ++ when 1 => ++ when others => ++ end case; ++ when "10111010" => ++ -- TSX ++ LDX <= '1'; ++ case to_integer(unsigned(MCycle)) is ++ when 0 => ++ when 1 => ++ Set_BusA_To <= Set_BusA_To_S; ++ dbg_Set_BusA_To<=17; ++ when others => ++ end case; + +- when "00001" | "00011" => +- --{{{ +- -- Zero Page Indexed Indirect (d,x) +- LCycle <= "101"; +- if IR(7 downto 6) /= "10" then +- LDA <= '1'; +- end if; +- case to_integer(unsigned(MCycle)) is +- when 0 => +- when 1 => +- Jump <= "01"; +- LDAD <= '1'; +- Set_Addr_To <= "10"; -- AD +- when 2 => +- ADAdd <= '1'; +- Set_Addr_To <= "10"; -- AD +- when 3 => +- BAAdd <= "01"; -- DB Inc +- LDBAL <= '1'; +- Set_Addr_To <= "10"; -- AD +- when 4 => +- LDBAH <= '1'; +- if IR(7 downto 5) = "100" then +- Write <= '1'; +- end if; +- Set_Addr_To <= "11"; -- BA +- when 5 => +- when others => +- end case; +- --}}} ++ -- when "00011000" | "00111000" | "01011000" | "01111000" | "10111000" | "11011000" | "11111000" | "11001000" | "11101000" => ++ -- -- CLC, SEC, CLI, SEI, CLV, CLD, SED, INY, INX ++ -- case to_integer(unsigned(MCycle)) is ++ -- when 1 => ++ -- when others => ++ -- end case; ++ when others => ++ case to_integer(unsigned(MCycle)) is ++ when 0 => ++ when others => ++ end case; ++ end case; ++ --}}} + +- when "01001" | "01011" => +- --{{{ +- -- Immediate +- LDA <= '1'; +- case to_integer(unsigned(MCycle)) is +- when 0 => +- when 1 => +- Jump <= "01"; +- when others => +- end case; ++ when "00001" | "00011" => ++ --{{{ ++ -- Zero Page Indexed Indirect (d,x) ++ tLCycle <= "101"; ++ dbg_LCycle<=10; ++ if IR(7 downto 6) /= "10" then ++ LDA <= '1'; ++ if Mode="00" and IR(1)='1' then--b3 ++ LDX <= '1';--undoc, can load both A and X ++ end if; ++ end if; ++ case to_integer(unsigned(MCycle)) is ++ when 1 => ++ Jump <= "01"; ++ LDAD <= '1'; ++ Set_Addr_To <= Set_Addr_To_AD; ++ dbg_Set_Addr_To<=19; ++ when 2 => ++ ADAdd <= '1'; ++ Set_Addr_To <= Set_Addr_To_AD; ++ dbg_Set_Addr_To<=20; ++ when 3 => ++ BAAdd <= "01"; -- DB Inc ++ LDBAL <= '1'; ++ Set_Addr_To <= Set_Addr_To_AD; ++ dbg_Set_Addr_To<=21; ++ when 4 => ++ LDBAH <= '1'; ++ if IR(7 downto 5) = "100" then ++ Write <= '1'; ++ end if; ++ Set_Addr_To <= Set_Addr_To_BA; ++ dbg_Set_Addr_To<=22; ++ when 5 => ++ if Mode="00" and IR(1)='1' then ++ tALUmore <= '1';--ML:For undoc ASO support ++ end if; ++ when 0 => ++ if Mode="00" and IR(1)='1' then ++ SaveP <= '1';--ML:For undoc DCP/DCM support, save again after compare ++ end if; ++ when others => ++ end case; ++ --}}} + +- --}}} ++ when "01001" | "01011" => ++ --{{{ ++ -- Immediate ++ LDA <= '1'; ++ case to_integer(unsigned(MCycle)) is ++ when 0 => ++ when 1 => ++ Jump <= "01"; ++ when others => ++ end case; + +- when "00010" | "10010" => +- --{{{ +- -- Immediate, KIL +- LDX <= '1'; +- case to_integer(unsigned(MCycle)) is +- when 0 => +- when 1 => +- if IR = "10100010" then +- -- LDX +- Jump <= "01"; +- else +- -- KIL !!!!!!!!!!!!!!!!!!!!!!!!!!!!! +- end if; +- when others => +- end case; +- --}}} ++ --}}} + +- when "00100" => +- --{{{ +- -- Zero Page +- LCycle <= "010"; +- case to_integer(unsigned(MCycle)) is +- when 0 => +- if IR(7 downto 5) = "001" then +- SaveP <= '1'; +- end if; +- when 1 => +- Jump <= "01"; +- LDAD <= '1'; +- if IR(7 downto 5) = "100" then +- Write <= '1'; +- end if; +- Set_Addr_To <= "10"; -- AD +- when 2 => +- when others => +- end case; +- --}}} ++ when "00010" | "10010" => ++ --{{{ ++ -- Immediate, SKB, KIL + +- when "00101" | "00110" | "00111" => +- --{{{ +- -- Zero Page +- if IR(7 downto 6) /= "10" and IR(1 downto 0) = "10" then +- -- Read-Modify-Write +- LCycle <= "100"; +- case to_integer(unsigned(MCycle)) is +- when 1 => +- Jump <= "01"; +- LDAD <= '1'; +- Set_Addr_To <= "10"; -- AD +- when 2 => +- LDDI <= '1'; +- Write <= '1'; +- Set_Addr_To <= "10"; -- AD +- when 3 => +- LDALU <= '1'; +- SaveP <= '1'; +- Write <= '1'; +- Set_Addr_To <= "10"; -- AD +- when 4 => +- when others => +- end case; +- else +- LCycle <= "010"; +- if IR(7 downto 6) /= "10" then +- LDA <= '1'; +- end if; +- case to_integer(unsigned(MCycle)) is +- when 0 => +- when 1 => +- Jump <= "01"; +- LDAD <= '1'; +- if IR(7 downto 5) = "100" then +- Write <= '1'; +- end if; +- Set_Addr_To <= "10"; -- AD +- when 2 => +- when others => +- end case; +- end if; +- --}}} ++ case to_integer(unsigned(MCycle)) is ++ when 0 => ++ when 1 => ++ if IR = "10100010" then ++ -- LDX ++ Jump <= "01"; ++ LDX <= '1';--ML:Moved, Lorenz test showed X changing on SKB (NOPx) ++ elsif IR(7 downto 4)="1000" or IR(7 downto 4)="1100" or IR(7 downto 4)="1110" then ++ -- SKB skip next byte undoc ++ else ++ -- KIL !!!!!!!!!!!!!!!!!!!!!!!!!!!!! ++ end if; ++ when others => ++ end case; ++ --}}} + +- when "01100" => +- --{{{ +- -- Absolute +- if IR(7 downto 6) = "01" and IR(4 downto 0) = "01100" then +- -- JMP +- if IR(5) = '0' then +- --LCycle <= "011"; +- LCycle <= "010"; +- case to_integer(unsigned(MCycle)) is +- when 1 => +- Jump <= "01"; +- LDDI <= '1'; +- when 2 => +- Jump <= "10"; -- DIDL +- when others => +- end case; +- else +- --LCycle <= "101"; +- LCycle <= "100"; -- mikej +- case to_integer(unsigned(MCycle)) is +- when 1 => +- Jump <= "01"; +- LDDI <= '1'; +- LDBAL <= '1'; +- when 2 => +- LDBAH <= '1'; +- if Mode /= "00" then +- Jump <= "10"; -- DIDL +- end if; +- if Mode = "00" then +- Set_Addr_To <= "11"; -- BA +- end if; +- when 3 => +- LDDI <= '1'; +- if Mode = "00" then +- Set_Addr_To <= "11"; -- BA +- BAAdd <= "01"; -- DB Inc +- else +- Jump <= "01"; +- end if; +- when 4 => +- Jump <= "10"; -- DIDL +- when others => +- end case; +- end if; +- else +- LCycle <= "011"; +- case to_integer(unsigned(MCycle)) is +- when 0 => +- if IR(7 downto 5) = "001" then +- SaveP <= '1'; +- end if; +- when 1 => +- Jump <= "01"; +- LDBAL <= '1'; +- when 2 => +- Jump <= "01"; +- LDBAH <= '1'; +- if IR(7 downto 5) = "100" then +- Write <= '1'; +- end if; +- Set_Addr_To <= "11"; -- BA +- when 3 => +- when others => +- end case; +- end if; +- --}}} ++ when "00100" => ++ --{{{ ++ -- Zero Page ++ tLCycle <= "010"; ++ dbg_LCycle<=11; ++ case to_integer(unsigned(MCycle)) is ++ when 0 => ++ if IR(7 downto 5) = "001" then--24=BIT zpg ++ SaveP <= '1'; ++ end if; ++ when 1 => ++ Jump <= "01"; ++ LDAD <= '1'; ++ if IR(7 downto 5) = "100" then--84=sty zpg (the only write in this group) ++ Write <= '1'; ++ end if; ++ Set_Addr_To <= Set_Addr_To_AD; ++ dbg_Set_Addr_To<=23; ++ when 2 => ++ when others => ++ end case; ++ --}}} + +- when "01101" | "01110" | "01111" => +- --{{{ +- -- Absolute +- if IR(7 downto 6) /= "10" and IR(1 downto 0) = "10" then +- -- Read-Modify-Write +- LCycle <= "101"; +- case to_integer(unsigned(MCycle)) is +- when 1 => +- Jump <= "01"; +- LDBAL <= '1'; +- when 2 => +- Jump <= "01"; +- LDBAH <= '1'; +- Set_Addr_To <= "11"; -- BA +- when 3 => +- LDDI <= '1'; +- Write <= '1'; +- Set_Addr_To <= "11"; -- BA +- when 4 => +- Write <= '1'; +- LDALU <= '1'; +- SaveP <= '1'; +- Set_Addr_To <= "11"; -- BA +- when 5 => +- SaveP <= '0'; -- MIKEJ was 1 +- when others => +- end case; +- else +- LCycle <= "011"; +- if IR(7 downto 6) /= "10" then +- LDA <= '1'; +- end if; +- case to_integer(unsigned(MCycle)) is +- when 0 => +- when 1 => +- Jump <= "01"; +- LDBAL <= '1'; +- when 2 => +- Jump <= "01"; +- LDBAH <= '1'; +- if IR(7 downto 5) = "100" then +- Write <= '1'; +- end if; +- Set_Addr_To <= "11"; -- BA +- when 3 => +- when others => +- end case; +- end if; +- --}}} ++ when "00101" | "00110" | "00111" => ++ --{{{ ++ -- Zero Page ++-- if IR(7 downto 6) /= "10" and IR(1 downto 0) = "10" then--0x-7x,cx-fx, x=2,6,a,e ++ if IR(7 downto 6) /= "10" and IR(1) = '1' and (mode="00" or IR(0)='0') then--covers 0x-7x,cx-fx x=2,3,6,7,a,b,e,f, for 6502 undocs ++ -- Read-Modify-Write ++ if Mode="00" and IR(0)='1' then ++ LDA<='1'; ++ end if; ++ tLCycle <= "100"; ++ dbg_LCycle<=12; ++ case to_integer(unsigned(MCycle)) is ++ when 1 => ++ Jump <= "01"; ++ LDAD <= '1'; ++ Set_Addr_To <= Set_Addr_To_AD; ++ dbg_Set_Addr_To<=24; ++ when 2 => ++ LDDI <= '1'; ++ if Mode="00" then--The old 6500 writes back what is just read, before changing. The 65c does another read ++ Write <= '1'; ++ end if; ++ Set_Addr_To <= Set_Addr_To_AD; ++ dbg_Set_Addr_To<=25; ++ when 3 => ++ LDALU <= '1'; ++ SaveP <= '1'; ++ Write <= '1'; ++ Set_Addr_To <= Set_Addr_To_AD; ++ dbg_Set_Addr_To<=26; ++ when 4 => ++ if Mode="00" and IR(0)='1' then ++ tALUmore <= '1';--ML:For undoc DCP/DCM support ++ end if; ++ when 0 => ++ if Mode="00" and IR(0)='1' then ++ SaveP <= '1';--ML:For undoc DCP/DCM support, save again after compare ++ end if; ++ when others => ++ end case; ++ else ++ tLCycle <= "010"; ++ dbg_LCycle<=13; ++ if IR(7 downto 6) /= "10" then ++ LDA <= '1'; ++ if Mode="00" and IR(1)='1' then--b3 ++ LDX <= '1';--undoc, can load both A and X ++ end if; ++ end if; ++ case to_integer(unsigned(MCycle)) is ++ when 0 => ++ when 1 => ++ Jump <= "01"; ++ LDAD <= '1'; ++ if IR(7 downto 5) = "100" then ++ Write <= '1'; ++ end if; ++ Set_Addr_To <= Set_Addr_To_AD; ++ dbg_Set_Addr_To<=27; ++ when 2 => ++ when others => ++ end case; ++ end if; ++ --}}} + +- when "10000" => +- --{{{ +- -- Relative ++ when "01100" => ++ --{{{ ++ -- Absolute ++ if IR(7 downto 6) = "01" and IR(4 downto 0) = "01100" then--4c,6c ++ -- JMP ++ if IR(5) = '0' then ++ --tLCycle <= "011"; ++ tLCycle <= "010"; ++ dbg_LCycle<=14; ++ case to_integer(unsigned(MCycle)) is ++ when 1 => ++ Jump <= "01"; ++ LDDI <= '1'; ++ when 2 => ++ Jump <= "10"; -- DIDL ++ when others => ++ end case; ++ else ++ --tLCycle <= "101"; ++ tLCycle <= "100"; -- mikej ++ dbg_LCycle<=15; ++ case to_integer(unsigned(MCycle)) is ++ when 1 => ++ Jump <= "01"; ++ LDDI <= '1'; ++ LDBAL <= '1'; ++ when 2 => ++ LDBAH <= '1'; ++ if Mode /= "00" then ++ Jump <= "10"; -- DIDL ++ end if; ++ if Mode = "00" then ++ Set_Addr_To <= Set_Addr_To_BA; ++ dbg_Set_Addr_To<=28; ++ end if; ++ when 3 => ++ LDDI <= '1'; ++ if Mode = "00" then ++ Set_Addr_To <= Set_Addr_To_BA; ++ dbg_Set_Addr_To<=29; ++ BAAdd <= "01"; -- DB Inc ++ else ++ Jump <= "01"; ++ end if; ++ when 4 => ++ Jump <= "10"; -- DIDL ++ when others => ++ end case; ++ end if; ++ else ++ tLCycle <= "011"; ++ dbg_LCycle<=16; ++ case to_integer(unsigned(MCycle)) is ++ when 0 => ++ if IR(7 downto 5) = "001" then--2c-BIT ++ SaveP <= '1'; ++ end if; ++ when 1 => ++ Jump <= "01"; ++ LDBAL <= '1'; ++ when 2 => ++ Jump <= "01"; ++ LDBAH <= '1'; ++ if IR(7 downto 5) = "100" then--80, sty, the only write in this group ++ Write <= '1'; ++ end if; ++ Set_Addr_To <= Set_Addr_To_BA; ++ dbg_Set_Addr_To<=30; ++ when 3 => ++ when others => ++ end case; ++ end if; ++ --}}} + +- -- This circuit dictates when the last +- -- microcycle occurs for the branch depending on +- -- whether or not the branch is taken and if a page +- -- is crossed... +- if (Branch = '1') then ++ when "01101" | "01110" | "01111" => ++ --{{{ ++ -- Absolute ++-- if IR(7 downto 6) /= "10" and IR(1 downto 0) = "10" then--0x-7x,cx-fx, x=2,6,a,e ++ if IR(7 downto 6) /= "10" and IR(1) = '1' and (mode="00" or IR(0)='0') then--covers 0x-7x,cx-fx x=2,3,6,7,a,b,e,f, for 6502 undocs ++ -- Read-Modify-Write ++ tLCycle <= "101"; ++ dbg_LCycle<=17; ++ case to_integer(unsigned(MCycle)) is ++ when 1 => ++ Jump <= "01"; ++ LDBAL <= '1'; ++ when 2 => ++ Jump <= "01"; ++ LDBAH <= '1'; ++ Set_Addr_To <= Set_Addr_To_BA; ++ dbg_Set_Addr_To<=31; ++ when 3 => ++ LDDI <= '1'; ++ if Mode="00" then--The old 6500 writes back what is just read, before changing. The 65c does another read ++ Write <= '1'; ++ end if; ++ Set_Addr_To <= Set_Addr_To_BA; ++ dbg_Set_Addr_To<=32; ++ when 4 => ++ Write <= '1'; ++ LDALU <= '1'; ++ SaveP <= '1'; ++ Set_Addr_To <= Set_Addr_To_BA; ++ dbg_Set_Addr_To<=33; ++ when 5 => ++ --SaveP <= '0'; -- MIKEJ was 1 ++ if Mode="00" and IR(0)='1' then ++ tALUmore <= '1';--ML:For undoc DCP/DCM support ++ end if; ++ when 0 => ++ if Mode="00" and IR(0)='1' then ++ SaveP <= '1';--ML:For undoc DCP/DCM support, save again after compare ++ end if; ++ when others => ++ end case; ++ else ++ tLCycle <= "011"; ++ dbg_LCycle<=18; ++ if IR(7 downto 6) /= "10" then ++ LDA <= '1'; ++ if Mode="00" and IR(1)='1' then--b3 ++ LDX <= '1';--undoc, can load both A and X ++ end if; ++ end if; ++ case to_integer(unsigned(MCycle)) is ++ when 0 => ++ when 1 => ++ Jump <= "01"; ++ LDBAL <= '1'; ++ when 2 => ++ Jump <= "01"; ++ LDBAH <= '1'; ++ if IR(7 downto 5) = "100" then ++ Write <= '1'; ++ end if; ++ Set_Addr_To <= Set_Addr_To_BA; ++ dbg_Set_Addr_To<=34; ++ when 3 => ++ when others => ++ end case; ++ end if; ++ --}}} + +- LCycle <= "011"; -- We're done @ T3 if branching...upper +- -- level logic will stop at T2 if no page cross +- -- (See the Break signal) +- else ++ when "10000" => ++ --{{{ ++ -- Relative + +- LCycle <= "001"; ++ -- This circuit dictates when the last ++ -- microcycle occurs for the branch depending on ++ -- whether or not the branch is taken and if a page ++ -- is crossed... ++ if (Branch = '1') then ++ tLCycle <= "011"; -- We're done @ T3 if branching...upper ++ -- level logic will stop at T2 if no page cross ++ -- (See the Break signal) ++ dbg_LCycle<=19; ++ else ++ tLCycle <= "001"; ++ dbg_LCycle<=20; + +- end if; ++ end if; + +- -- This decodes the current microcycle and takes the +- -- proper course of action... +- case to_integer(unsigned(MCycle)) is ++ -- This decodes the current microcycle and takes the ++ -- proper course of action... ++ case to_integer(unsigned(MCycle)) is + +- -- On the T1 microcycle, increment the program counter +- -- and instruct the upper level logic to fetch the offset +- -- from the Din bus and store it in the data latches. This +- -- will be the last microcycle if the branch isn't taken. +- when 1 => ++ -- On the T1 microcycle, increment the program counter ++ -- and instruct the upper level logic to fetch the offset ++ -- from the Din bus and store it in the data latches. This ++ -- will be the last microcycle if the branch isn't taken. ++ when 1 => + +- Jump <= "01"; -- Increments the PC by one (PC will now be PC+2) +- -- from microcycle T0. ++ Jump <= "01"; -- Increments the PC by one (PC will now be PC+2) ++ -- from microcycle T0. + +- LDDI <= '1'; -- Tells logic in top level (T65.vhd) to route +- -- the Din bus to the memory data latch (DL) +- -- so that the branch offset is fetched. ++ LDDI <= '1'; -- Tells logic in top level (T65.vhd) to route ++ -- the Din bus to the memory data latch (DL) ++ -- so that the branch offset is fetched. + +- -- In microcycle T2, tell the logic in the top level to +- -- add the offset. If the most significant byte of the +- -- program counter (i.e. the current "page") does not need +- -- updating, we are done here...the Break signal at the +- -- T65.vhd level takes care of that... +- when 2 => ++ -- In microcycle T2, tell the logic in the top level to ++ -- add the offset. If the most significant byte of the ++ -- program counter (i.e. the current "page") does not need ++ -- updating, we are done here...the Break signal at the ++ -- T65.vhd level takes care of that... ++ when 2 => + +- Jump <= "11"; -- Tell the PC Jump logic to use relative mode. ++ Jump <= "11"; -- Tell the PC Jump logic to use relative mode. + +- PCAdd <= '1'; -- This tells the PC adder to update itself with +- -- the current offset recently fetched from +- -- memory. ++ PCAdd <= '1'; -- This tells the PC adder to update itself with ++ -- the current offset recently fetched from ++ -- memory. + +- -- The following is microcycle T3 : +- -- The program counter should be completely updated +- -- on this cycle after the page cross is detected. +- -- We don't need to do anything here... +- when 3 => ++ -- The following is microcycle T3 : ++ -- The program counter should be completely updated ++ -- on this cycle after the page cross is detected. ++ -- We don't need to do anything here... ++ when 3 => + + +- when others => null; -- Do nothing. ++ when others => null; -- Do nothing. + +- end case; +- --}}} ++ end case; ++ --}}} + +- when "10001" | "10011" => +- --{{{ +- -- Zero Page Indirect Indexed (d),y +- LCycle <= "101"; +- if IR(7 downto 6) /= "10" then +- LDA <= '1'; +- end if; +- case to_integer(unsigned(MCycle)) is +- when 0 => +- when 1 => +- Jump <= "01"; +- LDAD <= '1'; +- Set_Addr_To <= "10"; -- AD +- when 2 => +- LDBAL <= '1'; +- BAAdd <= "01"; -- DB Inc +- Set_Addr_To <= "10"; -- AD +- when 3 => +- Set_BusA_To <= "011"; -- Y +- BAAdd <= "10"; -- BA Add +- LDBAH <= '1'; +- Set_Addr_To <= "11"; -- BA +- when 4 => +- BAAdd <= "11"; -- BA Adj +- if IR(7 downto 5) = "100" then +- Write <= '1'; +- else +- BreakAtNA <= '1'; +- end if; +- Set_Addr_To <= "11"; -- BA +- when 5 => +- when others => +- end case; +- --}}} ++ when "10001" | "10011" => ++ --{{{ ++ -- Zero Page Indirect Indexed (d),y ++ tLCycle <= "101"; ++ dbg_LCycle<=21; ++ if IR(7 downto 6) /= "10" then--91,b1,93,b3 only ++ LDA <= '1'; ++ if Mode="00" and IR(1)='1' then--b3 ++ LDX <= '1';--undoc, can load both A and X ++ end if; ++ end if; ++ case to_integer(unsigned(MCycle)) is ++ when 1 => ++ Jump <= "01"; ++ LDAD <= '1'; ++ Set_Addr_To <= Set_Addr_To_AD; ++ dbg_Set_Addr_To<=35; ++ when 2 => ++ LDBAL <= '1'; ++ BAAdd <= "01"; -- DB Inc ++ Set_Addr_To <= Set_Addr_To_AD; ++ dbg_Set_Addr_To<=36; ++ when 3 => ++ Set_BusA_To <= Set_BusA_To_Y; ++ dbg_Set_BusA_To<=18; ++ BAAdd <= "10"; -- BA Add ++ LDBAH <= '1'; ++ Set_Addr_To <= Set_Addr_To_BA; ++ dbg_Set_Addr_To<=37; ++ when 4 => ++ BAAdd <= "11"; -- BA Adj ++ if IR(7 downto 5) = "100" or IR(1)='1' then ++ Write <= '1'; ++ else ++ BreakAtNA <= '1'; ++ if Mode="00" and IR(1)='1' then ++ tALUmore <= '1';--ML:For undoc ++ end if; ++ end if; ++ Set_Addr_To <= Set_Addr_To_BA; ++ dbg_Set_Addr_To<=38; ++ when 5 => ++ if Mode="00" and IR(1)='1' then ++ tALUmore <= '1';--ML:For undoc ++ end if; ++ when 0 => ++ if Mode="00" and IR(1)='1' then ++ SaveP <= '1';--ML:For undoc ++ end if; ++ when others => ++ end case; ++ --}}} + +- when "10100" | "10101" | "10110" | "10111" => +- --{{{ +- -- Zero Page, X +- if IR(7 downto 6) /= "10" and IR(1 downto 0) = "10" then +- -- Read-Modify-Write +- LCycle <= "101"; +- case to_integer(unsigned(MCycle)) is +- when 1 => +- Jump <= "01"; +- LDAD <= '1'; +- Set_Addr_To <= "10"; -- AD +- when 2 => +- ADAdd <= '1'; +- Set_Addr_To <= "10"; -- AD +- when 3 => +- LDDI <= '1'; +- Write <= '1'; +- Set_Addr_To <= "10"; -- AD +- when 4 => +- LDALU <= '1'; +- SaveP <= '1'; +- Write <= '1'; +- Set_Addr_To <= "10"; -- AD +- when 5 => +- when others => +- end case; +- else +- LCycle <= "011"; +- if IR(7 downto 6) /= "10" then +- LDA <= '1'; +- end if; +- case to_integer(unsigned(MCycle)) is +- when 0 => +- when 1 => +- Jump <= "01"; +- LDAD <= '1'; +- Set_Addr_To <= "10"; -- AD +- when 2 => +- ADAdd <= '1'; +- -- Added this check for Y reg. use... +- if (IR(3 downto 0) = "0110") then +- AddY <= '1'; +- end if; ++ when "10100" | "10101" | "10110" | "10111" => ++ --{{{ ++ -- Zero Page, X ++-- if IR(7 downto 6) /= "10" and IR(1 downto 0) = "10" then--16,36,56,76,d6,f6 ++ if IR(7 downto 6) /= "10" and IR(1) = '1' and (Mode="00" or IR(0)='0') then--covers 0x-7x,cx-fx x=2,3,6,7,a,b,e,f, for 6502 undocs ++ -- Read-Modify-Write ++ if Mode="00" and IR(0)='1' then ++ LDA<='1'; ++ end if; ++ tLCycle <= "101"; ++ dbg_LCycle<=22; ++ case to_integer(unsigned(MCycle)) is ++ when 1 => ++ Jump <= "01"; ++ LDAD <= '1'; ++ Set_Addr_To <= Set_Addr_To_AD; ++ dbg_Set_Addr_To<=39; ++ when 2 => ++ ADAdd <= '1'; ++ Set_Addr_To <= Set_Addr_To_AD; ++ dbg_Set_Addr_To<=40; ++ when 3 => ++ LDDI <= '1'; ++ if Mode="00" then--The old 6500 writes back what is just read, before changing. The 65c does another read ++ Write <= '1'; ++ end if; ++ Set_Addr_To <= Set_Addr_To_AD; ++ dbg_Set_Addr_To<=41; ++ when 4 => ++ LDALU <= '1'; ++ SaveP <= '1'; ++ Write <= '1'; ++ Set_Addr_To <= Set_Addr_To_AD; ++ dbg_Set_Addr_To<=42; ++ when 5 => ++ if Mode="00" and IR(0)='1' then ++ tALUmore <= '1';--ML:For undoc DCP/DCM support ++ end if; ++ when 0 => ++ if Mode="00" and IR(0)='1' then ++ SaveP <= '1';--ML:For undoc DCP/DCM support, save again after compare ++ end if; ++ when others => ++ end case; ++ elsif Mode="00" and IR(7 downto 6)/="10" and IR(4)='1' and IR(1 downto 0)="00" then --covers 1x,3x,5x,7x,dx,fx, for skb/nopzx 6502 undocs ++ tLCycle <= "011";--SKB's at x4 ++ dbg_LCycle<=222; ++ case to_integer(unsigned(MCycle)) is ++ when 1 => ++ Jump <= "01";--skip a byte ++ when others=> ++ end case; ++ else ++ tLCycle <= "011"; ++ dbg_LCycle<=23; ++ if IR(7 downto 6) /= "10" then ++ LDA <= '1'; ++ if Mode="00" and IR(1 downto 0)="11" then--x7 ++ LDX <= '1';--undoc, can load both A and X ++ end if; ++ end if; ++ case to_integer(unsigned(MCycle)) is ++ when 0 => ++ when 1 => ++ Jump <= "01"; ++ LDAD <= '1'; ++ Set_Addr_To <= Set_Addr_To_AD; ++ dbg_Set_Addr_To<=43; ++ when 2 => ++ ADAdd <= '1'; ++ -- Added this check for Y reg. use... ++ if (IR(3 downto 0) = "0110") then--96,b6 ++ AddY <= '1'; ++ end if; + +- if IR(7 downto 5) = "100" then +- Write <= '1'; +- end if; +- Set_Addr_To <= "10"; -- AD +- when 3 => null; +- when others => +- end case; +- end if; +- --}}} ++ if IR(7 downto 5) = "100" then--94,95,96,97 the only write instruction ++ Write <= '1'; ++ end if; ++ Set_Addr_To <= Set_Addr_To_AD; ++ dbg_Set_Addr_To<=44; ++ when 3 => null; ++ when others => ++ end case; ++ end if; ++ --}}} + +- when "11001" | "11011" => +- --{{{ +- -- Absolute Y +- LCycle <= "100"; +- if IR(7 downto 6) /= "10" then +- LDA <= '1'; +- end if; +- case to_integer(unsigned(MCycle)) is +- when 0 => +- when 1 => +- Jump <= "01"; +- LDBAL <= '1'; +- when 2 => +- Jump <= "01"; +- Set_BusA_To <= "011"; -- Y +- BAAdd <= "10"; -- BA Add +- LDBAH <= '1'; +- Set_Addr_To <= "11"; -- BA +- when 3 => +- BAAdd <= "11"; -- BA adj +- if IR(7 downto 5) = "100" then +- Write <= '1'; +- else +- BreakAtNA <= '1'; +- end if; +- Set_Addr_To <= "11"; -- BA +- when 4 => +- when others => +- end case; +- --}}} ++ when "11001" | "11011" => ++ --{{{ ++ -- Absolute Y ++ tLCycle <= "100"; ++ dbg_LCycle<=24; ++ if IR(7 downto 6) /= "10" then ++ LDA <= '1'; ++ if Mode="00" and IR(1 downto 0)="11" then--xb ++ LDX <= '1';--undoc, can load both A and X ++ end if; ++ end if; ++ case to_integer(unsigned(MCycle)) is ++ when 1 => ++ Jump <= "01"; ++ LDBAL <= '1'; ++ when 2 => ++ Jump <= "01"; ++ Set_BusA_To <= Set_BusA_To_Y; ++ dbg_Set_BusA_To<=19; ++ BAAdd <= "10"; -- BA Add ++ LDBAH <= '1'; ++ Set_Addr_To <= Set_Addr_To_BA; ++ dbg_Set_Addr_To<=45; ++ when 3 => ++ BAAdd <= "11"; -- BA adj ++-- if IR(7 downto 5) = "100" then--99/9b ++ if IR(7 downto 5) = "100" or IR(1)='1' then ++ Write <= '1'; ++ else ++ BreakAtNA <= '1'; ++ end if; ++ Set_Addr_To <= Set_Addr_To_BA; ++ dbg_Set_Addr_To<=46; ++ when 4 => ++ if Mode="00" and IR(1)='1' then ++ tALUmore <= '1';--ML:For undoc ++ end if; ++ when 0 => ++ if Mode="00" and IR(1)='1' then ++ SaveP <= '1';--ML:For undoc ++ end if; ++ when others => ++ end case; ++ --}}} + +- when "11100" | "11101" | "11110" | "11111" => +- --{{{ +- -- Absolute X ++ when "11100" | "11101" | "11110" | "11111" => ++ --{{{ ++ -- Absolute X + +- if IR(7 downto 6) /= "10" and IR(1 downto 0) = "10" then +- -- Read-Modify-Write +- LCycle <= "110"; +- case to_integer(unsigned(MCycle)) is +- when 1 => +- Jump <= "01"; +- LDBAL <= '1'; +- when 2 => +- Jump <= "01"; +- Set_BusA_To <= "010"; -- X +- BAAdd <= "10"; -- BA Add +- LDBAH <= '1'; +- Set_Addr_To <= "11"; -- BA +- when 3 => +- BAAdd <= "11"; -- BA adj +- Set_Addr_To <= "11"; -- BA +- when 4 => +- LDDI <= '1'; +- Write <= '1'; +- Set_Addr_To <= "11"; -- BA +- when 5 => +- LDALU <= '1'; +- SaveP <= '1'; +- Write <= '1'; +- Set_Addr_To <= "11"; -- BA +- when 6 => +- when others => +- end case; +- else +- LCycle <= "100"; +- if IR(7 downto 6) /= "10" then +- LDA <= '1'; +- end if; +- case to_integer(unsigned(MCycle)) is +- when 0 => +- when 1 => +- Jump <= "01"; +- LDBAL <= '1'; +- when 2 => +- Jump <= "01"; +- -- mikej +- -- special case 0xBE which uses Y reg as index!! +- if (IR = "10111110") then +- Set_BusA_To <= "011"; -- Y +- else +- Set_BusA_To <= "010"; -- X +- end if; +- BAAdd <= "10"; -- BA Add +- LDBAH <= '1'; +- Set_Addr_To <= "11"; -- BA +- when 3 => +- BAAdd <= "11"; -- BA adj +- if IR(7 downto 5) = "100" then +- Write <= '1'; +- else +- BreakAtNA <= '1'; +- end if; +- Set_Addr_To <= "11"; -- BA +- when 4 => +- when others => +- end case; +- end if; +- --}}} +- when others => +- end case; +- end process; ++-- if IR(7 downto 6) /= "10" and IR(1 downto 0) = "10" then--1x,3x,5x,7x,dx,fx, x=c,d,e,f ++ if IR(7 downto 6) /= "10" and IR(1) = '1' and (Mode="00" or IR(0)='0') then--covers 0x-7x,cx-fx x=2,3,6,7,a,b,e,f, for 6502 undocs ++ -- Read-Modify-Write ++ tLCycle <= "110"; ++ dbg_LCycle<=25; ++ case to_integer(unsigned(MCycle)) is ++ when 1 => ++ Jump <= "01"; ++ LDBAL <= '1'; ++ when 2 => ++ Jump <= "01"; ++ Set_BusA_To <= Set_BusA_To_X; ++ dbg_Set_BusA_To<=20; ++ BAAdd <= "10"; -- BA Add ++ LDBAH <= '1'; ++ Set_Addr_To <= Set_Addr_To_BA; ++ dbg_Set_Addr_To<=47; ++ when 3 => ++ BAAdd <= "11"; -- BA adj ++ Set_Addr_To <= Set_Addr_To_BA; ++ dbg_Set_Addr_To<=48; ++ when 4 => ++ LDDI <= '1'; ++ if Mode="00" then--The old 6500 writes back what is just read, before changing. The 65c does another read ++ Write <= '1'; ++ end if; ++ Set_Addr_To <= Set_Addr_To_BA; ++ dbg_Set_Addr_To<=49; ++ when 5 => ++ LDALU <= '1'; ++ SaveP <= '1'; ++ Write <= '1'; ++ Set_Addr_To <= Set_Addr_To_BA; ++ dbg_Set_Addr_To<=50; ++ when 6 => ++ if Mode="00" and IR(0)='1' then ++ tALUmore <= '1';--ML:For undoc DCP/DCM support ++ end if; ++ when 0 => ++ if Mode="00" and IR(0)='1' then ++ SaveP <= '1';--ML:For undoc DCP/DCM support, save again after compare ++ end if; ++ when others => ++ end case; ++-- elsif Mode="00" and IR(7 downto 6)/="10" and IR(4)='1' and IR(1 downto 0)="00" then --covers 1x,3x,5x,7x,dx,fx, for 6502 skw/nopax undocs ++-- tLCycle <= "100";--SKW's at xc ++-- dbg_LCycle<=260; ++-- case to_integer(unsigned(MCycle)) is ++-- when 1 => ++-- Jump <= "01";--skip a byte ++-- when 2 => ++-- Jump <= "01";--skip a byte ++-- when 3 => ++-- BreakAtNA <= '1'; ++-- when others=> ++-- end case; ++ else--9c,9d,9e,9f,bc,bd,be,bf ++ tLCycle <= "100"; ++ dbg_LCycle<=26; ++ if IR(7 downto 6) /= "10" then ++ if Mode/="00" or IR(4)='0' or IR(1 downto 0)/="00" then --covers 1x,3x,5x,7x,dx,fx, for 6502 skw/nopax undocs ++ LDA <= '1'; ++ if Mode="00" and IR(1 downto 0)="11" then--9f,bf ++ LDX <= '1';--undoc, can load both A and X ++ end if; ++ end if; ++ end if; ++ case to_integer(unsigned(MCycle)) is ++ when 0 => ++ when 1 => ++ Jump <= "01"; ++ LDBAL <= '1'; ++ when 2 => ++ Jump <= "01"; ++ -- mikej ++ -- special case 0xBE which uses Y reg as index!! (added undoc 9e,9f,bf) ++-- if (IR = "10-1111-") then ++ if(IR(7 downto 6)="10" and IR(4 downto 1)="1111") then ++ Set_BusA_To <= Set_BusA_To_Y; ++ dbg_Set_BusA_To<=21; ++ else ++ Set_BusA_To <= Set_BusA_To_X; ++ dbg_Set_BusA_To<=22; ++ end if; ++ BAAdd <= "10"; -- BA Add ++ LDBAH <= '1'; ++ Set_Addr_To <= Set_Addr_To_BA; ++ dbg_Set_Addr_To<=51; ++ when 3 => ++ BAAdd <= "11"; -- BA adj ++ if IR(7 downto 5) = "100" then--9x ++ Write <= '1'; ++ else ++ BreakAtNA <= '1'; ++ end if; ++ Set_Addr_To <= Set_Addr_To_BA; ++ dbg_Set_Addr_To<=52; ++ when 4 => ++ when others => ++ end case; ++ end if; ++ --}}} ++ when others => ++ end case; ++ end process; + +- process (IR, MCycle) +- begin +- -- ORA, AND, EOR, ADC, NOP, LD, CMP, SBC +- -- ASL, ROL, LSR, ROR, BIT, LD, DEC, INC +- case IR(1 downto 0) is +- when "00" => +- --{{{ +- case IR(4 downto 2) is +- when "000" | "001" | "011" => +- case IR(7 downto 5) is +- when "110" | "111" => +- -- CP +- ALU_Op <= "0110"; +- when "101" => +- -- LD +- ALU_Op <= "0101"; +- when "001" => +- -- BIT +- ALU_Op <= "1100"; +- when others => +- -- NOP/ST +- ALU_Op <= "0100"; +- end case; +- when "010" => +- case IR(7 downto 5) is +- when "111" | "110" => +- -- IN +- ALU_Op <= "1111"; +- when "100" => +- -- DEY +- ALU_Op <= "1110"; +- when others => +- -- LD +- ALU_Op <= "1101"; +- end case; +- when "110" => +- case IR(7 downto 5) is +- when "100" => +- -- TYA +- ALU_Op <= "1101"; +- when others => +- ALU_Op <= "----"; +- end case; +- when others => +- case IR(7 downto 5) is +- when "101" => +- -- LD +- ALU_Op <= "1101"; +- when others => +- ALU_Op <= "0100"; +- end case; +- end case; +- --}}} +- when "01" => -- OR +- --{{{ +- ALU_Op(3) <= '0'; +- ALU_Op(2 downto 0) <= IR(7 downto 5); +- --}}} +- when "10" => +- --{{{ +- ALU_Op(3) <= '1'; +- ALU_Op(2 downto 0) <= IR(7 downto 5); +- case IR(7 downto 5) is +- when "000" => +- if IR(4 downto 2) = "110" then +- -- INC +- ALU_Op <= "1111"; +- end if; +- when "001" => +- if IR(4 downto 2) = "110" then +- -- DEC +- ALU_Op <= "1110"; +- end if; +- when "100" => +- if IR(4 downto 2) = "010" then +- -- TXA +- ALU_Op <= "0101"; +- else +- ALU_Op <= "0100"; +- end if; +- when others => +- end case; +- --}}} +- when others => +- --{{{ +- case IR(7 downto 5) is +- when "100" => +- ALU_Op <= "0100"; +- when others => +- if MCycle = "000" then +- ALU_Op(3) <= '0'; +- ALU_Op(2 downto 0) <= IR(7 downto 5); +- else +- ALU_Op(3) <= '1'; +- ALU_Op(2 downto 0) <= IR(7 downto 5); +- end if; +- end case; +- --}}} +- end case; +- end process; ++ process (IR, MCycle, Mode,tALUmore) ++ begin ++ -- ORA, AND, EOR, ADC, NOP, LD, CMP, SBC ++ -- ASL, ROL, LSR, ROR, BIT, LD, DEC, INC ++ case IR(1 downto 0) is ++ when "00" => ++ --{{{ ++ case IR(4 downto 2) is ++ when "000" | "001" | "011" =>-- "---0 xx00", xx!="10" ++ case IR(7 downto 5) is ++ when "110" | "111" =>--c0,c4,cc,e0,e5,ec ++ -- CP ++ ALU_Op <= ALU_OP_CMP; ++ when "101" =>--a0,a4,ac ++ -- LD ++ ALU_Op <= ALU_OP_EQ2; ++ when "001" =>--20,24,2c (20 is ignored, as its a jmp) ++ -- BIT ++ ALU_Op <= ALU_OP_BIT; ++ when others =>--other x0,x4,xc ++ -- NOP/ST ++ ALU_Op <= ALU_OP_EQ1; ++ end case; ++ when "010" =>-- "---0 1000" ++ case IR(7 downto 5) is ++ when "111" | "110" =>--c8,e8 ++ -- IN ++ ALU_Op <= ALU_OP_INC; ++ when "100" =>--88 ++ -- DEY ++ ALU_Op <= ALU_OP_DEC; ++ when others => ++ -- LD ++ ALU_Op <= ALU_OP_EQ3; ++ end case; ++ when "110" =>-- "---1 1000" ++ case IR(7 downto 5) is ++ when "100" =>--98 ++ -- TYA ++ ALU_Op <= ALU_OP_EQ3; ++ when others => ++ ALU_Op <= ALU_OP_UNDEF; ++ end case; ++ when others =>-- "---x xx00" ++ case IR(7 downto 5) is ++ when "101" =>--ax,bx ++ -- LD ++ ALU_Op <= ALU_OP_EQ3; ++ when others => ++ ALU_Op <= ALU_OP_EQ1; ++ end case; ++ end case; ++ --}}} ++ when "01" => -- OR ++ --{{{ ++ case(to_integer(unsigned(IR(7 downto 5)))) is ++ when 0=> ++ ALU_Op<=ALU_OP_OR; ++ when 1=> ++ ALU_Op<=ALU_OP_AND; ++ when 2=> ++ ALU_Op<=ALU_OP_EOR; ++ when 3=> ++ ALU_Op<=ALU_OP_ADC; ++ when 4=> ++ ALU_Op<=ALU_OP_EQ1;--sta ++ when 5=> ++ ALU_Op<=ALU_OP_EQ2;--lda ++ when 6=> ++ ALU_Op<=ALU_OP_CMP; ++ when others=> ++ ALU_Op<=ALU_OP_SBC; ++ end case; ++--ML:replaced by above case() ++-- ALU_Op(3) <= '0'; ++-- ALU_Op(2 downto 0) <= IR(7 downto 5); ++ --}}} ++ when "10" => ++ --{{{ ++ case(to_integer(unsigned(IR(7 downto 5)))) is ++ when 0=> ++ ALU_Op<=ALU_OP_ASL; ++ when 1=> ++ ALU_Op<=ALU_OP_ROL; ++ when 2=> ++ ALU_Op<=ALU_OP_LSR; ++ when 3=> ++ ALU_Op<=ALU_OP_ROR; ++ when 4=> ++ ALU_Op<=ALU_OP_BIT; ++ when 5=> ++ ALU_Op<=ALU_OP_EQ3;--ldx ++ when 6=> ++ ALU_Op<=ALU_OP_DEC; ++ when others=> ++ ALU_Op<=ALU_OP_INC; ++ end case; ++--ML:replaced by above case() ++-- ALU_Op(3) <= '1'; ++-- ALU_Op(2 downto 0) <= IR(7 downto 5); ++ case IR(7 downto 5) is ++ when "000" => ++ if IR(4 downto 2) = "110" and Mode/="00" then--ML:00011010,1a->inc acc, not on 6502 ++ -- INC ++ ALU_Op <= ALU_OP_INC; ++ end if; ++ when "001" => ++ if IR(4 downto 2) = "110" and Mode/="00" then--ML:00111010,3a->dec acc, not on 6502 ++ -- DEC ++ ALU_Op <= ALU_OP_DEC; ++ end if; ++ when "100" => ++ if IR(4 downto 2) = "010" then --10001010,8a->TXA ++ -- TXA ++ ALU_Op <= ALU_OP_EQ2; ++ else --100xxx10, 82,86,8e,92,96,9a,9e ++ ALU_Op <= ALU_OP_EQ1; ++ end if; ++ when others => ++ end case; ++ --}}} ++ when others =>--"11" undoc double alu ops ++ --{{{ ++ case IR(7 downto 5) is ++ when "101" =>--ax,bx ++ ALU_Op <= ALU_OP_EQ1; ++ when others => ++-- if MCycle >= tLCycle then ++ if tALUmore='1' then ++ case(to_integer(unsigned(IR(7 downto 5)))) is ++ when 0=> ++ ALU_Op<=ALU_OP_OR; ++ when 1=> ++ ALU_Op<=ALU_OP_AND; ++ when 2=> ++ ALU_Op<=ALU_OP_EOR; ++ when 3=> ++ ALU_Op<=ALU_OP_ADC; ++ when 4=> ++ ALU_Op<=ALU_OP_EQ1;--sta ++ when 5=> ++ ALU_Op<=ALU_OP_EQ2;--lda ++ when 6=> ++ ALU_Op<=ALU_OP_CMP; ++ when others=> ++ ALU_Op<=ALU_OP_SBC; ++ end case; ++--replaced by above case() ++-- ALU_Op(3) <= '0'; ++-- ALU_Op(2 downto 0) <= IR(7 downto 5); ++ else ++ case(to_integer(unsigned(IR(7 downto 5)))) is ++ when 0=> ++ ALU_Op<=ALU_OP_ASL; ++ when 1=> ++ ALU_Op<=ALU_OP_ROL; ++ when 2=> ++ ALU_Op<=ALU_OP_LSR; ++ when 3=> ++ ALU_Op<=ALU_OP_ROR; ++ when 4=> ++ ALU_Op<=ALU_OP_BIT; ++ when 5=> ++ ALU_Op<=ALU_OP_EQ3;--ldx ++ when 6=> ++ ALU_Op<=ALU_OP_DEC; ++ when others=> ++ ALU_Op<=ALU_OP_INC; ++ end case; ++--replaced by above case() ++-- ALU_Op(3) <= '1'; ++-- ALU_Op(2 downto 0) <= IR(7 downto 5); ++ end if; ++ end case; ++ --}}} ++ end case; ++ end process; + + end; +diff --git a/T65/T65_Pack.vhd b/T65/T65_Pack.vhd +index e025e1b..1c9178d 100644 +--- a/T65/T65_Pack.vhd ++++ b/T65/T65_Pack.vhd +@@ -2,6 +2,8 @@ + -- T65(b) core. In an effort to merge and maintain bug fixes .... + -- + -- ++-- Ver 303 ost(ML) July 2014 ++-- "magic" constants converted to vhdl types + -- Ver 300 Bugfixes by ehenciak added + -- MikeJ March 2005 + -- Latest version from www.fpgaarcade.com (original www.opencores.org) +@@ -59,59 +61,110 @@ use IEEE.std_logic_1164.all; + + package T65_Pack is + +- constant Flag_C : integer := 0; +- constant Flag_Z : integer := 1; +- constant Flag_I : integer := 2; +- constant Flag_D : integer := 3; +- constant Flag_B : integer := 4; +- constant Flag_1 : integer := 5; +- constant Flag_V : integer := 6; +- constant Flag_N : integer := 7; ++ constant Flag_C : integer := 0; ++ constant Flag_Z : integer := 1; ++ constant Flag_I : integer := 2; ++ constant Flag_D : integer := 3; ++ constant Flag_B : integer := 4; ++ constant Flag_1 : integer := 5; ++ constant Flag_V : integer := 6; ++ constant Flag_N : integer := 7; + +- component T65_MCode +- port( +- Mode : in std_logic_vector(1 downto 0); -- "00" => 6502, "01" => 65C02, "10" => 65816 +- IR : in std_logic_vector(7 downto 0); +- MCycle : in std_logic_vector(2 downto 0); +- P : in std_logic_vector(7 downto 0); +- LCycle : out std_logic_vector(2 downto 0); +- ALU_Op : out std_logic_vector(3 downto 0); +- Set_BusA_To : out std_logic_vector(2 downto 0); -- DI,A,X,Y,S,P +- Set_Addr_To : out std_logic_vector(1 downto 0); -- PC Adder,S,AD,BA +- Write_Data : out std_logic_vector(2 downto 0); -- DL,A,X,Y,S,P,PCL,PCH +- Jump : out std_logic_vector(1 downto 0); -- PC,++,DIDL,Rel +- BAAdd : out std_logic_vector(1 downto 0); -- None,DB Inc,BA Add,BA Adj +- BreakAtNA : out std_logic; +- ADAdd : out std_logic; +- AddY : out std_logic; +- PCAdd : out std_logic; +- Inc_S : out std_logic; +- Dec_S : out std_logic; +- LDA : out std_logic; +- LDP : out std_logic; +- LDX : out std_logic; +- LDY : out std_logic; +- LDS : out std_logic; +- LDDI : out std_logic; +- LDALU : out std_logic; +- LDAD : out std_logic; +- LDBAL : out std_logic; +- LDBAH : out std_logic; +- SaveP : out std_logic; +- Write : out std_logic +- ); +- end component; ++ type T_Set_BusA_To is ++ ( ++ Set_BusA_To_DI, ++ Set_BusA_To_ABC, ++ Set_BusA_To_X, ++ Set_BusA_To_Y, ++ Set_BusA_To_S, ++ Set_BusA_To_P, ++ Set_BusA_To_DONTCARE ++ ); ++ type T_Set_Addr_To is ++ ( ++ Set_Addr_To_S, ++ Set_Addr_To_AD, ++ Set_Addr_To_PBR, ++ Set_Addr_To_BA ++ ); ++ type T_Write_Data is ++ ( ++ Write_Data_DL, ++ Write_Data_ABC, ++ Write_Data_X, ++ Write_Data_Y, ++ Write_Data_S, ++ Write_Data_P, ++ Write_Data_PCL, ++ Write_Data_PCH, ++ Write_Data_DONTCARE ++ ); ++ type T_ALU_OP is ++ ( ++ ALU_OP_OR, --"0000" ++ ALU_OP_AND, --"0001" ++ ALU_OP_EOR, --"0010" ++ ALU_OP_ADC, --"0011" ++ ALU_OP_EQ1, --"0100" EQ1 does not change N,Z flags, EQ2/3 does. ++ ALU_OP_EQ2, --"0101"Not sure yet whats the difference between EQ2&3. They seem to do the same ALU op ++ ALU_OP_CMP, --"0110" ++ ALU_OP_SBC, --"0111" ++ ALU_OP_ASL, --"1000" ++ ALU_OP_ROL, --"1001" ++ ALU_OP_LSR, --"1010" ++ ALU_OP_ROR, --"1011" ++ ALU_OP_BIT, --"1100" ++ ALU_OP_EQ3, --"1101" ++ ALU_OP_DEC, --"1110" ++ ALU_OP_INC, --"1111" ++ ALU_OP_UNDEF--"----"--may be replaced with any? ++ ); + +- component T65_ALU +- port( +- Mode : in std_logic_vector(1 downto 0); -- "00" => 6502, "01" => 65C02, "10" => 65C816 +- Op : in std_logic_vector(3 downto 0); +- BusA : in std_logic_vector(7 downto 0); +- BusB : in std_logic_vector(7 downto 0); +- P_In : in std_logic_vector(7 downto 0); +- P_Out : out std_logic_vector(7 downto 0); +- Q : out std_logic_vector(7 downto 0) +- ); +- end component; ++ component T65_MCode ++ port( ++ Mode : in std_logic_vector(1 downto 0); -- "00" => 6502, "01" => 65C02, "10" => 65816 ++ IR : in std_logic_vector(7 downto 0); ++ MCycle : in std_logic_vector(2 downto 0); ++ P : in std_logic_vector(7 downto 0); ++ LCycle : out std_logic_vector(2 downto 0); ++ ALU_Op : out T_ALU_Op; ++ Set_BusA_To : out T_Set_BusA_To;-- DI,A,X,Y,S,P ++ Set_Addr_To : out T_Set_Addr_To;-- PC Adder,S,AD,BA ++ Write_Data : out T_Write_Data;-- DL,A,X,Y,S,P,PCL,PCH ++ Jump : out std_logic_vector(1 downto 0); -- PC,++,DIDL,Rel ++ BAAdd : out std_logic_vector(1 downto 0); -- None,DB Inc,BA Add,BA Adj ++ BreakAtNA : out std_logic; ++ ADAdd : out std_logic; ++ AddY : out std_logic; ++ PCAdd : out std_logic; ++ Inc_S : out std_logic; ++ Dec_S : out std_logic; ++ LDA : out std_logic; ++ LDP : out std_logic; ++ LDX : out std_logic; ++ LDY : out std_logic; ++ LDS : out std_logic; ++ LDDI : out std_logic; ++ LDALU : out std_logic; ++ LDAD : out std_logic; ++ LDBAL : out std_logic; ++ LDBAH : out std_logic; ++ SaveP : out std_logic; ++ ALUmore : out std_logic; ++ Write : out std_logic ++ ); ++ end component; ++ ++ component T65_ALU ++ port( ++ Mode : in std_logic_vector(1 downto 0); -- "00" => 6502, "01" => 65C02, "10" => 65C816 ++ Op : in T_ALU_Op; ++ BusA : in std_logic_vector(7 downto 0); ++ BusB : in std_logic_vector(7 downto 0); ++ P_In : in std_logic_vector(7 downto 0); ++ P_Out : out std_logic_vector(7 downto 0); ++ Q : out std_logic_vector(7 downto 0) ++ ); ++ end component; + + end; -- cgit v1.2.3