library ieee; use ieee.std_logic_1164.all; library work; use work.zpu_config.all; use work.zpupkg.all; entity zpuio is port ( areset : in std_logic; cpu_clk : in std_logic; clk_status : in std_logic_vector(2 downto 0); cpu_din : in std_logic_vector(15 downto 0); cpu_a : in std_logic_vector(20 downto 0); cpu_we : in std_logic_vector(1 downto 0); cpu_re : in std_logic; cpu_dout : inout std_logic_vector(15 downto 0) ); end zpuio; architecture behave of zpuio is signal timer_read : std_logic_vector(7 downto 0); signal timer_we : std_logic; -- signal io_busy : std_logic; signal io_read : std_logic_vector(7 downto 0); signal io_addr : std_logic_vector(maxAddrBit downto minAddrBit); signal io_writeEnable : std_logic; signal Enable : std_logic; -- signal din : std_logic_vector(7 downto 0); signal dout : std_logic_vector(7 downto 0); signal adr : std_logic_vector(15 downto 0); signal break : std_logic; signal we : std_logic; signal re : std_logic; -- -- uart forwarding... signal uartTXPending : std_logic; signal uartTXCleared : std_logic; signal uartData : std_logic_vector(7 downto 0); -- signal readingTimer : std_logic; -- -- signal mem_busy : std_logic; signal mem_read : std_logic_vector(wordSize-1 downto 0); signal mem_write : std_logic_vector(wordSize-1 downto 0); signal mem_addr : std_logic_vector(maxAddrBitIncIO downto 0); signal mem_writeEnable : std_logic; signal mem_readEnable : std_logic; signal mem_writeMask : std_logic_vector(wordBytes-1 downto 0); -- signal dram_mem_busy : std_logic; signal dram_mem_read : std_logic_vector(wordSize-1 downto 0); signal dram_mem_write : std_logic_vector(wordSize-1 downto 0); signal dram_mem_writeEnable : std_logic; signal dram_mem_readEnable : std_logic; signal dram_mem_writeMask : std_logic_vector(wordBytes-1 downto 0); -- signal io_readEnable : std_logic; -- signal dram_read : std_logic; begin io_addr <= mem_addr(maxAddrBit downto minAddrBit); timerinst : timer port map ( clk => cpu_clk, areset => areset, we => timer_we, din => mem_write(7 downto 0), adr => io_addr(4 downto 2), dout => timer_read ); zpu : zpu_core port map ( clk => cpu_clk , areset => areset, in_mem_busy => mem_busy, mem_read => mem_read, mem_write => mem_write, out_mem_addr => mem_addr, out_mem_writeEnable => mem_writeEnable, out_mem_readEnable => mem_readEnable, mem_writeMask => mem_writeMask, interrupt => '0', break => break ); ram_imp : dram port map ( clk => cpu_clk, areset => areset, mem_busy => dram_mem_busy, mem_read => dram_mem_read, mem_write => mem_write, mem_addr => mem_addr(maxAddrBit downto 0), mem_writeEnable => dram_mem_writeEnable, mem_readEnable => dram_mem_readEnable, mem_writeMask => mem_writeMask ); fauxUart : process(cpu_clk, areset) begin if areset = '1' then io_busy <= '0'; uartTXPending <= '0'; timer_we <= '0'; io_busy <= '0'; uartData <= x"58"; -- 'X' readingTimer <= '0'; elsif rising_edge(cpu_clk) then timer_we <= '0'; io_busy <= '0'; if uartTXCleared = '1' then uartTXPending <= '0'; end if; if io_writeEnable = '1' then if io_addr = x"2028003" then -- Write to UART uartData <= mem_write(7 downto 0); uartTXPending <= '1'; io_busy <= '1'; elsif io_addr(12) = '1' then timer_we <= '1'; io_busy <= '1'; else -- report "Illegal IO write" severity failure; end if; end if; if (io_readEnable = '1') then if io_addr = x"2028003" then io_read <= (0 => '1', -- recieve empty 1 => uartTXPending, -- tx full others => '0'); io_busy <= '1'; elsif io_addr(12) = '1' then readingTimer <= '1'; io_busy <= '1'; elsif io_addr(11) = '1' then io_read <= ZPU_Frequency; io_busy <= '1'; else -- report "Illegal IO read" severity failure; end if; else if (readingTimer = '1') then readingTimer <= '0'; io_read <= timer_read; io_busy <= '0'; else io_read <= (others => '1'); end if; end if; end if; end process; forwardUARTOutputToARM : process(cpu_clk, areset) begin if areset = '1' then uartTXCleared <= '0'; elsif rising_edge(cpu_clkt) then if cpu_we(0) = '1' and cpu_a(3 downto 1) = "000" then uartTXCleared <= cpu_din(0); else uartTXCleared <= uartTXCleared; end if; end if; end process; cpu_dout(7 downto 0) <= uartData when (cpu_re = '1' and cpu_a(3 downto 1) = "001") else (others => 'Z'); cpu_dout <= (0 => uartTXPending, others => '0') when (cpu_re = '1' and cpu_a(3 downto 1) = "000") else (others => 'Z'); dram_mem_writeEnable <= mem_writeEnable and not mem_addr(ioBit); dram_mem_readEnable <= mem_readEnable and not mem_addr(ioBit); io_writeEnable <= mem_writeEnable and mem_addr(ioBit); mem_busy <= io_busy or dram_mem_busy or dram_read or io_readEnable; -- Memory reads either come from IO or DRAM. We need to pick the right one. memorycontrol : process(cpu_clk, areset) begin if areset = '1' then dram_read <= '0'; io_readEnable <= '0'; elsif rising_edge(cpu_clk) then mem_read <= (others => '0'); if mem_addr(ioBit) = '0' and mem_readEnable = '1' then dram_read <= '1'; end if; if dram_read = '1' and dram_mem_busy = '0' then dram_read <= '0'; mem_read <= dram_mem_read; end if; if mem_addr(ioBit) = '1' and mem_readEnable = '1' then io_readEnable <= '1'; end if; if io_readEnable = '1' and io_busy = '0' then io_readEnable <= '0'; mem_read(7 downto 0) <= io_read; end if; end if; end process; end architecture behave;