📄 t65_mcode.vhd
字号:
-- ****
-- T65(b) core. In an effort to merge and maintain bug fixes ....
--
--
-- Ver 301 Jump timing fixed
-- Ver 300 Bugfixes by ehenciak added
-- MikeJ March 2005
-- Latest version from www.fpgaarcade.com (original www.opencores.org)
--
-- ****
--
-- 65xx compatible microprocessor core
--
-- Version : 0246 + fix
--
-- Copyright (c) 2002 Daniel Wallner (jesus@opencores.org)
--
-- All rights reserved
--
-- Redistribution and use in source and synthezised forms, with or without
-- modification, are permitted provided that the following conditions are met:
--
-- Redistributions of source code must retain the above copyright notice,
-- this list of conditions and the following disclaimer.
--
-- Redistributions in synthesized form must reproduce the above copyright
-- notice, this list of conditions and the following disclaimer in the
-- documentation and/or other materials provided with the distribution.
--
-- Neither the name of the author nor the names of other contributors may
-- be used to endorse or promote products derived from this software without
-- specific prior written permission.
--
-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-- POSSIBILITY OF SUCH DAMAGE.
--
-- Please report bugs to the author, but before you do so, please
-- make sure that this is not a derivative work and that
-- you have the latest version of this file.
--
-- The latest version of this file can be found at:
-- http://www.opencores.org/cvsweb.shtml/t65/
--
-- Limitations :
--
-- 65C02
-- supported : inc, dec, phx, plx, phy, ply
-- missing : bra, ora, lda, cmp, sbc, tsb*2, trb*2, stz*2, bit*2, wai, stp, jmp, bbr*8, bbs*8
--
-- File history :
--
-- 0246 : First release
--
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.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); -- instruction opcode
MCycle : in std_logic_vector(2 downto 0); -- number of cycles executed for the current instruction
P : in std_logic_vector(7 downto 0); -- processor status
LCycle : out std_logic_vector(2 downto 0); -- number of cycles instruction requires on original 6502
ALU_Op : out std_logic_vector(3 downto 0); -- specifies ALU operation to perform
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 T65_MCode;
architecture rtl of T65_MCode is
signal Branch : std_logic;
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;
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';
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;
if IR(7 downto 6) /= "10" and IR(1 downto 0) = "10" then
Set_BusA_To <= "000"; -- DI
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;
-- 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 "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 "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";
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -