📄 fpga64_cone.vhd
字号:
-- -----------------------------------------------------------------------
--
-- FPGA 64
--
-- A fully functional commodore 64 implementation in a single FPGA
--
-- -----------------------------------------------------------------------
-- Peter Wendrich (pwsoft@syntiac.com)
-- http://www.syntiac.com/fpga64.html
-- -----------------------------------------------------------------------
--
-- System runs on 32 Mhz (derived from a 50MHz clock).
-- The VIC-II runs in the first 4 cycles of 32 Mhz clock.
-- The CPU runs in the last 16 cycles. Effective cpu speed is 1 Mhz.
-- 4 additional cycles are used to interface with the C-One IEC port.
--
-- -----------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.std_logic_unsigned.ALL;
use IEEE.numeric_std.all;
-- -----------------------------------------------------------------------
entity fpga64_cone is
generic (
resetCycles: integer := 4095
);
port(
sysclk : in std_logic;
clk32 : in std_logic;
reset_n : in std_logic;
-- keyboard interface (use any ordinairy PS2 keyboard)
kbd_clk: in std_logic;
kbd_dat: in std_logic;
-- external memory
ramAddr: out unsigned(16 downto 0);
ramData: inout unsigned(7 downto 0);
ramCE: out std_logic;
ramWe: out std_logic;
-- VGA interface
hsync: out std_logic;
vsync: out std_logic;
r : out unsigned(7 downto 0);
g : out unsigned(7 downto 0);
b : out unsigned(7 downto 0);
-- cartridge port
game : in std_logic;
exrom : in std_logic;
irq_n : inout std_logic;
nmi_n : inout std_logic;
dma_n : in std_logic;
ba : out std_logic;
dot_clk: out std_logic;
cpu_clk: out std_logic;
-- joystick interface
joyA: in unsigned(5 downto 0);
joyB: in unsigned(5 downto 0);
-- serial port, for connection to pheripherals
serioclk : out std_logic;
ces : out std_logic_vector(3 downto 0);
--Connector to the SID
SIDclk: out std_logic;
still: out unsigned(15 downto 0)
);
end fpga64_cone;
-- -----------------------------------------------------------------------
architecture rtl of fpga64_cone is
-- System state machine
type sysCycleDef is (
CYCLE_IDLE0, CYCLE_IDLE1, CYCLE_IDLE2, CYCLE_IDLE3,
CYCLE_IDLE4, CYCLE_IDLE5, CYCLE_IDLE6, CYCLE_IDLE7,
CYCLE_IDLE8,
CYCLE_IEC0, CYCLE_IEC1, CYCLE_IEC2, CYCLE_IEC3,
CYCLE_VIC0, CYCLE_VIC1, CYCLE_VIC2, CYCLE_VIC3,
CYCLE_CPU0, CYCLE_CPU1, CYCLE_CPU2, CYCLE_CPU3,
CYCLE_CPU4, CYCLE_CPU5, CYCLE_CPU6, CYCLE_CPU7,
CYCLE_CPUP, CYCLE_CPUQ,
CYCLE_CPU8, CYCLE_CPU9, CYCLE_CPUA, CYCLE_CPUB,
CYCLE_CPUC, CYCLE_CPUD, CYCLE_CPUE, CYCLE_CPUF
);
signal sysCycle : sysCycleDef := sysCycleDef'low;
signal sysCycleCnt : unsigned(2 downto 0);
signal phi0_cpu : std_logic;
signal phi0_vic : std_logic;
signal cpuHasBus : std_logic;
signal cycleRestart : std_logic;
signal cycleRestartReg1 : std_logic;
signal cycleRestartReg2 : std_logic;
signal cycleRestartEdge : std_logic;
signal dotClkReg : std_logic;
signal dotClkCnt : integer range 0 to 7;
signal baLoc: std_logic;
signal irqLoc: std_logic;
signal nmiLoc: std_logic;
signal enableCpu: std_logic;
signal enableVic : std_logic;
signal enablePixel : std_logic;
signal irq_cia1: std_logic;
signal irq_cia2: std_logic;
signal irq_vic: std_logic;
signal systemWe: std_logic;
signal pulseWrRam: std_logic;
signal pulseWrIo: std_logic;
signal pulseRd: std_logic;
signal colorWe : std_logic;
signal systemAddr: unsigned(16 downto 0);
signal ramDataReg : unsigned(7 downto 0);
signal cs_vic: std_logic;
signal cs_sid: std_logic;
signal cs_color: std_logic;
signal cs_cia1: std_logic;
signal cs_cia2: std_logic;
signal cs_ram: std_logic;
signal cs_ioE: std_logic;
signal cs_ioF: std_logic;
signal cs_romL: std_logic;
signal cs_romH: std_logic;
signal reset: std_logic := '1';
signal reset_cnt: integer range 0 to resetCycles := 0;
signal bankSwitch: unsigned(2 downto 0);
-- CIA signals
signal enableCia : std_logic;
signal cia1Do: unsigned(7 downto 0);
signal cia2Do: unsigned(7 downto 0);
-- keyboard
signal newScanCode: std_logic;
signal theScanCode: unsigned(7 downto 0);
-- I/O
signal cia1_pai: unsigned(7 downto 0);
signal cia1_pao: unsigned(7 downto 0);
signal cia1_pad: unsigned(7 downto 0);
signal cia1_pbi: unsigned(7 downto 0);
signal cia1_pbo: unsigned(7 downto 0);
signal cia1_pbd: unsigned(7 downto 0);
signal cia2_pai: unsigned(7 downto 0);
signal cia2_pao: unsigned(7 downto 0);
signal cia2_pad: unsigned(7 downto 0);
signal cia2_pbi: unsigned(7 downto 0);
signal cia2_pbo: unsigned(7 downto 0);
signal cia2_pbd: unsigned(7 downto 0);
signal debugWE: std_logic := '0';
signal debugData: unsigned(7 downto 0) := (others => '0');
signal debugAddr: integer range 2047 downto 0 := 0;
signal cpuWe: std_logic;
signal cpuAddr: unsigned(15 downto 0);
signal cpuDi: unsigned(7 downto 0);
signal cpuDo: unsigned(7 downto 0);
signal cpuIO: unsigned(7 downto 0);
signal vicDi: unsigned(7 downto 0);
signal vicAddr: unsigned(15 downto 0);
signal vicData: unsigned(7 downto 0);
signal lastVicDi : unsigned(7 downto 0);
signal colorQ : unsigned(3 downto 0);
signal colorData : unsigned(3 downto 0);
signal cpuDebugOpcode: unsigned(7 downto 0);
signal cpuDebugPc: unsigned(15 downto 0);
signal cpuDebugA: unsigned(7 downto 0);
signal cpuDebugX: unsigned(7 downto 0);
signal cpuDebugY: unsigned(7 downto 0);
signal cpuDebugS: unsigned(7 downto 0);
signal cpuStep : std_logic;
signal traceKey : std_logic;
signal trace2Key : std_logic;
-- video
signal cyclesPerLine : unsigned(11 downto 0);
signal scanConverterFaster : std_logic;
signal vicColorIndex : unsigned(3 downto 0);
signal vicHSync : std_logic;
signal vicVSync : std_logic;
signal vgaColorIndex : unsigned(3 downto 0);
signal vgaR : unsigned(7 downto 0);
signal vgaG : unsigned(7 downto 0);
signal vgaB : unsigned(7 downto 0);
signal vgaVSync : std_logic;
signal vgaHSync : std_logic;
signal vgaDebug : std_logic;
signal vgaDebugDim : std_logic;
signal debuggerOn : std_logic;
signal traceStep : std_logic;
-- config
signal videoKey : std_logic;
signal ntscMode : std_logic;
signal videoConfigVideo : std_logic;
signal videoConfigDim : std_logic;
signal videoConfigShow : std_logic;
signal videoConfigTimeout : unsigned(19 downto 0);
begin
-- -----------------------------------------------------------------------
-- Local signal to outside world
-- -----------------------------------------------------------------------
ba <= baLoc;
-- -----------------------------------------------------------------------
-- System state machine, controls bus accesses
-- and triggers enables of other components
-- -----------------------------------------------------------------------
process(clk32)
begin
if rising_edge(clk32) then
cycleRestart <= '0';
if sysCycle = sysCycleDef'high then
sysCycle <= sysCycleDef'low;
sysCycleCnt <= sysCycleCnt + 1;
cycleRestart <= '1';
elsif sysCycle = CYCLE_CPU7
and ntscMode = '1' then
sysCycle <= CYCLE_CPU8; -- NTSC 33 Cycles
elsif sysCycle = CYCLE_CPUP
and sysCycleCnt /= "001"
and sysCycleCnt /= "100"
and sysCycleCnt /= "111" then -- PAL 34 + 3/8
sysCycle <= CYCLE_CPU8;
else
sysCycle <= sysCycleDef'succ(sysCycle);
end if;
end if;
end process;
iecClock: process(clk32)
begin
if rising_edge(clk32) then
serioclk <= '1';
if sysCycle = CYCLE_IEC0
or sysCycle = CYCLE_IEC1 then
serioclk <= '0'; --for iec write
end if;
end if;
end process;
sidClock: process(clk32)
begin
if rising_edge(clk32) then
-- Toggle SIDclk early to compensate for the delay caused by the gbridge
if sysCycle = CYCLE_VIC3 then
SIDclk <= '1';
end if;
if sysCycle = CYCLE_CPUD then
SIDclk <= '0';
end if;
end if;
end process;
-- PHI0/2-clock emulation
process(clk32)
begin
if rising_edge(clk32) then
if sysCycle = sysCycleDef'pred(CYCLE_CPU0) then
phi0_cpu <= '1';
if baLoc = '1' or cpuWe = '1' then
cpuHasBus <= '1';
end if;
end if;
if sysCycle = sysCycleDef'high then
phi0_cpu <= '0';
cpuHasBus <= '0';
end if;
if sysCycle = sysCycleDef'pred(CYCLE_VIC0) then
phi0_vic <= '1';
end if;
if sysCycle = CYCLE_VIC3 then
phi0_vic <= '0';
end if;
end if;
end process;
process(clk32)
begin
if rising_edge(clk32) then
enableVic <= '0';
enableCia <= '0';
enableCpu <= '0';
case sysCycle is
when CYCLE_VIC2 =>
enableVic <= '1';
when CYCLE_CPUE =>
enableCia <= '1';
enableVic <= '1';
if baLoc = '1'
or cpuWe = '1' then
enableCpu <= '1';
end if;
when others =>
null;
end case;
end if;
end process;
-- -----------------------------------------------------------------------
-- Cartridge clocks
-- -----------------------------------------------------------------------
process(sysclk)
begin
if rising_edge(sysclk) then
cycleRestartReg1 <= cycleRestart;
cycleRestartReg2 <= cycleRestartReg1;
cycleRestartEdge <= cycleRestartReg2;
dotClkCnt <= dotClkCnt + 1;
if dotClkCnt = 6 then
dotClkReg <= not dotClkReg;
dotClkCnt <= 0;
if ntscMode = '1'
or dotClkReg = '1' then
dotClkCnt <= 1;
end if;
end if;
if cycleRestartReg2 = '1'
and cycleRestartEdge = '0' then
dotClkReg <= '1';
dotClkCnt <= 0;
end if;
end if;
end process;
dot_clk <= dotClkReg;
cpu_clk <= phi0_cpu;
-- -----------------------------------------------------------------------
-- Scan-converter and VGA output
-- -----------------------------------------------------------------------
myScanConverter: entity work.fpga64_cone_scanconverter
generic map (
videoWidth => 4
)
port map (
clk => clk32,
cyclesPerLine => cyclesPerLine,
faster => scanConverterFaster,
hSyncPolarity => '0',
vSyncPolarity => '0',
enable_in => enablePixel,
video_in => vicColorIndex,
hsync_in => vicHSync,
vsync_in => vicVSync,
video_out => vgaColorIndex,
hsync_out => vgaHSync,
vsync_out => vgaVSync
);
cyclesPerLine <= to_unsigned(1080, 12) when ntscMode = '0' else to_unsigned(1088,12);
scanConverterFaster <= not ntscMode;
c64colors: entity work.fpga64_rgbcolor
port map (
index => vgaColorIndex,
r => vgaR,
g => vgaG,
b => vgaB
);
process(clk32)
begin
if rising_edge(clk32) then
r <= vgaR;
g <= vgaG;
b <= vgaB;
-- if videoConfigShow = '1' and videoConfigDim = '1' then
-- if videoConfigDim = '1' then
-- r <= videoConfigVideo & vgaR(7 downto 1);
-- g <= videoConfigVideo & vgaG(7 downto 1);
-- b <= videoConfigVideo & vgaB(7 downto 1);
-- end if;
-- if vgaDebugDim = '1' then
-- r <= vgaDebug & vgaR(7 downto 1);
-- g <= vgaDebug & vgaG(7 downto 1);
-- b <= vgaDebug & vgaB(7 downto 1);
-- end if;
end if;
end process;
hSync <= vgaHSync;
vSync <= vgaVSync;
-- -----------------------------------------------------------------------
-- Color RAM
-- -----------------------------------------------------------------------
colorram: entity work.gen_ram
generic map (
dWidth => 4,
aWidth => 10
)
port map (
clk => clk32,
we => colorWe,
addr => systemAddr(9 downto 0),
d => cpuDo(3 downto 0),
q => colorQ
);
process(clk32)
begin
if rising_edge(clk32) then
colorWe <= (cs_color and pulseWrRam);
colorData <= colorQ;
end if;
end process;
-- -----------------------------------------------------------------------
-- PLA and bus-switches
-- -----------------------------------------------------------------------
buslogic: entity work.fpga64_buslogic
port map (
clk => clk32,
reset => reset,
cpuHasBus => cpuHasBus,
bankSwitch => cpuIO(2 downto 0),
game => game,
exrom => exrom,
ramData => ramDataReg,
cpuWe => cpuWe,
cpuAddr => cpuAddr,
cpuData => cpuDo,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -