forth-cpu

Форк
0
/
core.vhd 
306 строк · 8.8 Кб
1
--------------------------------------------------------------------------------
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
library ieee, work;
13
use ieee.std_logic_1164.all;
14
use work.util.n_bits;
15
use work.util.common_generics;
16
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
	generic(g: common_generics; number_of_interrupts: positive := 8);
31
	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
		g: common_generics;
56
		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
use work.util.n_bits;
79
use work.util.common_generics;
80
use work.util.file_format;
81
use work.util.file_hex;
82
use work.util.or_reduce;
83

84
entity core is
85
	generic(g: common_generics; 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_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
	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
	signal dwe:   std_ulogic := '0'; -- Write enable
115
	signal dre:   std_ulogic := '0'; -- Read enable
116
	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
	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
	-- 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
	irqh_0: work.core_pkg.interrupt_request_handler
146
	generic map(g => g, number_of_interrupts => number_of_interrupts)
147
	port map(
148
		clk    => clk,
149
		rst    => rst,
150

151
		irq_i  => irq_edges,
152
		irc_i  => irc_edges,
153

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
	generic map(asynchronous_reset => g.asynchronous_reset, delay => g.delay, interrupt_address_length => interrupt_address_length)
162
	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
		g             => g,
190
		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
--| @copyright  Copyright 2017, 2019 Richard James Howe.
219
--| @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
--| another interrupt of occurs before it has been processed the second
225
--| interrupt will be lost.
226
--|
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
use work.util.common_generics;
238

239
entity interrupt_request_handler is
240
	generic(
241
		g: common_generics;
242
		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
		generic map(g => g, N  => 1)
270
		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
		generic map(g => g, N  => number_of_interrupts)
279
		port map(
280
			clk  =>  clk,
281
			rst  =>  rst,
282
			we   =>  '1',
283
			di   =>  irc_i,
284
			do   =>  irc_n);
285

286
	irc_mask: entity work.reg generic map(g => g, N  => number_of_interrupts)
287
		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
		addr_o <= addr_n after g.delay;
299
		if select_bit(mask_n, addr_n) = '1' then
300
			irq_o <= irq_n after g.delay;
301
		else
302
			irq_o <= '0' after g.delay;
303
		end if;
304
	end process;
305

306
end architecture;
307

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.