--------------------------------------------------------------------------- -- (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); ZPU_ADDR_ROM_RAM : out std_logic_vector(15 downto 0); -- direct from zpu, for short paths 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; ZPU_CONFIG_READ : out std_logic; -- stack request ZPU_STACK_WRITE : out std_logic_vector(3 downto 0); -- write to ROM!! ZPU_ROM_WREN : out std_logic; -- 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); signal memory_access : std_logic; -- 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; memory_ready_reg <= memory_ready_next; 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; 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, 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'); ZPU_ROM_WREN <= '0'; ZPU_config_write <= '0'; ZPU_config_read <= '0'; 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; request_type <= config_mem&block_mem&(zpu_addr_unsigned(14) and zpu_addr_unsigned(15))&memory_access&zpu_memory_fetch_pending_reg; 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" => 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; else result_next <= result_rom; end if; ZPU_ROM_WREN <= ZPU_WRITE_TEMP; 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; ZPU_config_read <= ZPU_READ_temp; 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" => ZPU_MEM_BUSY <= not(memory_ready_reg) or pause; zpu_memory_fetch_pending_next <= not(memory_ready); when others => -- nop end case; end process; zpu_di_next <= zpu_di; process(result_reg, zpu_di_reg, zpu_rom_di, zpu_ram_di, zpu_config_di) 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; ZPU_ADDR_ROM_RAM <= zpu_addr_next(15 downto 0); 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;