📄 cpu65xx_fast.vhd
字号:
-- -----------------------------------------------------------------------
--
-- FPGA 64
--
-- A fully functional commodore 64 implementation in a single FPGA
--
-- -----------------------------------------------------------------------
-- Copyright 2005-2008 by Peter Wendrich (pwsoft@syntiac.com)
-- http://www.syntiac.com/fpga64.html
-- -----------------------------------------------------------------------
--
-- Table driven, cycle exact 6502/6510 core
--
-- -----------------------------------------------------------------------
library IEEE;
use ieee.std_logic_1164.ALL;
use ieee.std_logic_unsigned.ALL;
use ieee.numeric_std.ALL;
-- -----------------------------------------------------------------------
-- Store Zp (3) => fetch, cycle2, cycleEnd
-- Store Zp,x (4) => fetch, cycle2, preWrite, cycleEnd
-- Read Zp,x (4) => fetch, cycle2, cycleRead, cycleRead2
-- Rmw Zp,x (6) => fetch, cycle2, cycleRead, cycleRead2, cycleRmw, cycleEnd
-- Store Abs (4) => fetch, cycle2, cycle3, cycleEnd
-- Store Abs,x (5) => fetch, cycle2, cycle3, preWrite, cycleEnd
-- Rts (6) => fetch, cycle2, cycle3, cycleRead, cycleJump, cycleIncrEnd
-- Rti (6) => fetch, cycle2, stack1, stack2, stack3, cycleJump
-- Jsr (6) => fetch, cycle2, .. cycle5, cycle6, cycleJump
-- Jmp abs (-) => fetch, cycle2, .., cycleJump
-- Jmp (ind) (-) => fetch, cycle2, .., cycleJump
-- Brk / irq (6) => fetch, cycle2, stack2, stack3, stack4
-- -----------------------------------------------------------------------
architecture fast of cpu65xx is
-- Statemachine
type cpuCycles is (
opcodeFetch, -- New opcode is read and registers updated
cycle2,
cycle3,
cyclePreIndirect,
cycleIndirect,
cycleBranchTaken,
cycleBranchPage,
cyclePreRead, -- Cycle before read while doing zeropage indexed addressing.
cycleRead, -- Read cycle
cycleRead2, -- Second read cycle after page-boundary crossing.
cycleRmw, -- Calculate ALU output for read-modify-write instr.
cyclePreWrite, -- Cycle before write when doing indexed addressing.
cycleWrite, -- Write cycle for zeropage or absolute addressing.
cycleStack1,
cycleStack2,
cycleStack3,
cycleStack4,
cycleJump, -- Last cycle of Jsr, Jmp. Next fetch address is target addr.
cycleEnd
);
signal theCpuCycle : cpuCycles;
signal nextCpuCycle : cpuCycles;
signal updateRegisters : boolean;
signal processIrq : std_logic;
signal nmiReg: std_logic;
signal nmiEdge: std_logic;
signal irqReg : std_logic; -- Delay IRQ input with one clock cycle.
signal soReg : std_logic; -- SO pin edge detection
-- Opcode decoding
constant opcUpdateA : integer := 0;
constant opcUpdateX : integer := 1;
constant opcUpdateY : integer := 2;
constant opcUpdateS : integer := 3;
constant opcUpdateN : integer := 4;
constant opcUpdateV : integer := 5;
constant opcUpdateD : integer := 6;
constant opcUpdateI : integer := 7;
constant opcUpdateZ : integer := 8;
constant opcUpdateC : integer := 9;
constant opcSecondByte : integer := 10;
constant opcAbsolute : integer := 11;
constant opcZeroPage : integer := 12;
constant opcIndirect : integer := 13;
constant opcStackAddr : integer := 14; -- Push/Pop address
constant opcStackData : integer := 15; -- Push/Pop status/data
constant opcJump : integer := 16;
constant opcBranch : integer := 17;
constant indexX : integer := 18;
constant indexY : integer := 19;
constant opcStackUp : integer := 20;
constant opcWrite : integer := 21;
constant opcRmw : integer := 22;
constant opcIncrAfter : integer := 23; -- Insert extra cycle to increment PC (RTS)
constant opcRti : integer := 24;
constant opcIRQ : integer := 25;
constant opcInA : integer := 26;
constant opcInE : integer := 27;
constant opcInX : integer := 28;
constant opcInY : integer := 29;
constant opcInS : integer := 30;
constant opcInT : integer := 31;
constant opcInH : integer := 32;
constant opcInClear : integer := 33;
constant aluMode1From : integer := 34;
--
constant aluMode1To : integer := 37;
constant aluMode2From : integer := 38;
--
constant aluMode2To : integer := 40;
--
constant opcInCmp : integer := 41;
constant opcInCpx : integer := 42;
constant opcInCpy : integer := 43;
subtype addrDef is unsigned(0 to 15);
--
-- is Interrupt -----------------+
-- instruction is RTI ----------------+|
-- PC++ on last cycle (RTS) ---------------+||
-- RMW --------------+|||
-- Write -------------+||||
-- Pop/Stack up -------------+|||||
-- Branch ---------+ ||||||
-- Jump ----------+| ||||||
-- Push or Pop data -------+|| ||||||
-- Push or Pop addr ------+||| ||||||
-- Indirect -----+|||| ||||||
-- ZeroPage ----+||||| ||||||
-- Absolute ---+|||||| ||||||
-- PC++ on cycle2 --+||||||| ||||||
-- |AZI||JBXY|WM|||
constant immediate : addrDef := "1000000000000000";
constant implied : addrDef := "0000000000000000";
-- Zero page
constant readZp : addrDef := "1010000000000000";
constant writeZp : addrDef := "1010000000010000";
constant rmwZp : addrDef := "1010000000001000";
-- Zero page indexed
constant readZpX : addrDef := "1010000010000000";
constant writeZpX : addrDef := "1010000010010000";
constant rmwZpX : addrDef := "1010000010001000";
constant readZpY : addrDef := "1010000001000000";
constant writeZpY : addrDef := "1010000001010000";
constant rmwZpY : addrDef := "1010000001001000";
-- Zero page indirect
constant readIndX : addrDef := "1001000010000000";
constant writeIndX : addrDef := "1001000010010000";
constant rmwIndX : addrDef := "1001000010001000";
constant readIndY : addrDef := "1001000001000000";
constant writeIndY : addrDef := "1001000001010000";
constant rmwIndY : addrDef := "1001000001001000";
-- |AZI||JBXY|WM||
-- Absolute
constant readAbs : addrDef := "1100000000000000";
constant writeAbs : addrDef := "1100000000010000";
constant rmwAbs : addrDef := "1100000000001000";
constant readAbsX : addrDef := "1100000010000000";
constant writeAbsX : addrDef := "1100000010010000";
constant rmwAbsX : addrDef := "1100000010001000";
constant readAbsY : addrDef := "1100000001000000";
constant writeAbsY : addrDef := "1100000001010000";
constant rmwAbsY : addrDef := "1100000001001000";
-- PHA PHP
constant push : addrDef := "0000010000000000";
-- PLA PLP
constant pop : addrDef := "0000010000100000";
-- Jumps
constant jsr : addrDef := "1000101000000000";
constant jumpAbs : addrDef := "1000001000000000";
constant jumpInd : addrDef := "1100001000000000";
constant relative : addrDef := "1000000100000000";
-- Specials
constant rts : addrDef := "0000101000100100";
constant rti : addrDef := "0000111000100010";
constant brk : addrDef := "1000111000000001";
-- constant : unsigned(0 to 0) := "0";
constant xxxxxxxx : addrDef := "----------0---00";
-- A = accu
-- E = Accu | 0xEE (for ANE, LXA)
-- X = index X
-- Y = index Y
-- S = Stack pointer
-- H = indexH
--
-- AEXYSTHc
constant aluInA : unsigned(0 to 7) := "10000000";
constant aluInE : unsigned(0 to 7) := "01000000";
constant aluInEXT : unsigned(0 to 7) := "01100100";
constant aluInET : unsigned(0 to 7) := "01000100";
constant aluInX : unsigned(0 to 7) := "00100000";
constant aluInXH : unsigned(0 to 7) := "00100010";
constant aluInY : unsigned(0 to 7) := "00010000";
constant aluInYH : unsigned(0 to 7) := "00010010";
constant aluInS : unsigned(0 to 7) := "00001000";
constant aluInT : unsigned(0 to 7) := "00000100";
constant aluInAX : unsigned(0 to 7) := "10100000";
constant aluInAXH : unsigned(0 to 7) := "10100010";
constant aluInAT : unsigned(0 to 7) := "10000100";
constant aluInXT : unsigned(0 to 7) := "00100100";
constant aluInST : unsigned(0 to 7) := "00001100";
constant aluInSet : unsigned(0 to 7) := "00000000";
constant aluInClr : unsigned(0 to 7) := "00000001";
constant aluInXXX : unsigned(0 to 7) := "--------";
-- Most of the aluModes are just like the opcodes.
-- aluModeInp -> input is output. calculate N and Z
-- aluModeCmp -> Compare for CMP, CPX, CPY
-- aluModeFlg -> input to flags needed for PLP, RTI and CLC, SEC, CLV
-- aluModeInc -> for INC but also INX, INY
-- aluModeDec -> for DEC but also DEX, DEY
subtype aluMode1 is unsigned(0 to 3);
subtype aluMode2 is unsigned(0 to 2);
subtype aluMode is unsigned(0 to 9);
-- Logic/Shift ALU
constant aluModeInp : aluMode1 := "0000";
constant aluModeP : aluMode1 := "0001";
constant aluModeInc : aluMode1 := "0010";
constant aluModeDec : aluMode1 := "0011";
constant aluModeFlg : aluMode1 := "0100";
constant aluModeBit : aluMode1 := "0101";
-- 0110
-- 0111
constant aluModeLsr : aluMode1 := "1000";
constant aluModeRor : aluMode1 := "1001";
constant aluModeAsl : aluMode1 := "1010";
constant aluModeRol : aluMode1 := "1011";
-- 1100
-- 1101
-- 1110
constant aluModeAnc : aluMode1 := "1111";
-- Arithmetic ALU
constant aluModePss : aluMode2 := "000";
constant aluModeCmp : aluMode2 := "001";
constant aluModeAdc : aluMode2 := "010";
constant aluModeSbc : aluMode2 := "011";
constant aluModeAnd : aluMode2 := "100";
constant aluModeOra : aluMode2 := "101";
constant aluModeEor : aluMode2 := "110";
constant aluModeArr : aluMode2 := "111";
constant aluInp : aluMode := aluModeInp & aluModePss & "---";
constant aluP : aluMode := aluModeP & aluModePss & "---";
constant aluInc : aluMode := aluModeInc & aluModePss & "---";
constant aluDec : aluMode := aluModeDec & aluModePss & "---";
constant aluFlg : aluMode := aluModeFlg & aluModePss & "---";
constant aluBit : aluMode := aluModeBit & aluModeAnd & "---";
constant aluRor : aluMode := aluModeRor & aluModePss & "---";
constant aluLsr : aluMode := aluModeLsr & aluModePss & "---";
constant aluRol : aluMode := aluModeRol & aluModePss & "---";
constant aluAsl : aluMode := aluModeAsl & aluModePss & "---";
constant aluCmp : aluMode := aluModeInp & aluModeCmp & "100";
constant aluCpx : aluMode := aluModeInp & aluModeCmp & "010";
constant aluCpy : aluMode := aluModeInp & aluModeCmp & "001";
constant aluAdc : aluMode := aluModeInp & aluModeAdc & "---";
constant aluSbc : aluMode := aluModeInp & aluModeSbc & "---";
constant aluAnd : aluMode := aluModeInp & aluModeAnd & "---";
constant aluOra : aluMode := aluModeInp & aluModeOra & "---";
constant aluEor : aluMode := aluModeInp & aluModeEor & "---";
constant aluSlo : aluMode := aluModeAsl & aluModeOra & "---";
constant aluSre : aluMode := aluModeLsr & aluModeEor & "---";
constant aluRra : aluMode := aluModeRor & aluModeAdc & "---";
constant aluRla : aluMode := aluModeRol & aluModeAnd & "---";
constant aluDcp : aluMode := aluModeDec & aluModeCmp & "100";
constant aluIsc : aluMode := aluModeInc & aluModeSbc & "---";
constant aluAnc : aluMode := aluModeAnc & aluModeAnd & "---";
constant aluArr : aluMode := aluModeRor & aluModeArr & "---";
constant aluSbx : aluMode := aluModeInp & aluModeCmp & "110";
constant aluXXX : aluMode := (others => '-');
-- Stack operations. Push/Pop/None
constant stackInc : unsigned(0 to 0) := "0";
constant stackDec : unsigned(0 to 0) := "1";
constant stackXXX : unsigned(0 to 0) := "-";
subtype decodedBitsDef is unsigned(0 to 43);
type opcodeInfoTableDef is array(0 to 255) of decodedBitsDef;
constant opcodeInfoTable : opcodeInfoTableDef := (
-- +------- Update register A
-- |+------ Update register X
-- ||+----- Update register Y
-- |||+---- Update register S
-- |||| +-- Update Flags
-- |||| |
-- |||| _|__
-- |||| / \
-- AXYS NVDIZC addressing aluInput aluMode
"0000" & "000100" & brk & aluInXXX & aluP, -- 00 BRK
"1000" & "100010" & readIndX & aluInT & aluOra, -- 01 ORA (zp,x)
"----" & "------" & xxxxxxxx & aluInXXX & aluXXX, -- 02 *** JAM ***
"1000" & "100011" & rmwIndX & aluInT & aluSlo, -- 03 iSLO (zp,x)
"0000" & "000000" & readZp & aluInXXX & aluXXX, -- 04 iNOP zp
"1000" & "100010" & readZp & aluInT & aluOra, -- 05 ORA zp
"0000" & "100011" & rmwZp & aluInT & aluAsl, -- 06 ASL zp
"1000" & "100011" & rmwZp & aluInT & aluSlo, -- 07 iSLO zp
"0000" & "000000" & push & aluInXXX & aluP, -- 08 PHP
"1000" & "100010" & immediate & aluInT & aluOra, -- 09 ORA imm
"1000" & "100011" & implied & aluInA & aluAsl, -- 0A ASL accu
"1000" & "100011" & immediate & aluInT & aluAnc, -- 0B iANC imm
"0000" & "000000" & readAbs & aluInXXX & aluXXX, -- 0C iNOP abs
"1000" & "100010" & readAbs & aluInT & aluOra, -- 0D ORA abs
"0000" & "100011" & rmwAbs & aluInT & aluAsl, -- 0E ASL abs
"1000" & "100011" & rmwAbs & aluInT & aluSlo, -- 0F iSLO abs
"0000" & "000000" & relative & aluInXXX & aluXXX, -- 10 BPL
"1000" & "100010" & readIndY & aluInT & aluOra, -- 11 ORA (zp),y
"----" & "------" & xxxxxxxx & aluInXXX & aluXXX, -- 12 *** JAM ***
"1000" & "100011" & rmwIndY & aluInT & aluSlo, -- 13 iSLO (zp),y
"0000" & "000000" & readZpX & aluInXXX & aluXXX, -- 14 iNOP zp,x
"1000" & "100010" & readZpX & aluInT & aluOra, -- 15 ORA zp,x
"0000" & "100011" & rmwZpX & aluInT & aluAsl, -- 16 ASL zp,x
"1000" & "100011" & rmwZpX & aluInT & aluSlo, -- 17 iSLO zp,x
"0000" & "000001" & implied & aluInClr & aluFlg, -- 18 CLC
"1000" & "100010" & readAbsY & aluInT & aluOra, -- 19 ORA abs,y
"0000" & "000000" & implied & aluInXXX & aluXXX, -- 1A iNOP implied
"1000" & "100011" & rmwAbsY & aluInT & aluSlo, -- 1B iSLO abs,y
"0000" & "000000" & readAbsX & aluInXXX & aluXXX, -- 1C iNOP abs,x
"1000" & "100010" & readAbsX & aluInT & aluOra, -- 1D ORA abs,x
"0000" & "100011" & rmwAbsX & aluInT & aluAsl, -- 1E ASL abs,x
"1000" & "100011" & rmwAbsX & aluInT & aluSlo, -- 1F iSLO abs,x
-- AXYS NVDIZC addressing aluInput aluMode
"0000" & "000000" & jsr & aluInXXX & aluXXX, -- 20 JSR
"1000" & "100010" & readIndX & aluInT & aluAnd, -- 21 AND (zp,x)
"----" & "------" & xxxxxxxx & aluInXXX & aluXXX, -- 22 *** JAM ***
"1000" & "100011" & rmwIndX & aluInT & aluRla, -- 23 iRLA (zp,x)
"0000" & "110010" & readZp & aluInT & aluBit, -- 24 BIT zp
"1000" & "100010" & readZp & aluInT & aluAnd, -- 25 AND zp
"0000" & "100011" & rmwZp & aluInT & aluRol, -- 26 ROL zp
"1000" & "100011" & rmwZp & aluInT & aluRla, -- 27 iRLA zp
"0000" & "111111" & pop & aluInT & aluFlg, -- 28 PLP
"1000" & "100010" & immediate & aluInT & aluAnd, -- 29 AND imm
"1000" & "100011" & implied & aluInA & aluRol, -- 2A ROL accu
"1000" & "100011" & immediate & aluInT & aluAnc, -- 2B iANC imm
"0000" & "110010" & readAbs & aluInT & aluBit, -- 2C BIT abs
"1000" & "100010" & readAbs & aluInT & aluAnd, -- 2D AND abs
"0000" & "100011" & rmwAbs & aluInT & aluRol, -- 2E ROL abs
"1000" & "100011" & rmwAbs & aluInT & aluRla, -- 2F iRLA abs
"0000" & "000000" & relative & aluInXXX & aluXXX, -- 30 BMI
"1000" & "100010" & readIndY & aluInT & aluAnd, -- 31 AND (zp),y
"----" & "------" & xxxxxxxx & aluInXXX & aluXXX, -- 32 *** JAM ***
"1000" & "100011" & rmwIndY & aluInT & aluRla, -- 33 iRLA (zp),y
"0000" & "000000" & readZpX & aluInXXX & aluXXX, -- 34 iNOP zp,x
"1000" & "100010" & readZpX & aluInT & aluAnd, -- 35 AND zp,x
"0000" & "100011" & rmwZpX & aluInT & aluRol, -- 36 ROL zp,x
"1000" & "100011" & rmwZpX & aluInT & aluRla, -- 37 iRLA zp,x
"0000" & "000001" & implied & aluInSet & aluFlg, -- 38 SEC
"1000" & "100010" & readAbsY & aluInT & aluAnd, -- 39 AND abs,y
"0000" & "000000" & implied & aluInXXX & aluXXX, -- 3A iNOP implied
"1000" & "100011" & rmwAbsY & aluInT & aluRla, -- 3B iRLA abs,y
"0000" & "000000" & readAbsX & aluInXXX & aluXXX, -- 3C iNOP abs,x
"1000" & "100010" & readAbsX & aluInT & aluAnd, -- 3D AND abs,x
"0000" & "100011" & rmwAbsX & aluInT & aluRol, -- 3E ROL abs,x
"1000" & "100011" & rmwAbsX & aluInT & aluRla, -- 3F iRLA abs,x
-- AXYS NVDIZC addressing aluInput aluMode
"0000" & "111111" & rti & aluInT & aluFlg, -- 40 RTI
"1000" & "100010" & readIndX & aluInT & aluEor, -- 41 EOR (zp,x)
"----" & "------" & xxxxxxxx & aluInXXX & aluXXX, -- 42 *** JAM ***
"1000" & "100011" & rmwIndX & aluInT & aluSre, -- 43 iSRE (zp,x)
"0000" & "000000" & readZp & aluInXXX & aluXXX, -- 44 iNOP zp
"1000" & "100010" & readZp & aluInT & aluEor, -- 45 EOR zp
"0000" & "100011" & rmwZp & aluInT & aluLsr, -- 46 LSR zp
"1000" & "100011" & rmwZp & aluInT & aluSre, -- 47 iSRE zp
"0000" & "000000" & push & aluInA & aluInp, -- 48 PHA
"1000" & "100010" & immediate & aluInT & aluEor, -- 49 EOR imm
"1000" & "100011" & implied & aluInA & aluLsr, -- 4A LSR accu
"1000" & "100011" & immediate & aluInAT & aluLsr, -- 4B iALR imm
"0000" & "000000" & jumpAbs & aluInXXX & aluXXX, -- 4C JMP abs
"1000" & "100010" & readAbs & aluInT & aluEor, -- 4D EOR abs
"0000" & "100011" & rmwAbs & aluInT & aluLsr, -- 4E LSR abs
"1000" & "100011" & rmwAbs & aluInT & aluSre, -- 4F iSRE abs
"0000" & "000000" & relative & aluInXXX & aluXXX, -- 50 BVC
"1000" & "100010" & readIndY & aluInT & aluEor, -- 51 EOR (zp),y
"----" & "------" & xxxxxxxx & aluInXXX & aluXXX, -- 52 *** JAM ***
"1000" & "100011" & rmwIndY & aluInT & aluSre, -- 53 iSRE (zp),y
"0000" & "000000" & readZpX & aluInXXX & aluXXX, -- 54 iNOP zp,x
"1000" & "100010" & readZpX & aluInT & aluEor, -- 55 EOR zp,x
"0000" & "100011" & rmwZpX & aluInT & aluLsr, -- 56 LSR zp,x
"1000" & "100011" & rmwZpX & aluInT & aluSre, -- 57 SRE zp,x
"0000" & "000100" & implied & aluInClr & aluXXX, -- 58 CLI
"1000" & "100010" & readAbsY & aluInT & aluEor, -- 59 EOR abs,y
"0000" & "000000" & implied & aluInXXX & aluXXX, -- 5A iNOP implied
"1000" & "100011" & rmwAbsY & aluInT & aluSre, -- 5B iSRE abs,y
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -