📄 cpu65xx_fast.vhd
字号:
end if;
end if;
end process;
-- -----------------------------------------------------------------------
-- C flag
-- -----------------------------------------------------------------------
process(clk)
begin
if rising_edge(clk) then
if updateRegisters then
if opcInfo(opcUpdateC) = '1' then
C <= aluC;
end if;
end if;
end if;
end process;
-- -----------------------------------------------------------------------
-- Z flag
-- -----------------------------------------------------------------------
process(clk)
begin
if rising_edge(clk) then
if updateRegisters then
if opcInfo(opcUpdateZ) = '1' then
Z <= aluZ;
end if;
end if;
end if;
end process;
-- -----------------------------------------------------------------------
-- I flag
-- -----------------------------------------------------------------------
process(clk)
begin
if rising_edge(clk) then
if updateRegisters then
if opcInfo(opcUpdateI) = '1' then
I <= aluInput(2);
end if;
end if;
end if;
end process;
-- -----------------------------------------------------------------------
-- D flag
-- -----------------------------------------------------------------------
process(clk)
begin
if rising_edge(clk) then
if updateRegisters then
if opcInfo(opcUpdateD) = '1' then
D <= aluInput(3);
end if;
end if;
end if;
end process;
-- -----------------------------------------------------------------------
-- V flag
-- -----------------------------------------------------------------------
process(clk)
begin
if rising_edge(clk) then
if updateRegisters then
if opcInfo(opcUpdateV) = '1' then
V <= aluV;
end if;
end if;
if enable = '1' then
if soReg = '1' and so_n = '0' then
V <= '1';
end if;
soReg <= so_n;
end if;
end if;
end process;
-- -----------------------------------------------------------------------
-- N flag
-- -----------------------------------------------------------------------
process(clk)
begin
if rising_edge(clk) then
if updateRegisters then
if opcInfo(opcUpdateN) = '1' then
N <= aluN;
end if;
end if;
end if;
end process;
-- -----------------------------------------------------------------------
-- Stack pointer
-- -----------------------------------------------------------------------
process(clk)
variable sIncDec : unsigned(7 downto 0);
variable updateFlag : boolean;
begin
if rising_edge(clk) then
if opcInfo(opcStackUp) = '1' then
sIncDec := S + 1;
else
sIncDec := S - 1;
end if;
if enable = '1' then
updateFlag := false;
case nextCpuCycle is
when cycleStack1 =>
if (opcInfo(opcStackUp) = '1')
or (opcInfo(opcStackData) = '1') then
updateFlag := true;
end if;
when cycleStack2 =>
updateFlag := true;
when cycleStack3 =>
updateFlag := true;
when cycleStack4 =>
updateFlag := true;
when cycleRead =>
if opcInfo(opcRti) = '1' then
updateFlag := true;
end if;
when cycleWrite =>
if opcInfo(opcStackData) = '1' then
updateFlag := true;
end if;
when others =>
null;
end case;
if updateFlag then
S <= sIncDec;
end if;
end if;
if updateRegisters then
if opcInfo(opcUpdateS) = '1' then
S <= aluRegisterOut;
end if;
end if;
end if;
end process;
-- -----------------------------------------------------------------------
-- Data out
-- -----------------------------------------------------------------------
--calcDo: process(cpuNo, theCpuCycle, aluOut, PC, T)
calcDo: process(clk)
begin
if rising_edge(clk) then
if enable = '1' then
doReg <= aluRmwOut;
if opcInfo(opcInH) = '1' then
-- For illegal opcodes SHA, SHX, SHY, SHS
doReg <= aluRmwOut and myAddrIncrH;
end if;
case nextCpuCycle is
when cycleStack2 =>
if opcInfo(opcIRQ) = '1'
and irqActive = '0' then
doReg <= myAddrIncr(15 downto 8);
else
doReg <= PC(15 downto 8);
end if;
when cycleStack3 =>
doReg <= PC(7 downto 0);
when cycleRmw =>
-- do <= T; -- Read-modify-write write old value first.
doReg <= di; -- Read-modify-write write old value first.
when others => null;
end case;
end if;
end if;
end process;
do <= doReg;
-- -----------------------------------------------------------------------
-- Write enable
-- -----------------------------------------------------------------------
calcWe: process(clk)
begin
if rising_edge(clk) then
if enable = '1' then
theWe <= '0';
case nextCpuCycle is
when cycleStack1 =>
if opcInfo(opcStackUp) = '0'
and ((opcInfo(opcStackAddr) = '0')
or (opcInfo(opcStackData) = '1')) then
theWe <= '1';
end if;
when cycleStack2 | cycleStack3 | cycleStack4 =>
if opcInfo(opcStackUp) = '0' then
theWe <= '1';
end if;
when cycleRmw =>
theWe <= '1';
when cycleWrite =>
theWe <= '1';
when others =>
null;
end case;
end if;
end if;
end process;
we <= theWe;
-- -----------------------------------------------------------------------
-- Program counter
-- -----------------------------------------------------------------------
calcPC: process(clk)
begin
if rising_edge(clk) then
if enable = '1' then
case theCpuCycle is
when opcodeFetch =>
PC <= myAddr;
when cycle2 =>
if irqActive = '0' then
if opcInfo(opcSecondByte) = '1' then
PC <= myAddrIncr;
else
PC <= myAddr;
end if;
end if;
when cycle3 =>
if opcInfo(opcAbsolute) = '1' then
PC <= myAddrIncr;
end if;
when others =>
null;
end case;
end if;
end if;
end process;
debugPc <= PC;
-- -----------------------------------------------------------------------
-- Address generation
-- -----------------------------------------------------------------------
calcNextAddr: process(theCpuCycle, opcInfo, indexOut, T, reset)
begin
nextAddr <= nextAddrIncr;
case theCpuCycle is
when cycle2 =>
if opcInfo(opcStackAddr) = '1'
or opcInfo(opcStackData) = '1' then
nextAddr <= nextAddrStack;
elsif opcInfo(opcAbsolute) = '1' then
nextAddr <= nextAddrIncr;
elsif opcInfo(opcZeroPage) = '1' then
nextAddr <= nextAddrZeroPage;
elsif opcInfo(opcIndirect) = '1' then
nextAddr <= nextAddrZeroPage;
elsif opcInfo(opcSecondByte) = '1' then
nextAddr <= nextAddrIncr;
else
nextAddr <= nextAddrHold;
end if;
when cycle3 =>
if (opcInfo(opcIndirect) = '1')
and (opcInfo(indexX) = '1') then
nextAddr <= nextAddrAbs;
else
nextAddr <= nextAddrAbsIndexed;
end if;
when cyclePreIndirect =>
nextAddr <= nextAddrZPIndexed;
when cycleIndirect =>
nextAddr <= nextAddrIncrL;
when cycleBranchTaken =>
nextAddr <= nextAddrRelative;
when cycleBranchPage =>
if T(7) = '0' then
nextAddr <= nextAddrIncrH;
else
nextAddr <= nextAddrDecrH;
end if;
when cyclePreRead =>
nextAddr <= nextAddrZPIndexed;
when cycleRead =>
nextAddr <= nextAddrPc;
if opcInfo(opcJump) = '1' then
-- Emulate 6510 bug, jmp(xxFF) fetches from same page.
-- Replace with nextAddrIncr if emulating 65C02 or later cpu.
nextAddr <= nextAddrIncrL;
elsif indexOut(8) = '1' then
nextAddr <= nextAddrIncrH;
elsif opcInfo(opcRmw) = '1' then
nextAddr <= nextAddrHold;
end if;
when cycleRead2 =>
nextAddr <= nextAddrPc;
if opcInfo(opcRmw) = '1' then
nextAddr <= nextAddrHold;
end if;
when cycleRmw =>
nextAddr <= nextAddrHold;
when cyclePreWrite =>
nextAddr <= nextAddrHold;
if opcInfo(opcZeroPage) = '1' then
nextAddr <= nextAddrZPIndexed;
elsif indexOut(8) = '1' then
nextAddr <= nextAddrIncrH;
end if;
when cycleWrite =>
nextAddr <= nextAddrPc;
when cycleStack1 =>
nextAddr <= nextAddrStack;
when cycleStack2 =>
nextAddr <= nextAddrStack;
when cycleStack3 =>
nextAddr <= nextAddrStack;
if opcInfo(opcStackData) = '0' then
nextAddr <= nextAddrPc;
end if;
when cycleStack4 =>
nextAddr <= nextAddrIrq;
when cycleJump =>
nextAddr <= nextAddrAbs;
when others =>
null;
end case;
if reset = '1' then
nextAddr <= nextAddrReset;
end if;
end process;
indexAlu: process(opcInfo, myAddr, T, X, Y)
begin
if opcInfo(indexX) = '1' then
indexOut <= (B"0" & T) + (B"0" & X);
elsif opcInfo(indexY) = '1' then
indexOut <= (B"0" & T) + (B"0" & Y);
elsif opcInfo(opcBranch) = '1' then
indexOut <= (B"0" & T) + (B"0" & myAddr(7 downto 0));
else
indexOut <= B"0" & T;
end if;
end process;
calcAddr: process(clk)
begin
if rising_edge(clk) then
if enable = '1' then
case nextAddr is
when nextAddrIncr => myAddr <= myAddrIncr;
when nextAddrIncrL => myAddr(7 downto 0) <= myAddrIncr(7 downto 0);
when nextAddrIncrH => myAddr(15 downto 8) <= myAddrIncrH;
when nextAddrDecrH => myAddr(15 downto 8) <= myAddrDecrH;
when nextAddrPc => myAddr <= PC;
when nextAddrIrq =>
myAddr <= X"FFFE";
if nmiReg = '0' then
myAddr <= X"FFFA";
end if;
when nextAddrReset => myAddr <= X"FFFC";
when nextAddrAbs => myAddr <= di & T;
when nextAddrAbsIndexed => myAddr <= di & indexOut(7 downto 0);
when nextAddrZeroPage => myAddr <= "00000000" & di;
when nextAddrZPIndexed => myAddr <= "00000000" & indexOut(7 downto 0);
when nextAddrStack => myAddr <= "00000001" & S;
when nextAddrRelative => myAddr(7 downto 0) <= indexOut(7 downto 0);
when others => null;
end case;
end if;
end if;
end process;
myAddrIncr <= myAddr + 1;
myAddrIncrH <= myAddr(15 downto 8) + 1;
myAddrDecrH <= myAddr(15 downto 8) - 1;
addr <= myAddr;
debugA <= A;
debugX <= X;
debugY <= Y;
debugS <= S;
end architecture;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -