summaryrefslogtreecommitdiffstats
path: root/zpu/hdl/zpu4/src/zpuio.vhd
diff options
context:
space:
mode:
Diffstat (limited to 'zpu/hdl/zpu4/src/zpuio.vhd')
-rw-r--r--zpu/hdl/zpu4/src/zpuio.vhd218
1 files changed, 218 insertions, 0 deletions
diff --git a/zpu/hdl/zpu4/src/zpuio.vhd b/zpu/hdl/zpu4/src/zpuio.vhd
new file mode 100644
index 0000000..9ca9050
--- /dev/null
+++ b/zpu/hdl/zpu4/src/zpuio.vhd
@@ -0,0 +1,218 @@
+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;
OpenPOWER on IntegriCloud