⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dan_2a03.vhd

📁 用FPGA制作的NES游戏主机(80后都知道的游戏主机)的VHDL代码
💻 VHD
字号:
--Dan Leach
--2A03 for NES
--Created 1/03/06
	--Initial revision
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.Pack_2A03.all;

entity NES_2A03 is
	port (
		Global_Clk	: in std_logic;		--input clock signal from NES mobo crystal
		Reset_N 		: in std_logic;		--External Reset
		NMI_N 		: in std_logic;
		IRQ_N 		: in std_logic;
		Data 			: inout std_logic_vector(7 downto 0);
		Address 		: buffer std_logic_vector(15 downto 0);
		RW_10			: buffer std_logic;		--low if writing, high if reading
		PHI1			: out std_logic;
		PHI2 			: out std_logic;	--Clock Divider Output
		
		--Controller Outputs
		CStrobe	: out std_logic;	--Controller Strobe Signal 
		C1R_N 	: out std_logic;	--low when reading controller 1
		C2R_N 	: out std_logic;	--low when reading controller 2
		
		--Audio Outputs
		A_Rectangle : out std_logic;	--Rectangle Wave Output (Mixed)
		A_Combined 	: out std_logic;	--Triangle, Noise, And PCM (DPCM) Output
		
		--The following three signals represent the status of an internal register
		--	used in accessing the expansion port
		W_4016_1 	: out std_logic;
		W_4016_2 	: out std_logic;
		
		--Debugging
		ClockDividerTrigger : out std_logic;
		--LCycle : out std_logic_vector(2 downto 0);
		--MCycle : out std_logic_vector(2 downto 0);
		--InitialReset : out std_logic;
		AddOKDebug : out std_logic;
		ReadOKDebug : out std_logic;
		WriteOKDebug : out std_logic;
		SRAMChipSelect_NDebug : out std_logic;
		SRAMWriteEnable_NDebug : out std_logic;
		SRAMOutputEnable_NDebug :out std_logic;
		SRAMReading : out std_logic;
		SRAMWriting : out std_logic
	);
end NES_2A03;

architecture Behavioral of NES_2A03 is
	--Clock Control
	signal PHI1_Internal	: std_logic;
	signal PHI2_Internal	: std_logic;
	
	--Internal Status Registers
	signal Global_Enable	: std_logic;
	
	--T65 Control
	signal	T65Enable 	: std_logic;
	signal	T65RW_10 	: std_logic := '0';
	signal	T65Address	: std_logic_vector (15 downto 0);
	signal	T65DataIn	: std_logic_vector(7 downto 0);
	signal	T65DataOut	: std_logic_vector(7 downto 0);
	
	--DMA
	signal	TransferCount		: unsigned (9 downto 0);
	signal	TransferAddress	: unsigned (15 downto 0);
	signal	DMAEnable	: std_logic;
	signal	DMARW_10 	: std_logic := '0';
	signal	DMAAddress	: std_logic_vector (15 downto 0) := "0000000000000000";
	signal	DMADataIn 	: std_logic_vector(7 downto 0);
	signal	DMADataOut	: std_logic_vector(7 downto 0);
	signal	DMAContinue : std_logic;
	signal	DMADelay 	: unsigned (2 downto 0);
	
	--Bus Control
	signal	BusControl		: std_logic;
	signal	RW_10Signal		: std_logic;
	signal	AddressSignal	: std_logic_vector (15 downto 0);
	signal	DataInSignal	: std_logic_vector (7 downto 0);
	signal	DataOutSignal	: std_logic_vector (7 downto 0);
	
	--Bus Timing
	signal	AddOKSignal		: std_logic := '0';
	signal	ReadOKSignal	: std_logic := '0';
	signal	WriteOKSignal	: std_logic := '0';
	
	--Memory
	signal	SRAMWriteSignal	: std_logic;
	signal	SRAM_Reading		: std_logic;
	signal	SRAM_Writing		: std_logic;
	
	--Controllers
	signal	ControllerOnePoll : std_logic := '0';
	signal	ControllerTwoPoll : std_logic := '0';
	
begin
--more or less constant assignments
	Global_Enable	<=	'1';
	PHI1	<= PHI1_Internal;
	PHI2	<= PHI2_Internal;
	
	SRAMWriteSignal <= not ReadOKSignal when RW_10 = '0' else '1';
	
--to be implemented later
	A_Rectangle <= '0';
	A_Combined 	<= '0';
	W_4016_1		<= 'Z';
	W_4016_2		<= 'Z';

--Debugging
	WriteOKDebug	<= WriteOKSignal;
	AddOKDebug		<= AddOKSignal;
	ReadOKDebug		<= ReadOKSignal;
	
	SRAMWriteEnable_NDebug <= SRAMWriteSignal;
	SRAMOutputEnable_NDebug <= '0';
	SRAMChipSelect_NDebug <= (not PHI2_Internal) or (Address(15) or Address(14) or Address(13));
	
	SRAMReading <= SRAM_Reading;
	SRAMWriting <= SRAM_Writing;

--Controllers
ControllerOnePoll <= '1' when Address = x"4016" else '0';
ControllerTwoPoll <= '1' when Address = x"4017" else '0';
C1R_N <= not (ControllerOnePoll and RW_10 and PHI2_Internal);
C2R_N <= not (ControllerTwoPoll and RW_10 and PHI2_Internal);

process (Address, ReadOKSignal, RW_10, PHI2_Internal)
begin
	if (Address = x"4016" and RW_10 = '0' and ReadOKSignal = '1') then
		Data <= "ZZZZZZZZ";
		CStrobe <= Data(0);
	elsif (Address = x"4016" and RW_10 = '1' and PHI2_Internal = '1') then
		Data <= "010ZZZZZ";
	else
		Data <= "ZZZZZZZZ";
	end if;
