summaryrefslogtreecommitdiffstats
path: root/zpu/hdl/zpu4/src/zpuio.vhd
blob: 9ca905046415492daed83e7898ce69f85acdda6a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
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