OpenCores
URL https://opencores.org/ocsvn/forth-cpu/forth-cpu/trunk

Subversion Repositories forth-cpu

[/] [forth-cpu/] [trunk/] [core.vhd] - Blame information for rev 5

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 3 howe.r.j.8
--------------------------------------------------------------------------------
2
--| @file core.vhd
3
--| @brief This contains the CPU, memory and interrupt handler instances
4
--|
5
--| @author     Richard James Howe.
6
--| @copyright  Copyright 2013,2017 Richard James Howe.
7
--| @license    MIT
8
--| @email      howe.r.j.89@gmail.com
9
--|
10
--------------------------------------------------------------------------------
11
 
12 5 howe.r.j.8
library ieee, work;
13 3 howe.r.j.8
use ieee.std_logic_1164.all;
14
use work.util.n_bits;
15 5 howe.r.j.8
use work.util.common_generics;
16 3 howe.r.j.8
use work.h2_pkg.all;
17
 
18
package core_pkg is
19
        type cpu_debug_interface is record
20
                pc:        address;
21
                insn:      word;
22
                dwe:       std_ulogic;
23
                dre:       std_ulogic;
24
                din:       word;
25
                dout:      word;
26
                daddr:     address;
27
        end record;
28
 
29
        component core is
30 5 howe.r.j.8
        generic(g: common_generics; number_of_interrupts: positive := 8);
31 3 howe.r.j.8
        port(
32
                -- synthesis translate_off
33
                debug:           out cpu_debug_interface;
34
                -- synthesis translate_on
35
 
36
                clk:             in   std_ulogic;
37
                rst:             in   std_ulogic;
38
 
39
                stop:            in   std_ulogic; -- Halts the CPU
40
 
41
                io_wr:           out  std_ulogic; -- I/O Write enable
42
                io_re:           out  std_ulogic; -- hardware *READS* can have side effects
43
                io_din:          in   word;
44
                io_dout:         out  word:= (others => 'X');
45
                io_daddr:        out  word:= (others => 'X');
46
 
47
                -- Interrupts
48
                cpu_irc:         in std_ulogic_vector(number_of_interrupts - 1 downto 0);
49
                cpu_irc_mask:    in std_ulogic_vector(number_of_interrupts - 1 downto 0);
50
                cpu_irc_mask_we: in std_ulogic);
51
        end component;
52
 
53
        component interrupt_request_handler is
54
        generic(
55 5 howe.r.j.8
                g: common_generics;
56 3 howe.r.j.8
                number_of_interrupts:   positive := 8;
57
                lowest_interrupt_first: boolean  := true);
58
        port(
59
                clk:     in  std_ulogic;
60
                rst:     in  std_ulogic;
61
 
62
                irq_i:   in  std_ulogic;
63
                irc_i:   in  std_ulogic_vector(number_of_interrupts - 1 downto 0);
64
 
65
                mask:    in  std_ulogic_vector(number_of_interrupts - 1 downto 0);
66
                mask_we: in  std_ulogic;
67
 
68
                irq_o:   out std_ulogic;
69
                addr_o:  out std_ulogic_vector(n_bits(number_of_interrupts) - 1 downto 0));
70
        end component;
71
end package;
72
 
73
----- CPU ----------------------------------------------------------------------
74
library ieee,work;
75
use ieee.std_logic_1164.all;
76
use work.core_pkg.all;
77
use work.h2_pkg.all;
78 5 howe.r.j.8
use work.util.n_bits;
79
use work.util.common_generics;
80 3 howe.r.j.8
use work.util.file_format;
81 5 howe.r.j.8
use work.util.file_hex;
82
use work.util.or_reduce;
83 3 howe.r.j.8
 
84
entity core is
85 5 howe.r.j.8
        generic(g: common_generics; number_of_interrupts: positive := 8);
86 3 howe.r.j.8
        port(
87
                -- synthesis translate_off
88
                debug:           out cpu_debug_interface;
89
                -- synthesis translate_on
90
 
91
                clk:             in   std_ulogic;
92
                rst:             in   std_ulogic;
93
 
94
                stop:            in   std_ulogic; -- Halts the CPU
95
 
96
                io_wr:           out  std_ulogic; -- I/O Write enable
97
                io_re:           out  std_ulogic; -- hardware *READS* can have side effects
98
                io_din:          in   word;
99
                io_dout:         out  word := (others => 'X');
100
                io_daddr:        out  word := (others => 'X');
101
 
102
                -- Interrupts
103
                cpu_irc:         in std_ulogic_vector(number_of_interrupts - 1 downto 0);
104
                cpu_irc_mask:    in std_ulogic_vector(number_of_interrupts - 1 downto 0);
105
                cpu_irc_mask_we: in std_ulogic);
