📄 cpu65xx_fast.vhd
字号:
end if;
when others =>
null;
end case;
if (opcInfo(aluMode1From to aluMode1To) = aluModeBit)
or (opcInfo(aluMode1From to aluMode1To) = aluModeFlg) then
varN := rmwBits(7);
else
varN := nineBits(7);
end if;
varC := ninebits(8);
if opcInfo(aluMode2From to aluMode2To) = aluModeArr then
varC := aluInput(7);
varV := aluInput(7) xor aluInput(6);
end if;
case opcInfo(aluMode2From to aluMode2To) is
when aluModeAdc =>
-- decimal mode high bits correction, is done after setting Z and N flags
varV := (A(7) xor ninebits(7)) and (rmwBits(7) xor ninebits(7));
if D = '1' then
if ninebits(8 downto 4) > 9 then
ninebits(8 downto 4) := ninebits(8 downto 4) + 6;
varC := '1';
end if;
end if;
when aluModeSbc =>
varV := (A(7) xor ninebits(7)) and ((not rmwBits(7)) xor ninebits(7));
if D = '1' then
-- Check for borrow (lower 4 bits)
if lowBits(5) = '0' then
ninebits(3 downto 0) := ninebits(3 downto 0) - 6;
end if;
-- Check for borrow (upper 4 bits)
if ninebits(8) = '0' then
ninebits(8 downto 4) := ninebits(8 downto 4) - 6;
end if;
end if;
when aluModeArr =>
if D = '1' then
if (("0" & aluInput(3 downto 0)) + ("0000" & aluInput(0))) > 5 then
ninebits(3 downto 0) := ninebits(3 downto 0) + 6;
end if;
if (("0" & aluInput(7 downto 4)) + ("0000" & aluInput(4))) > 5 then
ninebits(8 downto 4) := ninebits(8 downto 4) + 6;
varC := '1';
else
varC := '0';
end if;
end if;
when others =>
null;
end case;
if rising_edge(clk) then
aluRmwReg <= rmwBits(7 downto 0);
aluNineReg <= ninebits(7 downto 0);
aluCReg <= varC;
aluZReg <= varZ;
aluVReg <= varV;
aluNReg <= varN;
end if;
aluRmwOut <= rmwBits(7 downto 0);
aluRegisterOut <= ninebits(7 downto 0);
aluC <= varC;
aluZ <= varZ;
aluV <= varV;
aluN <= varN;
if pipelineAluOut then
aluRmwOut <= aluRmwReg;
aluRegisterOut <= aluNineReg;
aluC <= aluCReg;
aluZ <= aluZReg;
aluV <= aluVReg;
aluN <= aluNReg;
end if;
end process;
calcInterrupt: process(clk)
begin
if rising_edge(clk) then
if enable = '1' then
if theCpuCycle = cycleStack4
or reset = '1' then
nmiReg <= '1';
end if;
if nextCpuCycle /= cycleBranchTaken
and nextCpuCycle /= opcodeFetch then
irqReg <= irq_n;
nmiEdge <= nmi_n;
if (nmiEdge = '1') and (nmi_n = '0') then
nmiReg <= '0';
end if;
end if;
-- The 'or opcInfo(opcSetI)' prevents NMI immediately after BRK or IRQ.
-- Presumably this is done in the real 6502/6510 to prevent a double IRQ.
processIrq <= not ((nmiReg and (irqReg or I)) or opcInfo(opcIRQ));
end if;
end if;
end process;
calcNextOpcode: process(clk, di, reset, processIrq)
variable myNextOpcode : unsigned(7 downto 0);
begin
-- Next opcode is read from input unless a reset or IRQ is pending.
myNextOpcode := di;
if reset = '1' then
myNextOpcode := X"4C";
elsif processIrq = '1' then
myNextOpcode := X"00";
end if;
nextOpcode <= myNextOpcode;
end process;
nextOpcInfo <= opcodeInfoTable(to_integer(nextOpcode));
process(clk)
begin
if rising_edge(clk) then
nextOpcInfoReg <= nextOpcInfo;
end if;
end process;
-- Read bits and flags from opcodeInfoTable and store in opcInfo.
-- This info is used to control the execution of the opcode.
calcOpcInfo: process(clk)
begin
if rising_edge(clk) then
if enable = '1' then
if (reset = '1') or (theCpuCycle = opcodeFetch) then
opcInfo <= nextOpcInfo;
if pipelineOpcode then
opcInfo <= nextOpcInfoReg;
end if;
end if;
end if;
end if;
end process;
calcTheOpcode: process(clk)
begin
if rising_edge(clk) then
if enable = '1' then
if theCpuCycle = opcodeFetch then
irqActive <= '0';
if processIrq = '1' then
irqActive <= '1';
end if;
-- Fetch opcode
theOpcode <= nextOpcode;
end if;
end if;
end if;
end process;
-- -----------------------------------------------------------------------
-- State machine
-- -----------------------------------------------------------------------
process(enable, theCpuCycle, opcInfo)
begin
updateRegisters <= false;
if enable = '1' then
if opcInfo(opcRti) = '1' then
if theCpuCycle = cycleRead then
updateRegisters <= true;
end if;
elsif theCpuCycle = opcodeFetch then
updateRegisters <= true;
end if;
end if;
end process;
debugOpcode <= theOpcode;
process(clk)
begin
if rising_edge(clk) then
if enable = '1' then
theCpuCycle <= nextCpuCycle;
end if;
if reset = '1' then
theCpuCycle <= cycle2;
end if;
end if;
end process;
-- Determine the next cpu cycle. After the last cycle we always
-- go to opcodeFetch to get the next opcode.
calcNextCpuCycle: process(theCpuCycle, opcInfo, theOpcode, indexOut, T, N, V, C, Z)
begin
nextCpuCycle <= opcodeFetch;
case theCpuCycle is
when opcodeFetch =>
nextCpuCycle <= cycle2;
when cycle2 =>
if opcInfo(opcBranch) = '1' then
if (N = theOpcode(5) and theOpcode(7 downto 6) = "00")
or (V = theOpcode(5) and theOpcode(7 downto 6) = "01")
or (C = theOpcode(5) and theOpcode(7 downto 6) = "10")
or (Z = theOpcode(5) and theOpcode(7 downto 6) = "11") then
-- Branch condition is true
nextCpuCycle <= cycleBranchTaken;
end if;
elsif (opcInfo(opcStackUp) = '1') then
nextCpuCycle <= cycleStack1;
elsif opcInfo(opcStackAddr) = '1'
and opcInfo(opcStackData) = '1' then
nextCpuCycle <= cycleStack2;
elsif opcInfo(opcStackAddr) = '1' then
nextCpuCycle <= cycleStack1;
elsif opcInfo(opcStackData) = '1' then
nextCpuCycle <= cycleWrite;
elsif opcInfo(opcAbsolute) = '1' then
nextCpuCycle <= cycle3;
elsif opcInfo(opcIndirect) = '1' then
if opcInfo(indexX) = '1' then
nextCpuCycle <= cyclePreIndirect;
else
nextCpuCycle <= cycleIndirect;
end if;
elsif opcInfo(opcZeroPage) = '1' then
if opcInfo(opcWrite) = '1' then
if (opcInfo(indexX) = '1')
or (opcInfo(indexY) = '1') then
nextCpuCycle <= cyclePreWrite;
else
nextCpuCycle <= cycleWrite;
end if;
else
if (opcInfo(indexX) = '1')
or (opcInfo(indexY) = '1') then
nextCpuCycle <= cyclePreRead;
else
nextCpuCycle <= cycleRead2;
end if;
end if;
elsif opcInfo(opcJump) = '1' then
nextCpuCycle <= cycleJump;
end if;
when cycle3 =>
nextCpuCycle <= cycleRead;
if opcInfo(opcWrite) = '1' then
if (opcInfo(indexX) = '1')
or (opcInfo(indexY) = '1') then
nextCpuCycle <= cyclePreWrite;
else
nextCpuCycle <= cycleWrite;
end if;
end if;
if (opcInfo(opcIndirect) = '1')
and (opcInfo(indexX) = '1') then
if opcInfo(opcWrite) = '1' then
nextCpuCycle <= cycleWrite;
else
nextCpuCycle <= cycleRead2;
end if;
end if;
when cyclePreIndirect =>
nextCpuCycle <= cycleIndirect;
when cycleIndirect =>
nextCpuCycle <= cycle3;
when cycleBranchTaken =>
if indexOut(8) /= T(7) then
-- Page boundary crossing during branch.
nextCpuCycle <= cycleBranchPage;
end if;
when cyclePreRead =>
if opcInfo(opcZeroPage) = '1' then
nextCpuCycle <= cycleRead2;
end if;
when cycleRead =>
if opcInfo(opcJump) = '1' then
nextCpuCycle <= cycleJump;
elsif indexOut(8) = '1' then
-- Page boundary crossing while indexed addressing.
nextCpuCycle <= cycleRead2;
elsif opcInfo(opcRmw) = '1' then
nextCpuCycle <= cycleRmw;
if opcInfo(indexX) = '1'
or opcInfo(indexY) = '1' then
-- 6510 needs extra cycle for indexed addressing
-- combined with RMW indexing
nextCpuCycle <= cycleRead2;
end if;
end if;
when cycleRead2 =>
if opcInfo(opcRmw) = '1' then
nextCpuCycle <= cycleRmw;
end if;
when cycleRmw =>
nextCpuCycle <= cycleWrite;
when cyclePreWrite =>
nextCpuCycle <= cycleWrite;
when cycleStack1 =>
nextCpuCycle <= cycleRead;
if opcInfo(opcStackAddr) = '1' then
nextCpuCycle <= cycleStack2;
end if;
when cycleStack2 =>
nextCpuCycle <= cycleStack3;
if opcInfo(opcRti) = '1' then
nextCpuCycle <= cycleRead;
end if;
if opcInfo(opcStackData) = '0'
and opcInfo(opcStackUp) = '1' then
nextCpuCycle <= cycleJump;
end if;
when cycleStack3 =>
nextCpuCycle <= cycleRead;
if opcInfo(opcStackData) = '0'
or opcInfo(opcStackUp) = '1' then
nextCpuCycle <= cycleJump;
elsif opcInfo(opcStackAddr) = '1' then
nextCpuCycle <= cycleStack4;
end if;
when cycleStack4 =>
nextCpuCycle <= cycleRead;
when cycleJump =>
if opcInfo(opcIncrAfter) = '1' then
-- Insert extra cycle
nextCpuCycle <= cycleEnd;
end if;
when others =>
null;
end case;
end process;
-- -----------------------------------------------------------------------
-- T register
-- -----------------------------------------------------------------------
calcT: process(clk)
begin
if rising_edge(clk) then
if enable = '1' then
case theCpuCycle is
when cycle2 =>
T <= di;
when cycleStack1 | cycleStack2 =>
if opcInfo(opcStackUp) = '1' then
-- Read from stack
T <= di;
end if;
when cycleIndirect | cycleRead | cycleRead2 =>
T <= di;
when others =>
null;
end case;
end if;
end if;
end process;
-- -----------------------------------------------------------------------
-- A register
-- -----------------------------------------------------------------------
process(clk)
begin
if rising_edge(clk) then
if updateRegisters then
if opcInfo(opcUpdateA) = '1' then
A <= aluRegisterOut;
end if;
end if;
end if;
end process;
-- -----------------------------------------------------------------------
-- X register
-- -----------------------------------------------------------------------
process(clk)
begin
if rising_edge(clk) then
if updateRegisters then
if opcInfo(opcUpdateX) = '1' then
X <= aluRegisterOut;
end if;
end if;
end if;
end process;
-- -----------------------------------------------------------------------
-- Y register
-- -----------------------------------------------------------------------
process(clk)
begin
if rising_edge(clk) then
if updateRegisters then
if opcInfo(opcUpdateY) = '1' then
Y <= aluRegisterOut;
end if;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -