repo2/common/zpu/zpu_glue.vhdl @ 445
1 | markw | ---------------------------------------------------------------------------
|
|
-- (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.std_logic_unsigned.ALL;
|
|||
use ieee.numeric_std.ALL;
|
|||
use IEEE.STD_LOGIC_MISC.all;
|
|||
library work;
|
|||
use work.zpupkg.all;
|
|||
ENTITY zpu_glue IS
|
|||
PORT
|
|||
(
|
|||
CLK : in std_logic;
|
|||
RESET : in std_logic;
|
|||
PAUSE : in std_logic;
|
|||
ZPU_DI : in std_logic_vector(31 downto 0); -- response from general memory - for areas that only support 8/16 bit set top bits to 0
|
|||
ZPU_ROM_DI : in std_logic_vector(31 downto 0); -- response from own program memory
|
|||
ZPU_RAM_DI : in std_logic_vector(31 downto 0); -- response from own stack
|
|||
ZPU_CONFIG_DI : in std_logic_vector(31 downto 0); -- response from config registers
|
|||
ZPU_DO : out std_logic_vector(31 downto 0);
|
|||
7 | markw | ZPU_ADDR_ROM_RAM : out std_logic_vector(15 downto 0); -- direct from zpu, for short paths
|
|
1 | markw | ZPU_ADDR_FETCH : out std_logic_vector(23 downto 0); -- clk->q, for longer paths
|
|
-- request
|
|||
MEMORY_FETCH : out std_logic;
|
|||
ZPU_READ_ENABLE : out std_logic;
|
|||
ZPU_32BIT_WRITE_ENABLE : out std_logic; -- common case
|
|||
ZPU_16BIT_WRITE_ENABLE : out std_logic; -- for sram (never happens yet!)
|
|||
ZPU_8BIT_WRITE_ENABLE : out std_logic; -- for hardware regs
|
|||
-- config
|
|||
ZPU_CONFIG_WRITE : out std_logic;
|
|||
277 | markw | ZPU_CONFIG_READ : out std_logic;
|
|
1 | markw | ||
-- stack request
|
|||
ZPU_STACK_WRITE : out std_logic_vector(3 downto 0);
|
|||
74 | markw | -- write to ROM!!
|
|
ZPU_ROM_WREN : out std_logic;
|
|||
1 | markw | -- response
|
|
MEMORY_READY : in std_logic
|
|||
);
|
|||
END zpu_glue;
|
|||
architecture sticky of zpu_glue is
|
|||
component ZPUMediumCore is
|
|||
generic(
|
|||
WORD_SIZE : integer:=32; -- 16/32 (2**wordPower)
|
|||
ADDR_W : integer:=24; -- Total address space width (incl. I/O)
|
|||
MEM_W : integer:=16; -- Memory (prog+data+stack) width - stack at end of memory - so end of sdram. 32K ROM, 32K RAM (MAX)
|
|||
D_CARE_VAL : std_logic:='X'; -- Value used to fill the unsused bits
|
|||
MULT_PIPE : boolean:=false; -- Pipeline multiplication
|
|||
BINOP_PIPE : integer range 0 to 2:=0; -- Pipeline binary operations (-, =, < and <=)
|
|||
ENA_LEVEL0 : boolean:=true; -- eq, loadb, neqbranch and pushspadd
|
|||
ENA_LEVEL1 : boolean:=true; -- lessthan, ulessthan, mult, storeb, callpcrel and sub
|
|||
ENA_LEVEL2 : boolean:=true; -- lessthanorequal, ulessthanorequal, call and poppcrel
|
|||
ENA_LSHR : boolean:=true; -- lshiftright
|
|||
ENA_IDLE : boolean:=false; -- Enable the enable_i input
|
|||
FAST_FETCH : boolean:=true); -- Merge the st_fetch with the st_execute states
|
|||
port(
|
|||
clk_i : in std_logic; -- CPU Clock
|
|||
reset_i : in std_logic; -- Sync Reset
|
|||
enable_i : in std_logic; -- Hold the CPU (after reset)
|
|||
break_o : out std_logic; -- Break instruction executed
|
|||
dbg_o : out zpu_dbgo_t; -- Debug outputs (i.e. trace log)
|
|||
-- Memory interface
|
|||
mem_busy_i : in std_logic; -- Memory is busy
|
|||
data_i : in unsigned(WORD_SIZE-1 downto 0); -- Data from mem
|
|||
data_o : out unsigned(WORD_SIZE-1 downto 0); -- Data to mem
|
|||
addr_o : out unsigned(ADDR_W-1 downto 0); -- Memory address
|
|||
write_en_o : out std_logic; -- Memory write enable (32-bit)
|
|||
read_en_o : out std_logic; -- Memory read enable (32-bit)
|
|||
byte_read_o : out std_logic;
|
|||
byte_write_o : out std_logic;
|
|||
short_write_o: out std_logic); -- never happens
|
|||
end component;
|
|||
signal zpu_addr_unsigned : unsigned(23 downto 0);
|
|||
signal zpu_do_unsigned : unsigned(31 downto 0);
|
|||
signal ZPU_DI_unsigned : unsigned(31 downto 0);
|
|||
signal zpu_break : std_logic;
|
|||
signal zpu_debug : zpu_dbgo_t;
|
|||
signal zpu_mem_busy : std_logic;
|
|||
signal zpu_memory_fetch_pending_next : std_logic;
|
|||
signal zpu_memory_fetch_pending_reg : std_logic;
|
|||
signal ZPU_32bit_READ_ENABLE_temp : std_logic;
|
|||
signal ZPU_8bit_READ_ENABLE_temp : std_logic;
|
|||
signal ZPU_READ_temp : std_logic;
|
|||
signal ZPU_32BIT_WRITE_ENABLE_temp : std_logic;
|
|||
signal ZPU_16BIT_WRITE_ENABLE_temp : std_logic;
|
|||
signal ZPU_8BIT_WRITE_ENABLE_temp : std_logic;
|
|||
signal ZPU_WRITE_temp : std_logic;
|
|||
signal ZPU_32BIT_WRITE_ENABLE_next : std_logic;
|
|||
signal ZPU_16BIT_WRITE_ENABLE_next : std_logic;
|
|||
signal ZPU_8BIT_WRITE_ENABLE_next : std_logic;
|
|||
signal ZPU_READ_next : std_logic;
|
|||
signal ZPU_32BIT_WRITE_ENABLE_reg : std_logic;
|
|||
signal ZPU_16BIT_WRITE_ENABLE_reg : std_logic;
|
|||
signal ZPU_8BIT_WRITE_ENABLE_reg : std_logic;
|
|||
signal ZPU_READ_reg : std_logic;
|
|||
signal block_mem : std_logic;
|
|||
signal config_mem : std_logic;
|
|||
signal special_mem : std_logic;
|
|||
signal result_next : std_logic_vector(4 downto 0);
|
|||
signal result_reg : std_logic_vector(4 downto 0);
|
|||
constant result_external : std_logic_vector(4 downto 0) := "00000";
|
|||
constant result_ram : std_logic_vector(4 downto 0) := "00001";
|
|||
constant result_ram_8bit_0 : std_logic_vector(4 downto 0) := "00010";
|
|||
constant result_ram_8bit_1 : std_logic_vector(4 downto 0) := "00011";
|
|||
constant result_ram_8bit_2 : std_logic_vector(4 downto 0) := "00100";
|
|||
constant result_ram_8bit_3 : std_logic_vector(4 downto 0) := "00101";
|
|||
constant result_rom : std_logic_vector(4 downto 0) := "00110";
|
|||
constant result_rom_8bit_0 : std_logic_vector(4 downto 0) := "00111";
|
|||
constant result_rom_8bit_1 : std_logic_vector(4 downto 0) := "01000";
|
|||
constant result_rom_8bit_2 : std_logic_vector(4 downto 0) := "01001";
|
|||
constant result_rom_8bit_3 : std_logic_vector(4 downto 0) := "01010";
|
|||
constant result_config : std_logic_vector(4 downto 0) := "01011";
|
|||
constant result_external_special : std_logic_vector(4 downto 0) := "01100";
|
|||
signal request_type : std_logic_vector(4 downto 0);
|
|||
signal zpu_di_use : std_logic_vector(31 downto 0);
|
|||
277 | markw | signal memory_access : std_logic;
|
|
1 | markw | ||
-- 1 cycle delay on memory read - needed to allow running at higher clock
|
|||
signal zpu_di_next : std_logic_vector(31 downto 0);
|
|||
signal zpu_di_reg : std_logic_vector(31 downto 0);
|
|||
signal memory_ready_next : std_logic;
|
|||
signal memory_ready_reg : std_logic;
|
|||
signal zpu_enable : std_logic;
|
|||
signal zpu_addr_next : std_logic_vector(23 downto 0);
|
|||
signal zpu_addr_reg : std_logic_vector(23 downto 0);
|
|||
signal ZPU_DO_next : std_logic_vector(31 downto 0);
|
|||
signal ZPU_DO_reg : std_logic_vector(31 downto 0);
|
|||
begin
|
|||
-- register
|
|||
process(clk,reset)
|
|||
begin
|
|||
if (reset='1') then
|
|||
zpu_memory_fetch_pending_reg <= '0';
|
|||
result_reg <= result_rom;
|
|||
zpu_di_reg <= (others=>'0');
|
|||
zpu_do_reg <= (others=>'0');
|
|||
memory_ready_reg <= '0';
|
|||
zpu_addr_reg <= (others=>'0');
|
|||
ZPU_32BIT_WRITE_ENABLE_reg <= '0';
|
|||
ZPU_16BIT_WRITE_ENABLE_reg <= '0';
|
|||
ZPU_8BIT_WRITE_ENABLE_reg <= '0';
|
|||
ZPU_READ_reg <= '0';
|
|||
elsif (clk'event and clk='1') then
|
|||
zpu_memory_fetch_pending_reg <= zpu_memory_fetch_pending_next;
|
|||
result_reg <= result_next;
|
|||
zpu_di_reg <= zpu_di_next;
|
|||
zpu_do_reg <= zpu_do_next;
|
|||
277 | markw | memory_ready_reg <= memory_ready_next;
|
|
1 | markw | zpu_addr_reg <=zpu_addr_next;
|
|
ZPU_32BIT_WRITE_ENABLE_reg <= ZPU_32BIT_WRITE_ENABLE_next;
|
|||
ZPU_16BIT_WRITE_ENABLE_reg <= ZPU_16BIT_WRITE_ENABLE_next;
|
|||
ZPU_8BIT_WRITE_ENABLE_reg <= ZPU_8BIT_WRITE_ENABLE_next;
|
|||
ZPU_READ_reg <= ZPU_READ_next;
|
|||
end if;
|
|||
end process;
|
|||
-- a little glue
|
|||
process(zpu_ADDR_unsigned)
|
|||
begin
|
|||
block_mem <= '0';
|
|||
config_mem <= '0';
|
|||
special_mem <= '0';
|
|||
-- $00000-$0FFFF = Own ROM/RAM
|
|||
-- $10000-$1FFFF = Atari
|
|||
-- $20000-$2FFFF = Atari - savestate (gtia/antic/pokey have memory behind them)
|
|||
-- $40000-$4FFFF = Config area
|
|||
if (or_reduce(std_logic_vector(zpu_ADDR_unsigned(23 downto 21))) = '0') then -- special area
|
|||
block_mem <= not(zpu_addr_unsigned(18) or zpu_addr_unsigned(17) or zpu_addr_unsigned(16));
|
|||
config_mem <= zpu_addr_unsigned(18);
|
|||
special_mem <= zpu_addr_unsigned(17);
|
|||
end if;
|
|||
end process;
|
|||
ZPU_READ_TEMP <= zpu_32bit_read_enable_temp or zpu_8BIT_read_enable_temp;
|
|||
ZPU_WRITE_TEMP<= zpu_32BIT_WRITE_ENABLE_temp or zpu_16BIT_WRITE_ENABLE_temp or zpu_8BIT_WRITE_ENABLE_temp;
|
|||
277 | markw | process(zpu_addr_reg,pause,memory_ready,zpu_memory_fetch_pending_next,request_type, zpu_memory_fetch_pending_reg, memory_ready_reg, zpu_ADDR_unsigned, zpu_8bit_read_enable_temp, zpu_write_temp, result_reg, block_mem, config_mem, special_mem, memory_access,
|
|
1 | markw | zpu_read_reg,zpu_8BIT_WRITE_ENABLE_reg, zpu_16BIT_WRITE_ENABLE_reg, zpu_32BIT_WRITE_ENABLE_reg,
|
|
zpu_read_temp,zpu_8BIT_WRITE_ENABLE_temp, zpu_16BIT_WRITE_ENABLE_temp, zpu_32BIT_WRITE_ENABLE_temp,
|
|||
zpu_do_unsigned, zpu_do_reg
|
|||
)
|
|||
begin
|
|||
zpu_memory_fetch_pending_next <= zpu_memory_fetch_pending_reg;
|
|||
result_next <= result_reg;
|
|||
memory_ready_next <= memory_ready;
|
|||
zpu_stACK_WRITE <= (others=>'0');
|
|||
74 | markw | ZPU_ROM_WREN <= '0';
|
|
1 | markw | ZPU_config_write <= '0';
|
|
277 | markw | ZPU_config_read <= '0';
|
|
1 | markw | zpu_addr_next <= zpu_addr_reg;
|
|
zpu_do_next <= zpu_do_reg;
|
|||
ZPU_MEM_BUSY <= pause;
|
|||
MEMORY_ACCESS <= zpu_READ_temp or ZPU_WRITE_temp;
|
|||
if (memory_access = '1') then
|
|||
zpu_do_next <= std_logic_vector(zpu_do_unsigned);
|
|||
end if;
|
|||
memory_fetch <= zpu_memory_fetch_pending_reg;
|
|||
zpu_read_next <= zpu_read_reg;
|
|||
zpu_8bit_write_enable_next <= zpu_8bit_write_enable_reg;
|
|||
zpu_16bit_write_enable_next <= zpu_16bit_write_enable_reg;
|
|||
zpu_32bit_write_enable_next <= zpu_32bit_write_enable_reg;
|
|||
277 | markw | request_type <= config_mem&block_mem&zpu_addr_unsigned(15)&memory_access&zpu_memory_fetch_pending_reg;
|
|
1 | markw | case request_type is
|
|
when "00010"|"00110" =>
|
|||
zpu_memory_fetch_pending_next <= '1';
|
|||
if (special_mem='0') then
|
|||
result_next <= result_external;
|
|||
else
|
|||
result_next <= result_external_special;
|
|||
end if;
|
|||
ZPU_MEM_BUSY <= '1';
|
|||
zpu_addr_next <= std_logic_vector(zpu_addr_unsigned);
|
|||
zpu_read_next <= zpu_read_temp;
|
|||
zpu_8bit_write_enable_next <= zpu_8bit_write_enable_temp;
|
|||
zpu_16bit_write_enable_next <= zpu_16bit_write_enable_temp;
|
|||
zpu_32bit_write_enable_next <= zpu_32bit_write_enable_temp;
|
|||
when "01010" =>
|
|||
7 | markw | if (zpu_8bit_read_enable_temp='1') then
|
|
case (zpu_addr_unsigned(1 downto 0)) is
|
|||
when "00" =>
|
|||
result_next <= result_rom_8bit_3;
|
|||
when "01" =>
|
|||
result_next <= result_rom_8bit_2;
|
|||
when "10" =>
|
|||
result_next <= result_rom_8bit_1;
|
|||
when "11" =>
|
|||
result_next <= result_rom_8bit_0;
|
|||
when others =>
|
|||
--nop
|
|||
end case;
|
|||
1 | markw | else
|
|
7 | markw | result_next <= result_rom;
|
|
1 | markw | end if;
|
|
74 | markw | ZPU_ROM_WREN <= ZPU_WRITE_TEMP;
|
|
1 | markw | ZPU_MEM_BUSY <= '1';
|
|
zpu_addr_next <= std_logic_vector(zpu_addr_unsigned);
|
|||
when "01110" =>
|
|||
if (zpu_8bit_read_enable_temp='1' or zpu_8BIT_WRITE_ENABLE_temp='1') then
|
|||
case (zpu_addr_unsigned(1 downto 0)) is
|
|||
when "00" =>
|
|||
result_next <= result_ram_8bit_3;
|
|||
ZPU_STACK_WRITE(3) <= zpu_8BIT_write_enable_temp;
|
|||
when "01" =>
|
|||
result_next <= result_ram_8bit_2;
|
|||
ZPU_STACK_WRITE(2) <= zpu_8BIT_write_enable_temp;
|
|||
when "10" =>
|
|||
result_next <= result_ram_8bit_1;
|
|||
ZPU_STACK_WRITE(1) <= zpu_8BIT_write_enable_temp;
|
|||
when "11" =>
|
|||
result_next <= result_ram_8bit_0;
|
|||
ZPU_STACK_WRITE(0) <= zpu_8BIT_write_enable_temp;
|
|||
when others =>
|
|||
--nop
|
|||
end case;
|
|||
else
|
|||
result_next <= result_ram;
|
|||
ZPU_STACK_WRITE <= (others=>zpu_write_temp);
|
|||
end if;
|
|||
ZPU_MEM_BUSY <= '1';
|
|||
zpu_addr_next <= std_logic_vector(zpu_addr_unsigned);
|
|||
when "10110"|"10010" =>
|
|||
result_next <= result_config;
|
|||
ZPU_MEM_BUSY <= '1';
|
|||
ZPU_config_write <= ZPU_WRITE_temp;
|
|||
277 | markw | ZPU_config_read <= ZPU_READ_temp;
|
|
1 | markw | zpu_addr_next <= std_logic_vector(zpu_addr_unsigned);
|
|
when "00001"|"00011"|"00101"|"00111"|"01001"|"01011"|"01101"|"01111"|
|
|||
"10001"|"10011"|"10101"|"10111"|"11001"|"11011"|"11101"|"11111"|"00X01" =>
|
|||
277 | markw | ZPU_MEM_BUSY <= not(memory_ready_reg) or pause;
|
|
zpu_memory_fetch_pending_next <= not(memory_ready);
|
|||
1 | markw | when others =>
|
|
-- nop
|
|||
end case;
|
|||
end process;
|
|||
zpu_di_next <= zpu_di;
|
|||
7 | markw | process(result_reg, zpu_di_reg, zpu_rom_di, zpu_ram_di, zpu_config_di)
|
|
1 | markw | begin
|
|
zpu_di_use <= (others=>'0');
|
|||
case result_reg is
|
|||
when result_external =>
|
|||
zpu_di_use <= zpu_di_reg;
|
|||
when result_external_special =>
|
|||
zpu_di_use(7 downto 0) <= zpu_di_reg(15 downto 8);
|
|||
when result_rom =>
|
|||
zpu_di_use <= zpu_rom_DI;
|
|||
when result_rom_8bit_0 =>
|
|||
zpu_di_use(7 downto 0) <= zpu_rom_DI(7 downto 0);
|
|||
when result_rom_8bit_1 =>
|
|||
zpu_di_use(7 downto 0) <= zpu_rom_DI(15 downto 8);
|
|||
when result_rom_8bit_2 =>
|
|||
zpu_di_use(7 downto 0) <= zpu_rom_DI(23 downto 16);
|
|||
when result_rom_8bit_3 =>
|
|||
zpu_di_use(7 downto 0) <= zpu_rom_DI(31 downto 24);
|
|||
when result_ram =>
|
|||
zpu_di_use <= zpu_ram_DI;
|
|||
when result_ram_8bit_0 =>
|
|||
zpu_di_use(7 downto 0) <= zpu_ram_DI(7 downto 0);
|
|||
when result_ram_8bit_1 =>
|
|||
zpu_di_use(7 downto 0) <= zpu_ram_DI(15 downto 8);
|
|||
when result_ram_8bit_2 =>
|
|||
zpu_di_use(7 downto 0) <= zpu_ram_DI(23 downto 16);
|
|||
when result_ram_8bit_3 =>
|
|||
zpu_di_use(7 downto 0) <= zpu_ram_DI(31 downto 24);
|
|||
when result_config =>
|
|||
zpu_di_use <= zpu_config_di;
|
|||
when others =>
|
|||
-- nothing
|
|||
end case;
|
|||
end process;
|
|||
-- zpu itself
|
|||
--zpu_enable <= enable and not(pause);
|
|||
zpu_enable <= '1'; -- does nothing useful...
|
|||
myzpu: ZPUMediumCore
|
|||
port map (clk_i=>clk, reset_i=>reset,enable_i=>zpu_enable,break_o=>zpu_break,dbg_o=>zpu_debug,mem_busy_i=>ZPU_MEM_BUSY,
|
|||
data_i=>zpu_di_unsigned,data_o=>zpu_do_unsigned,addr_o=>zpu_addr_unsigned,write_en_o=>zpu_32bit_write_enable_temp,read_en_o=>zpu_32bit_read_enable_temp,
|
|||
byte_read_o=>zpu_8bit_read_enable_temp, byte_write_o=>zpu_8bit_write_enable_temp,short_write_o=>zpu_16bit_write_enable_temp);
|
|||
zpu_di_unsigned <= unsigned(zpu_di_use);
|
|||
zpu_do <= zpu_do_next;
|
|||
7 | markw | ZPU_ADDR_ROM_RAM <= zpu_addr_next(15 downto 0);
|
|
1 | markw | ZPU_ADDR_FETCH <= zpu_addr_reg;
|
|
zpu_read_enable <= zpu_read_reg;
|
|||
zpu_8bit_write_enable <= zpu_8bit_write_enable_reg;
|
|||
zpu_16bit_write_enable <= zpu_16bit_write_enable_reg;
|
|||
zpu_32bit_write_enable <= zpu_32bit_write_enable_reg;
|
|||
end sticky;
|