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

Subversion Repositories forth-cpu

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

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

powered by: WebSVN 2.1.0

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