|
---------------------------------------------------------------------------
|
|
-- (c) 2013 mark watson
|
|
-- I am happy for anyone to use this for non-commercial use.
|
|
-- If my vhdl files are used commercially or otherwise sold,
|
|
-- please contact me for explicit permission at scrameta (gmail).
|
|
-- This applies for source and binary form and derived works.
|
|
---------------------------------------------------------------------------
|
|
|
|
LIBRARY ieee;
|
|
USE ieee.std_logic_1164.all;
|
|
use ieee.numeric_std.all;
|
|
USE ieee.math_real.log2;
|
|
USE ieee.math_real.ceil;
|
|
|
|
LIBRARY work;
|
|
|
|
ENTITY zpucore IS
|
|
GENERIC
|
|
(
|
|
platform : integer := 1; -- So ROM can detect which type of system...
|
|
spi_clock_div : integer := 4; -- see notes on zpu_config_regs
|
|
memory : integer := 4096; -- up to 32K allowed
|
|
usb : integer := 0;
|
|
nMHz_clock_div : integer
|
|
);
|
|
PORT
|
|
(
|
|
-- standard...
|
|
CLK : in std_logic;
|
|
RESET_N : in std_logic;
|
|
|
|
-- dma bus master (with many waitstates...)
|
|
ZPU_ADDR_FETCH : out std_logic_vector(23 downto 0);
|
|
ZPU_DATA_OUT : out std_logic_vector(31 downto 0);
|
|
ZPU_FETCH : out std_logic;
|
|
ZPU_32BIT_WRITE_ENABLE : out std_logic;
|
|
ZPU_16BIT_WRITE_ENABLE : out std_logic;
|
|
ZPU_8BIT_WRITE_ENABLE : out std_logic;
|
|
ZPU_READ_ENABLE : out std_logic;
|
|
ZPU_MEMORY_READY : in std_logic;
|
|
ZPU_MEMORY_DATA : in std_logic_vector(31 downto 0);
|
|
|
|
-- rom bus master
|
|
-- data on next cycle after addr
|
|
ZPU_ADDR_ROM : out std_logic_vector(15 downto 0);
|
|
ZPU_ROM_DATA : in std_logic_vector(31 downto 0);
|
|
ZPU_ROM_WREN : out std_logic;
|
|
|
|
-- change clock support
|
|
ZPU_PLL_WRITE : out std_logic;
|
|
ZPU_PLL_DATA : out std_logic_vector(31 downto 0);
|
|
ZPU_PLL_ADDR : out std_logic_vector(7 downto 2);
|
|
|
|
-- spi master
|
|
-- Too painful to bit bang spi from zpu, so we have a hardware master in here
|
|
--ZPU_SD_DAT0 : IN STD_LOGIC;
|
|
--ZPU_SD_CLK : OUT STD_LOGIC;
|
|
--ZPU_SD_CMD : OUT STD_LOGIC;
|
|
--ZPU_SD_DAT3 : OUT STD_LOGIC;
|
|
ZPU_SPI_DI : IN STD_LOGIC;
|
|
ZPU_SPI_CLK : OUT STD_LOGIC;
|
|
ZPU_SPI_DO : OUT STD_LOGIC;
|
|
ZPU_SPI_SELECT0 : OUT STD_LOGIC;
|
|
ZPU_SPI_SELECT1 : OUT STD_LOGIC;
|
|
|
|
-- SIO
|
|
-- Ditto for speaking to Atari, we have a built in Pokey
|
|
ZPU_POKEY_ENABLE : in std_logic; -- if run at 1.79MHz we can use standard dividers...
|
|
ZPU_SIO_TXD : out std_logic;
|
|
ZPU_SIO_RXD : in std_logic;
|
|
ZPU_SIO_COMMAND : in std_logic;
|
|
ZPU_SIO_CLK : in std_logic;
|
|
|
|
-- external control
|
|
-- switches etc. sector DMA blah blah.
|
|
ZPU_IN1 : in std_logic_vector(31 downto 0);
|
|
ZPU_IN2 : in std_logic_vector(31 downto 0);
|
|
ZPU_IN3 : in std_logic_vector(31 downto 0);
|
|
ZPU_IN4 : in std_logic_vector(31 downto 0);
|
|
|
|
-- ouputs - e.g. Atari system control, halt, throttle, rom select
|
|
ZPU_OUT1 : out std_logic_vector(31 downto 0);
|
|
ZPU_OUT2 : out std_logic_vector(31 downto 0);
|
|
ZPU_OUT3 : out std_logic_vector(31 downto 0);
|
|
ZPU_OUT4 : out std_logic_vector(31 downto 0);
|
|
ZPU_OUT5 : out std_logic_vector(31 downto 0);
|
|
ZPU_OUT6 : out std_logic_vector(31 downto 0);
|
|
ZPU_OUT7 : out std_logic_vector(31 downto 0);
|
|
ZPU_OUT8 : out std_logic_vector(31 downto 0);
|
|
|
|
-- nMHz clock, for timer. Divided by n before use.
|
|
CLK_nMHz : in std_logic;
|
|
|
|
-- USB host
|
|
CLK_USB : in std_logic := '0';
|
|
|
|
USBWireVPin :in std_logic_vector(usb-1 downto 0) := (others=>'0');
|
|
USBWireVMin :in std_logic_vector(usb-1 downto 0) := (others=>'0');
|
|
USBWireVPout :out std_logic_vector(usb-1 downto 0);
|
|
USBWireVMout :out std_logic_vector(usb-1 downto 0);
|
|
USBWireOE_n :out std_logic_vector(usb-1 downto 0);
|
|
|
|
-- I2C (400k)
|
|
i2c0_sda_in : in std_logic := '1';
|
|
i2c0_scl_in : in std_logic := '1';
|
|
i2c0_sda_wen : out std_logic;
|
|
i2c0_scl_wen : out std_logic;
|
|
|
|
i2c1_sda_in : in std_logic := '1';
|
|
i2c1_scl_in : in std_logic := '1';
|
|
i2c1_sda_wen : out std_logic;
|
|
i2c1_scl_wen : out std_logic
|
|
);
|
|
END zpucore;
|
|
|
|
ARCHITECTURE vhdl OF zpucore IS
|
|
signal ZPU_PAUSE : std_logic;
|
|
signal ZPU_RESET : std_logic;
|
|
|
|
signal ZPU_DO : std_logic_vector(31 downto 0);
|
|
|
|
signal ZPU_ADDR_ROM_RAM : std_logic_vector(15 downto 0);
|
|
|
|
signal ZPU_RAM_DATA : std_logic_vector(31 downto 0);
|
|
signal ZPU_STACK_WRITE : std_logic_vector(3 downto 0);
|
|
|
|
signal ZPU_CONFIG_DO : std_logic_vector(31 downto 0);
|
|
signal ZPU_CONFIG_WRITE_ENABLE : std_logic;
|
|
signal ZPU_CONFIG_READ_ENABLE : std_logic;
|
|
|
|
signal ZPU_SD_DMA_ADDR : std_logic_vector(15 downto 0);
|
|
signal ZPU_SD_DMA_DATA : std_logic_vector(7 downto 0);
|
|
signal ZPU_SD_DMA_WRITE : std_logic;
|
|
signal ZPU_SD_DMA_WRITE_BITS : std_logic_vector(3 downto 0);
|
|
|
|
signal ZPU_ADDR_ROM_RAM_DMA : std_logic_vector(15 downto 0);
|
|
signal ZPU_DO_DMA : std_logic_vector(31 downto 0);
|
|
signal ZPU_STACK_WRITE_DMA : std_logic_vector(3 downto 0);
|
|
|
|
constant memory_bits: integer := integer(ceil(log2(real(memory))));
|
|
BEGIN
|
|
|
|
ZPU_RESET <= not(reset_n);
|
|
zpu_and_glue : entity work.zpu_glue
|
|
PORT MAP(CLK => CLK,
|
|
RESET => ZPU_RESET,
|
|
PAUSE => ZPU_PAUSE,
|
|
MEMORY_READY => ZPU_MEMORY_READY,
|
|
ZPU_CONFIG_DI => ZPU_CONFIG_DO,
|
|
ZPU_DI => ZPU_MEMORY_DATA,
|
|
ZPU_RAM_DI => ZPU_RAM_DATA,
|
|
ZPU_ROM_DI => ZPU_ROM_DATA,
|
|
MEMORY_FETCH => ZPU_FETCH,
|
|
ZPU_READ_ENABLE => ZPU_READ_ENABLE,
|
|
ZPU_32BIT_WRITE_ENABLE => ZPU_32BIT_WRITE_ENABLE,
|
|
ZPU_16BIT_WRITE_ENABLE => ZPU_16BIT_WRITE_ENABLE,
|
|
ZPU_8BIT_WRITE_ENABLE => ZPU_8BIT_WRITE_ENABLE,
|
|
ZPU_CONFIG_WRITE => ZPU_CONFIG_WRITE_ENABLE,
|
|
ZPU_CONFIG_READ => ZPU_CONFIG_READ_ENABLE,
|
|
ZPU_ADDR_FETCH => ZPU_ADDR_FETCH,
|
|
ZPU_ADDR_ROM_RAM => ZPU_ADDR_ROM_RAM,
|
|
ZPU_DO => ZPU_DO,
|
|
ZPU_STACK_WRITE => ZPU_STACK_WRITE,
|
|
ZPU_ROM_WREN => ZPU_ROM_WREN);
|
|
|
|
config_regs : entity work.zpu_config_regs
|
|
GENERIC MAP (
|
|
platform => platform,
|
|
spi_clock_div => spi_clock_div,
|
|
usb => usb,
|
|
nmhz_clock_div => nmhz_clock_div
|
|
)
|
|
PORT MAP (
|
|
CLK => CLK,
|
|
RESET_N => RESET_N,
|
|
|
|
POKEY_ENABLE => ZPU_POKEY_ENABLE,
|
|
|
|
ADDR => ZPU_ADDR_ROM_RAM(12 DOWNTO 2),
|
|
CPU_DATA_IN => ZPU_DO,
|
|
WR_EN => ZPU_CONFIG_WRITE_ENABLE,
|
|
RD_EN => ZPU_CONFIG_READ_ENABLE,
|
|
|
|
IN1 => ZPU_IN1,
|
|
IN2 => ZPU_IN2,
|
|
IN3 => ZPU_IN3,
|
|
IN4 => ZPU_IN4,
|
|
|
|
OUT1 => ZPU_OUT1,
|
|
OUT2 => ZPU_OUT2,
|
|
OUT3 => ZPU_OUT3,
|
|
OUT4 => ZPU_OUT4,
|
|
OUT5 => ZPU_OUT5,
|
|
OUT6 => ZPU_OUT6,
|
|
OUT7 => ZPU_OUT7,
|
|
OUT8 => ZPU_OUT8,
|
|
|
|
PLL_WRITE => ZPU_PLL_WRITE,
|
|
PLL_DATA => ZPU_PLL_DATA,
|
|
PLL_ADDR => ZPU_PLL_ADDR,
|
|
|
|
SPI_DI => ZPU_SPI_DI,
|
|
SPI_CLK => ZPU_SPI_CLK,
|
|
SPI_DO => ZPU_SPI_DO,
|
|
SPI_SELECT0 => ZPU_SPI_SELECT0,
|
|
SPI_SELECT1 => ZPU_SPI_SELECT1,
|
|
|
|
--SPI_DI => ZPU_SD_DAT0,
|
|
--SPI_CLK => ZPU_SD_CLK,
|
|
--SPI_DO => ZPU_SD_CMD,
|
|
--SPI_SELECT0 => ZPU_SD_DAT3,
|
|
--SPI_SELECT1 => ZPU_SD_DAT3,
|
|
|
|
SIO_DATA_IN => ZPU_SIO_TXD,
|
|
SIO_DATA_OUT => ZPU_SIO_RXD,
|
|
SIO_COMMAND => ZPU_SIO_COMMAND,
|
|
SIO_CLK_OUT => ZPU_SIO_CLK,
|
|
|
|
sd_addr => ZPU_SD_DMA_ADDR,
|
|
sd_data => ZPU_SD_DMA_DATA,
|
|
sd_write => ZPU_SD_DMA_WRITE,
|
|
|
|
DATA_OUT => ZPU_CONFIG_DO,
|
|
PAUSE_ZPU => ZPU_PAUSE,
|
|
|
|
CLK_nMHz => CLK_nMHz,
|
|
|
|
CLK_USB => CLK_USB,
|
|
|
|
USBWireVPin => USBWireVPin,
|
|
USBWireVMin => USBWireVMin,
|
|
USBWireVPout => USBWireVPout,
|
|
USBWireVMout => USBWireVMout,
|
|
USBWireOE_n => USBWireOE_n,
|
|
|
|
i2c0_sda_in => i2c0_sda_in,
|
|
i2c0_scl_in => i2c0_scl_in,
|
|
i2c0_sda_wen => i2c0_sda_wen,
|
|
i2c0_scl_wen => i2c0_scl_wen,
|
|
i2c1_sda_in => i2c1_sda_in,
|
|
i2c1_scl_in => i2c1_scl_in,
|
|
i2c1_sda_wen => i2c1_sda_wen,
|
|
i2c1_scl_wen => i2c1_scl_wen
|
|
);
|
|
|
|
decode_addr1 : entity work.complete_address_decoder
|
|
generic map(width=>2)
|
|
port map (addr_in=>ZPU_SD_DMA_ADDR(1 downto 0), addr_decoded=>ZPU_SD_DMA_WRITE_BITS);
|
|
|
|
process(ZPU_DO, ZPU_ADDR_ROM_RAM, ZPU_STACK_WRITE, ZPU_SD_DMA_ADDR, ZPU_SD_DMA_DATA, ZPU_SD_DMA_WRITE, ZPU_SD_DMA_WRITE_BITS)
|
|
begin
|
|
ZPU_DO_DMA <= ZPU_DO;
|
|
ZPU_ADDR_ROM_RAM_DMA <= ZPU_ADDR_ROM_RAM;
|
|
ZPU_STACK_WRITE_DMA <= ZPU_STACK_WRITE;
|
|
|
|
if (ZPU_SD_DMA_WRITE = '1') then
|
|
ZPU_DO_DMA <= ZPU_SD_DMA_DATA&ZPU_SD_DMA_DATA&ZPU_SD_DMA_DATA&ZPU_SD_DMA_DATA;
|
|
ZPU_ADDR_ROM_RAM_DMA <= ZPU_SD_DMA_ADDR(15 downto 2)&"00";
|
|
ZPU_STACK_WRITE_DMA <= ZPU_SD_DMA_WRITE_BITS(0)&ZPU_SD_DMA_WRITE_BITS(1)&ZPU_SD_DMA_WRITE_BITS(2)&ZPU_SD_DMA_WRITE_BITS(3);
|
|
end if;
|
|
|
|
end process;
|
|
|
|
ram_31_24 : entity work.generic_ram_infer
|
|
GENERIC MAP
|
|
(
|
|
ADDRESS_WIDTH => memory_bits-2,
|
|
SPACE => memory/4,
|
|
DATA_WIDTH => 8
|
|
)
|
|
PORT MAP
|
|
(
|
|
we => ZPU_STACK_WRITE_DMA(3),
|
|
clock => CLK,
|
|
address => ZPU_ADDR_ROM_RAM_DMA(memory_bits-1 DOWNTO 2),
|
|
data => ZPU_DO_DMA(31 DOWNTO 24),
|
|
q => ZPU_RAM_DATA(31 DOWNTO 24)
|
|
);
|
|
|
|
ram23_16 : entity work.generic_ram_infer
|
|
GENERIC MAP
|
|
(
|
|
ADDRESS_WIDTH => memory_bits-2,
|
|
SPACE => memory/4,
|
|
DATA_WIDTH => 8
|
|
)
|
|
PORT MAP
|
|
(
|
|
we => ZPU_STACK_WRITE_DMA(2),
|
|
clock => CLK,
|
|
address => ZPU_ADDR_ROM_RAM_DMA(memory_bits-1 DOWNTO 2),
|
|
data => ZPU_DO_DMA(23 DOWNTO 16),
|
|
q => ZPU_RAM_DATA(23 DOWNTO 16)
|
|
);
|
|
|
|
ram_15_8 : entity work.generic_ram_infer
|
|
GENERIC MAP
|
|
(
|
|
ADDRESS_WIDTH => memory_bits-2,
|
|
SPACE => memory/4,
|
|
DATA_WIDTH => 8
|
|
)
|
|
PORT MAP
|
|
(
|
|
we => ZPU_STACK_WRITE_DMA(1),
|
|
clock => CLK,
|
|
address => ZPU_ADDR_ROM_RAM_DMA(memory_bits-1 DOWNTO 2),
|
|
data => ZPU_DO_DMA(15 DOWNTO 8),
|
|
q => ZPU_RAM_DATA(15 DOWNTO 8)
|
|
);
|
|
|
|
ram_7_0 : entity work.generic_ram_infer
|
|
GENERIC MAP
|
|
(
|
|
ADDRESS_WIDTH => memory_bits-2,
|
|
SPACE => memory/4,
|
|
DATA_WIDTH => 8
|
|
)
|
|
PORT MAP
|
|
(
|
|
we => ZPU_STACK_WRITE_DMA(0),
|
|
clock => CLK,
|
|
address => ZPU_ADDR_ROM_RAM_DMA(memory_bits-1 DOWNTO 2),
|
|
data => ZPU_DO_DMA(7 DOWNTO 0),
|
|
q => ZPU_RAM_DATA(7 DOWNTO 0)
|
|
);
|
|
|
|
-- OUTPUT
|
|
ZPU_ADDR_ROM <= ZPU_ADDR_ROM_RAM;
|
|
ZPU_DATA_OUT <= ZPU_DO;
|
|
|
|
end vhdl;
|