106
end;
107
 
108
architecture structural of core is
109
        constant interrupt_address_length: natural     := n_bits(number_of_interrupts);
110
        constant file_name:                string      := "h2.hex";
111 5 howe.r.j.8
        constant file_type:                file_format := file_hex;
112
        signal pc:    address    := (others => '0'); -- Program counter
113
        signal insn:  word       := (others => '0'); -- Instruction issued by program counter
114 3 howe.r.j.8
        signal dwe:   std_ulogic := '0'; -- Write enable
115
        signal dre:   std_ulogic := '0'; -- Read enable
116 5 howe.r.j.8
        signal din:   word       := (others => '0');
117
        signal dout:  word       := (others => '0');
118
        signal daddr: address    := (others => '0');
119
        signal irc_edges:    std_ulogic_vector(cpu_irc'range) := (others => '0');
120
        signal irq_edges:    std_ulogic := '0';
121 3 howe.r.j.8
        signal h2_irq:       std_ulogic := '0';
122
        signal h2_irq_addr:  std_ulogic_vector(interrupt_address_length - 1 downto 0) := (others=>'0');
123
begin
124
        -- synthesis translate_off
125
        debug.pc    <= pc;
126
        debug.insn  <= insn;
127
        debug.dwe   <= dwe;
128
        debug.dre   <= dre;
129
        debug.din   <= din;
130
        debug.dout  <= dout;
131
        debug.daddr <= daddr;
132
        -- synthesis translate_on
133
 
134 5 howe.r.j.8
        -- Ensure all interrupts occur are rising edge triggered
135
        edges: work.util.rising_edge_detectors
136
        generic map(g => g, N => cpu_irc'length)
137
        port map(
138
                clk   => clk,
139
                rst   => rst,
140
                di    => cpu_irc,
141
                do    => irc_edges);
142
 
143
        irq_edges <= or_reduce(irc_edges);
144
 
145 3 howe.r.j.8
        irqh_0: work.core_pkg.interrupt_request_handler
146 5 howe.r.j.8
        generic map(g => g, number_of_interrupts => number_of_interrupts)
147 3 howe.r.j.8
        port map(
148
                clk    => clk,
149
                rst    => rst,
150
 
151 5 howe.r.j.8
                irq_i  => irq_edges,
152
                irc_i  => irc_edges,
153 3 howe.r.j.8
 
154
                irq_o  => h2_irq,
155
                addr_o => h2_irq_addr,
156
 
157
                mask    => cpu_irc_mask,
158
                mask_we => cpu_irc_mask_we);
159
 
160
        h2_0: work.h2_pkg.h2 -- The actual CPU instance (H2)
161 5 howe.r.j.8
        generic map(asynchronous_reset => g.asynchronous_reset, delay => g.delay, interrupt_address_length => interrupt_address_length)
162 3 howe.r.j.8
        port map(
163
                clk       =>    clk,
164
                rst       =>    rst,
165
 
166
                -- External interface with the 'outside world'
167
                stop      =>  stop,
168
                io_wr     =>  io_wr,
169
                io_re     =>  io_re,
170
                io_din    =>  io_din,
171
                io_dout   =>  io_dout,
172
                io_daddr  =>  io_daddr,
173
 
174
                irq       =>  h2_irq,
175
                irq_addr  =>  h2_irq_addr,
176
 
177
                -- Instruction and instruction address to CPU
178
                pc        =>  pc,
179
                insn      =>  insn,
180
                -- Fetch/Store
181
                dwe       =>  dwe,
182
                dre       =>  dre,
183
                din       =>  din,
184
                dout      =>  dout,
185
                daddr     =>  daddr);
186
 
187
        mem_h2_0: entity work.dual_port_block_ram
188
        generic map(
189 5 howe.r.j.8
                g             => g,
190 3 howe.r.j.8
                addr_length   => address'length,
191
                data_length   => word'length,
192
                file_name     => file_name,
193
                file_type     => file_type)
194
        port map(
195
                -- Port A, Read only, CPU instruction/address
196
                a_clk   =>    clk,
197
                a_dwe   =>    '0',
198
                a_dre   =>    '1',
199
                a_addr  =>    pc,
200
                a_din   =>    (others => '0'),
201
                a_dout  =>    insn,
202
                -- Port B, Read/Write controlled by CPU instructions
203
                b_clk   =>    clk,
204
                b_dwe   =>    dwe,
205
                b_dre   =>    dre,
206
                b_addr  =>    daddr,
207
                b_din   =>    dout,
208
                b_dout  =>    din);
209
 
210
end architecture;
211
 
212
--------------------------------------------------------------------------------
213
--| @brief Interrupt request handler, while the CPU can handle interrupts
214
--|        it does not to a good job of it. This allows customization of
215
--|        priority.
216
--|
217
--| @author     Richard James Howe.
218 5 howe.r.j.8
--| @copyright  Copyright 2017, 2019 Richard James Howe.
219 3 howe.r.j.8
--| @license    MIT
220
--| @email      howe.r.j.89@gmail.com
221
--|
222
--| This is a simple interrupt handler, interrupts are decoded in priority
223
--| order which can be set by a generic. If an interrupt occurs and then
224 5 howe.r.j.8
--| another interrupt of occurs before it has been processed the second
225
--| interrupt will be lost.
226 3 howe.r.j.8
--|
227
--------------------------------------------------------------------------------
228
 
229
library ieee,work;
230
use ieee.std_logic_1164.all;
231
use ieee.numeric_std.all;
232
use ieee.math_real.all; -- only needed for calculations relating to generics
233
use work.util.reg;
234
use work.util.n_bits;
235
use work.util.select_bit;
236
use work.util.priority;
237 5 howe.r.j.8
use work.util.common_generics;
238 3 howe.r.j.8
 
239
entity interrupt_request_handler is
240
        generic(
241 5 howe.r.j.8
                g: common_generics;
242 3 howe.r.j.8
                number_of_interrupts:   positive := 8;
243
                lowest_interrupt_first: boolean  := true);
244
        port(
245
                clk:     in  std_ulogic;
246
                rst:     in  std_ulogic;
247
 
248
                irq_i:   in  std_ulogic;
249
                irc_i:   in  std_ulogic_vector(number_of_interrupts - 1 downto 0);
250
 
251
                mask:    in  std_ulogic_vector(number_of_interrupts - 1 downto 0);
252
                mask_we: in  std_ulogic;
253
 
254
                irq_o:   out std_ulogic;
255
                addr_o:  out std_ulogic_vector(n_bits(number_of_interrupts) - 1 downto 0));
256
end;
257
 
258
architecture rtl of interrupt_request_handler is
259
        constant addr_length: natural := n_bits(number_of_interrupts);
260
        signal irq_n: std_ulogic := '0';
261
        signal irc_n: std_ulogic_vector(irc_i'range) := (others => '0');
262
 
263
        signal addr:  std_ulogic_vector(addr_length - 1 downto 0) := (others => '0');
264
        signal irq:   std_ulogic := '0';
265
 
266
        signal mask_n: std_ulogic_vector(mask'range) := (others => '0');
267
begin
268
        irq_in: entity work.reg
269 5 howe.r.j.8
                generic map(g => g, N  => 1)
270 3 howe.r.j.8
                port map(
271
                        clk    =>  clk,
272
                        rst    =>  rst,
273
                        we     =>  '1',
274
                        di(0)  =>  irq_i,
275
                        do(0)  =>  irq_n);
276
 
277
        irc_in: entity work.reg
278 5 howe.r.j.8
                generic map(g => g, N  => number_of_interrupts)
279 3 howe.r.j.8
                port map(
280
                        clk  =>  clk,
281
                        rst  =>  rst,
282
                        we   =>  '1',
283
                        di   =>  irc_i,
284
                        do   =>  irc_n);
285
 
286 5 howe.r.j.8
        irc_mask: entity work.reg generic map(g => g, N  => number_of_interrupts)
287 3 howe.r.j.8
                port map(
288
                        clk  =>  clk,
289
                        rst  =>  rst,
290
                        we   =>  mask_we,
291
                        di   =>  mask,
292
                        do   =>  mask_n);
293
 
294
        process(irc_n, irq_n, mask_n)
295
                variable addr_n: std_ulogic_vector(addr'range) := (others => '0');
296
        begin
297
                addr_n := priority(irc_n, not lowest_interrupt_first);
298 5 howe.r.j.8
                addr_o <= addr_n after g.delay;
299 3 howe.r.j.8
                if select_bit(mask_n, addr_n) = '1' then
300 5 howe.r.j.8
                        irq_o <= irq_n after g.delay;
301 3 howe.r.j.8
                else
302 5 howe.r.j.8
                        irq_o <= '0' after g.delay;
303 3 howe.r.j.8
                end if;
304
        end process;
305
 
306
end architecture;

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.