end process;

--Bus Control
with BusControl select RW_10Signal <=
	T65RW_10 when '0',
	DMARW_10	when '1';
			
with BusControl select AddressSignal <=
	T65Address when '0',
	DMAAddress when '1';
	
T65DataIn	<= DataInSignal when BusControl = '0' else "01010101"; --????
DMADataIn	<= DataInSignal when BusControl = '1' else "01010101";
	
with BusControl select DataOutSignal <=
	T65DataOut when '0',
	DMADataOut when '1';

--Bus stuff
process (Reset_N, AddOKSignal)
begin
	if (Reset_N = '0') then
		DMAEnable <= '0';
		Address <= x"0000";
	else
		if AddOKSignal'event and AddOKSignal = '1' then
			RW_10 <= RW_10Signal;
			Address <= AddressSignal;
			if (T65Address = x"4014") then
				DMAEnable	<= '1';
			else
				DMAEnable	<= '0';		
			end if;
		end if;
	end if;
end process;

process (RW_10Signal, ReadOKSignal, WriteOKSignal, PHI2_Internal)
begin
	if (RW_10Signal = '1') then --reading
		if (PHI2_Internal = '0') then
			Data <= DataInSignal; --might be causing big-ass problems
		else
			Data <= "ZZZZZZZZ";
			if (ReadOKSignal = '1') then
				DataInSignal <= Data;
			end if;
		end if;
	else --writing
		if (PHI2_Internal = '1' and WriteOKSignal = '1') then
			Data		<= DataOutSignal;
			DataInSignal	<= Data;
		else
			--Data 		<= DataInSignal;
		end if;
	end if;
end process;

DMATransfer : process (Reset_N, PHI2_Internal)
begin
	if (Reset_N = '0') then
		TransferCount		<= "0000000000";
		TransferAddress	<= "0000000000000000";
		DMAContinue <= '0';
		T65Enable <= '1';
		BusControl <= '0';
		DMARW_10 <= '1';
		--D
	elsif (falling_edge(PHI2_Internal)) then  --may need to check timing here
		if (DMAEnable = '1') then
			DMAContinue <= '1';
		end if;
		if (DMAContinue = '1') then
			case TransferCount is
				when "0000000000" =>
					DMAAddress	<= T65DataOut & "00000000";
					TransferAddress <= unsigned(T65DataOut & "00000000") + 1;
					T65Enable <= '0';
					BusControl <= '1';
					TransferCount <= "0000000001";
				when "1000000000" =>
					T65Enable <= '1';
					BusControl <= '0';
					TransferCount <= "0000000000";
					DMAContinue <= '0';
					DMARW_10 <= '1'; --shit dude, it's amazing anything happened without this
				when others =>
					T65Enable <= '0';
					BusControl <= '1';
					TransferCount <= TransferCount + 1;
					case TransferCount(0) is
						when '0' =>
							DMARW_10 <= '1';
							DMAAddress <=  std_logic_vector(TransferAddress);
							TransferAddress <= TransferAddress + 1;
						when '1' =>
							DMARW_10 <= '0';
							DMAAddress <=  x"2004";
							DMADataOut <= DMADataIn;
					end case;
			end case;
		end if;
	end if;
end process DMATransfer;

--Port Maps	
	Clk_Div_12 : Clock_Divider
		port map (
			Clk_In				=> Global_Clk,
			Reset_N				=> Reset_N,
			Enable				=> Global_Enable,
			Clk_Out				=> PHI1_Internal,
			Clk_Out_Phi2		=> PHI2_Internal,
			Clk_Out_AddOK 		=> AddOKSignal,
			Clk_Out_WriteOK	=> WriteOKSignal,
			Clk_Out_ReadOK		=> ReadOKSignal,
			In_Out	 			=> ClockDividerTrigger
		);
	
	NES_2A03 : T65
		port map (
			Mode			=> "00",
			Res_n			=> Reset_N,
			Enable		=> T65Enable,
			Clk			=> PHI1_Internal,
			Clk_Phi2		=> PHI2_Internal,
			Clk_AddOK 	=> AddOKSignal,
			Clk_ReadOK 	=> ReadOKSignal,
			Rdy     		=> '1',	--used for single-cycle execution, not used in 2A03
			--Abort_n		=> '0',	--not used at all
			IRQ_n   		=> IRQ_N,
			NMI_n   		=> NMI_N,
			SO_n    		=> '1',	--Set Overflow, not used by NES
			R_W_n   		=> T65RW_10,
			Sync    		=> open,	--used for single-cycle execution, not used in 2A03
			ML_n    		=> open,	--used in 65C816
			VP_n    		=> open,	--used in 65C816
			VDA     		=> open,	--used in 65C816
			VPA     		=> open,	--used in 65C816
			T65Address	=> T65Address,
			T65DataIn	=> T65DataIn,
			T65DataOut	=> T65DataOut
		);
		
	CPU_RAM : SRAM
		port map (
			--Clock				=> PHI2_Internal,
			ChipSelect_N	=> (not PHI2_Internal) or (Address(15) or Address(14) or Address(13)),
			ReadEnable_N	=> not RW_10,
			WriteEnable_N	=> SRAMWriteSignal,
			OutputEnable_N	=> '0',--not WriteOKSignal,--< this is a problem :-(
			Address			=> Address (10 downto 0),
			Data				=> Data,
			Reading			=> SRAM_Reading,
			Writing			=> SRAM_Writing
		);
end;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -