forth-cpu

Форк
0
/
top.vhd 
527 строк · 17.6 Кб
1
---------------------------------------------------------------------------------
2
--| @file top.vhd
3
--| @brief This file is the top level of the project.
4
--|  It presents an interface between the CPU,
5
--|  RAM, and all the I/O modules.
6
--|
7
--| @author     Richard James Howe.
8
--| @copyright  Copyright 2017 Richard James Howe.
9
--| @license    MIT
10
--| @email      howe.r.j.89@gmail.com
11
--|
12
---------------------------------------------------------------------------------
13

14
library ieee,work;
15
use ieee.std_logic_1164.all;
16
use ieee.numeric_std.all;
17
use work.core_pkg.all;
18
use work.vga_pkg.all;
19
use work.kbd_pkg.ps2_kbd_top;
20
use work.util.all;
21
use work.uart_pkg.all;
22

23
entity top is
24
	generic(
25
		g: common_generics         := default_settings;
26
		reset_period_us:  natural  := 100;
27
		uart_baud:        positive := 115200;
28
		uart_fifo_depth:  positive := 8);
29
	port
30
	(
31
		-- synthesis translate_off
32
		debug:    out cpu_debug_interface;
33
		-- synthesis translate_on
34

35
		clk:      in  std_ulogic                    := 'X';  -- clock
36
		-- Buttons
37
		btnu:     in  std_ulogic                    := 'X';  -- button up
38
		btnd:     in  std_ulogic                    := 'X';  -- button down
39
		btnc:     in  std_ulogic                    := 'X';  -- button centre
40
		btnl:     in  std_ulogic                    := 'X';  -- button left
41
		btnr:     in  std_ulogic                    := 'X';  -- button right
42
		-- Switches
43
		sw:       in  std_ulogic_vector(7 downto 0) := (others => 'X'); -- switches
44
		-- Simple LED outputs
45
		an:       out std_ulogic_vector(3 downto 0) := (others => '0'); -- anodes   7 segment display
46
		ka:       out std_ulogic_vector(7 downto 0) := (others => '0'); -- cathodes 7 segment display
47

48
		ld:       out std_ulogic_vector(7 downto 0) := (others => '0'); -- leds
49

50
		-- UART
51
		rx:       in  std_ulogic                    := 'X';  -- uart rx
52
		tx:       out std_ulogic                    := '0';  -- uart tx
53

54
		-- VGA
55
		o_vga:    out vga_physical_interface;
56

57
		-- PS/2 Interface
58
		ps2_keyboard_data:  in std_ulogic           := '0';
59
		ps2_keyboard_clk:   in std_ulogic           := '0';
60

61
		-- Memory Interface
62
		ram_cs:    out   std_ulogic := '1';
63
		mem_oe:    out   std_ulogic := '0'; -- negative logic
64
		mem_wr:    out   std_ulogic := '0'; -- negative logic
65
		mem_adv:   out   std_ulogic := '0'; -- negative logic
66
		mem_wait:  out   std_ulogic := '0'; -- positive logic!
67
		flash_cs:  out   std_ulogic := '0';
68
		flash_rp:  out   std_ulogic := '1';
69
		mem_addr:  out   std_ulogic_vector(26 downto 1) := (others => '0');
70
		mem_data:  inout std_logic_vector(15 downto 0)  := (others => 'Z'));
71
end;
72

73
architecture behav of top is
74
	constant timer_length:           positive := 16;
75
	constant number_of_interrupts:   positive := 8;
76
	constant number_of_led_displays: positive := 4;
77
	constant timer_period_us:        positive := 20000;
78
	constant use_sine:               boolean  := false;
79

80
	-- Signals
81
	signal rst:      std_ulogic := '0';
82
	-- CPU H2 IO interface signals.
83
	signal cpu_wait: std_ulogic := '0';
84
	signal io_wr:    std_ulogic := '0';
85
	signal io_re:    std_ulogic := '0';
86
	signal io_din:   std_ulogic_vector(15 downto 0) := (others => '0');
87
	signal io_dout:  std_ulogic_vector(15 downto 0) := (others => '0');
88
	signal io_daddr: std_ulogic_vector(15 downto 0) := (others => '0');
89

90
	-- CPU H2 Interrupts
91
	signal cpu_irc:         std_ulogic_vector(number_of_interrupts - 1 downto 0) := (others => '0');
92
	signal cpu_irc_mask_we: std_ulogic := '0';
93

94
	signal clk25MHz: std_ulogic:= '0';
95
	signal clk50MHz: std_ulogic:= '0';
96

97
	attribute buffer_type: string;
98
	attribute buffer_type of clk50MHz: signal is "BUFG";
99
	attribute buffer_type of clk25MHz: signal is "BUFG";
100

101
	-- Basic IO register
102

103
	---- LEDs/Switches
104
	signal ld_we:             std_ulogic := '0';
105

106
	---- VGA
107
	signal vga_data:          std_ulogic_vector(7 downto 0) := (others => '0');
108
	signal vga_data_we:       std_ulogic                    := '0';
109
	signal vga_data_busy:     std_ulogic                    := '0';
110

111
	---- UART
112
	signal rx_data:           std_ulogic_vector(7 downto 0) := (others => '0');
113
	signal rx_fifo_empty:     std_ulogic := '0';
114
	signal rx_fifo_full:      std_ulogic := '0';
115
	signal rx_data_re:        std_ulogic := '0';
116

117
	signal tx_fifo_full:      std_ulogic := '0';
118
	signal tx_fifo_empty:     std_ulogic := '0';
119
	signal tx_data_we:        std_ulogic := '0';
120

121
	signal uart_clock_tx_we:  std_ulogic := '0';
122
	signal uart_clock_rx_we:  std_ulogic := '0';
123
	signal uart_control_we:   std_ulogic := '0';
124
	---- Timer
125
	signal timer_control_we:  std_ulogic := '0';
126
	signal timer_counter_o:   std_ulogic_vector(timer_length - 4 downto 0) := (others =>'0');
127
	signal timer_irq:         std_ulogic;
128

129
	---- PS/2
130
	signal kbd_char_buf_new:  std_ulogic := '0';
131
	signal kbd_char_buf:      std_ulogic_vector(6 downto 0) := (others => '0'); -- ASCII char
132
	signal kbd_char_re:       std_ulogic := '0';
133

134
	---- 8 Segment Display
135
	signal leds_reg_we:       std_ulogic := '0';
136

137
	---- Buttons
138
	signal btnu_d:            std_ulogic := '0'; -- button up
139
	signal btnd_d:            std_ulogic := '0'; -- button down
140
	signal btnc_d:            std_ulogic := '0'; -- button centre
141
	signal btnl_d:            std_ulogic := '0'; -- button left
142
	signal btnr_d:            std_ulogic := '0'; -- button right
143
	signal button_changed:    std_ulogic := '0'; -- Any of the buttons have changed state
144

145
	-- Switches
146
	signal sw_d:              std_ulogic_vector(sw'range) := (others => '0');
147

148
	-- Memory
149
	signal mem_addr_26_17_we: std_ulogic := '0';
150
	signal mem_addr_16_1_we:  std_ulogic := '0';
151
	signal mem_data_i_we:     std_ulogic := '0';
152
	signal mem_data_o:        std_ulogic_vector(15 downto 0) := (others => '0');
153
	signal mem_control_we:    std_ulogic := '0';
154

155
	signal sine_we: std_ulogic := '0';
156
	signal sine: std_ulogic_vector(15 downto 0) := (others => '0');
157

158
begin
159
-------------------------------------------------------------------------------
160
-- The Main components
161
-------------------------------------------------------------------------------
162

163
	cpu_wait   <= btnc_d; -- temporary testing measure only!
164

165
	system_reset: work.util.reset_generator
166
	generic map (g => g, reset_period_us => reset_period_us)
167
	port map (
168
		clk        => clk,
169
		rst        => rst);
170

171
	-- NB. Video blanking interrupts would be useful for writing
172
	-- graphics code (if the VGA module had a graphics mode, which it
173
	-- currently does not).
174
	cpu_irc(0) <= btnu_d; -- configurable CPU reset (can mask this)
175
	cpu_irc(1) <= not rx_fifo_empty;
176
	cpu_irc(2) <= rx_fifo_full;
177
	cpu_irc(3) <= not tx_fifo_empty;
178
	cpu_irc(4) <= tx_fifo_full;
179
	cpu_irc(5) <= kbd_char_buf_new;
180
	cpu_irc(6) <= timer_irq;
181
	cpu_irc(7) <= button_changed;
182

183
	core_0: entity work.core
184
	generic map (g => g, number_of_interrupts => number_of_interrupts)
185
	port map (
186
-- synthesis translate_off
187
		debug            => debug,
188
-- synthesis translate_on
189
		clk              => clk,
190
		rst              => rst,
191
		stop             => cpu_wait,
192
		io_wr            => io_wr,
193
		io_re            => io_re,
194
		io_din           => io_din,
195
		io_dout          => io_dout,
196
		io_daddr         => io_daddr,
197
		cpu_irc          => cpu_irc,
198
		cpu_irc_mask     => io_dout(number_of_interrupts - 1 downto 0),
199
		cpu_irc_mask_we  => cpu_irc_mask_we);
200

201
	-------------------------------------------------------------------------------
202
	-- IO
203
	-------------------------------------------------------------------------------
204

205
	-- NOTE: A Wishbone Interface on each of the components would simplify the
206
	-- system overall. However, each peripheral would need an interface
207
	-- specifying. This module could be made to be much smaller.
208
	-- See: <https://en.wikipedia.org/wiki/Wishbone_(computer_bus)>
209
	-- And: <http://cdn.opencores.org/downloads/wbspec_b4.pdf>
210

211
	-- Xilinx Application Note:
212
	-- It seems like it buffers the clock correctly here, so no need to
213
	-- use a DCM. However, see:
214
	-- http://electronics.stackexchange.com/questions/112534/using-digital-clock-manager-with-verilog-to-generate-25mhz-clock-from-32mhz-inte
215
	---- Clock divider /2.
216
	clk50MHz <= '0' when rst = '1' else not clk50MHz when rising_edge(clk);
217

218
	---- Clock divider /2. Pixel clock is 25MHz
219
	clk25MHz <= '0' when rst = '1' else not clk25MHz when rising_edge(clk50MHz);
220

221
	-- It possible for CPU to issue both signals at the same time, but it should
222
	-- not happen with a standard instruction.
223
	assert not(io_wr = '1' and io_re = '1') report "IO Read/Write issued at same time" severity error;
224

225
	vga_data <= io_dout(vga_data'range);
226

227
	io_write: block
228
		signal selector: std_ulogic_vector(3 downto 0) := (others => '0');
229
		signal is_write: boolean := false;
230
	begin
231
		selector          <= io_daddr(4 downto 1);
232
		is_write          <= true when io_wr = '1' else false;
233

234
		tx_data_we        <= io_dout(13) when is_write and selector = x"0" else '0';
235
		rx_data_re        <= io_dout(10) when is_write and selector = x"0" else '0';
236

237
		vga_data_we       <= io_dout(13) when is_write and selector = x"1" else '0';
238
		kbd_char_re       <= io_dout(10) when is_write and selector = x"1" else '0';
239

240
		timer_control_we  <= '1'         when is_write and selector = x"2" else '0';
241
		ld_we             <= '1'         when is_write and selector = x"3" else '0';
242
		mem_data_i_we     <= '1'         when is_write and selector = x"4" else '0';
243

244
		mem_addr_26_17_we <= '1'         when is_write and selector = x"5" else '0';
245
		mem_control_we    <= '1'         when is_write and selector = x"5" else '0';
246

247
		mem_addr_16_1_we  <= '1'         when is_write and selector = x"6" else '0';
248

249
		leds_reg_we       <= '1'         when is_write and selector = x"7" else '0';
250
		cpu_irc_mask_we   <= '1'         when is_write and selector = x"8" else '0';
251

252
		uart_clock_tx_we  <= '1'         when is_write and selector = x"9" else '0';
253
		uart_clock_rx_we  <= '1'         when is_write and selector = x"A" else '0';
254
		uart_control_we   <= '1'         when is_write and selector = x"B" else '0';
255

256
		sine_o: if use_sine generate
257
		sine_we           <= '1'         when is_write and selector = x"C" else '0';
258
		end generate;
259
	end block;
260

261
	io_read: process(
262
		io_wr, io_re, io_daddr,
263
		sw_d, btnu_d, btnd_d, btnl_d, btnr_d, btnc_d,
264
		kbd_char_buf_new, kbd_char_buf,
265

266
		rx_data,
267
		rx_fifo_empty,
268
		rx_fifo_full,
269

270
		tx_fifo_full,
271
		tx_fifo_empty,
272

273
		timer_counter_o,
274

275
		vga_data_busy,
276
		sine,
277

278
		mem_data_o)
279
	begin
280
		io_din <= (others => '0');
281

282
		-- The signal io_re is not needed as none of the reads have
283
		-- any side effects
284

285
		case io_daddr(3 downto 1) is
286
		when "000" => -- buttons, plus direct access to UART bit.
287
			io_din(7 downto 0) <= rx_data;
288
			io_din(8)          <= rx_fifo_empty;
289
			io_din(9)          <= rx_fifo_full;
290
			io_din(11)         <= tx_fifo_empty;
291
			io_din(12)         <= tx_fifo_full;
292
		when "001" => -- VT100 status and Keyboard
293
			io_din(6 downto 0) <= kbd_char_buf;
294
			io_din(8)          <= not kbd_char_buf_new;
295
			io_din(9)          <= kbd_char_buf_new;
296
			io_din(11)         <= not vga_data_busy;
297
			io_din(12)         <= vga_data_busy;
298
		when "010" => -- Timer in
299
			io_din(timer_counter_o'range) <= timer_counter_o;
300
		when "011" => -- Switches and buttons
301
			io_din <= "000" & btnu_d & btnd_d & btnl_d & btnr_d & btnc_d & sw_d;
302
		when "100" =>
303
			io_din             <= mem_data_o;
304
		when "101" =>
305
			if use_sine then
306
				io_din <= sine;
307
			end if;
308
		when others => io_din <= (others => '0');
309
		end case;
310
	end process;
311

312
	--- Sine ----------------------------------------------------------
313
	sine_gen_0: if use_sine generate
314
		sine_0: work.util.sine
315
			generic map(g => g)
316
			port map(clk => clk, rst => rst, xwe => sine_we, x => io_dout, s => sine);
317
	end generate;
318
	--- Sine ----------------------------------------------------------
319

320
	--- UART ----------------------------------------------------------
321
	uart_fifo_0: work.uart_pkg.uart_top
322
		generic map (g => g, baud => uart_baud, use_fifo => true)
323
		port map (
324
			clk => clk,
325
			rst => rst,
326

327
			tx            => tx,
328
			tx_fifo_full  => tx_fifo_full,
329
			tx_fifo_empty => tx_fifo_empty,
330
			tx_fifo_we    => tx_data_we,
331
			tx_fifo_data  => io_dout(7 downto 0),
332

333
			rx            => rx,
334
			rx_fifo_re    => rx_data_re,
335
			rx_fifo_data  => rx_data,
336
			rx_fifo_full  => rx_fifo_full,
337
			rx_fifo_empty => rx_fifo_empty,
338

339
			reg             => io_dout,
340
			clock_reg_tx_we => uart_clock_tx_we,
341
			clock_reg_rx_we => uart_clock_rx_we,
342
			control_reg_we  => uart_control_we);
343
	--- UART ----------------------------------------------------------
344

345
	--- LED Output ----------------------------------------------------
346
	led_output_reg_0: entity work.reg
347
		generic map (g => g, N => ld'length)
348
		port map (
349
			clk => clk,
350
			rst => rst,
351
			we  => ld_we,
352
			di  => io_dout(ld'range),
353
			do  => ld);
354
	--- LED Output ----------------------------------------------------
355

356
	--- Timer ---------------------------------------------------------
357
	timer_0: entity work.timer
358
	generic map (g => g, timer_length => timer_length)
359
	port map (
360
		clk       => clk,
361
		rst       => rst,
362
		we        => timer_control_we,
363
		control_i => io_dout,
364
		counter_o => timer_counter_o,
365
		irq       => timer_irq);
366
	--- Timer ---------------------------------------------------------
367

368
	--- VGA -----------------------------------------------------------
369
	vga_selector: block
370
		constant use_vt100: boolean := true;
371
	begin
372
		gen_vt100_0: if use_vt100 generate
373
		vt100_0: work.vga_pkg.vt100
374
			generic map (g => g)
375
			port map (
376
				clk         =>  clk,
377
				clk25MHz    =>  clk25MHz,
378
				rst         =>  rst,
379
				we          =>  vga_data_we,
380
				char        =>  vga_data,
381
				busy        =>  vga_data_busy,
382
				o_vga       =>  o_vga);
383
		end generate;
384

385
		-- Test code
386
		-- NOTE: Timing is not the best, VGA monitor loses synchronization
387
		-- every so often with this module.
388
		vga_gen_c1: if not use_vt100 generate
389
		vga_c1: block
390
			signal row, column: integer := 0;
391
			signal h_blank, v_blank, draw: std_ulogic := '0';
392
		begin
393
			draw <= not h_blank and not v_blank;
394
			vga_c: work.util.vga_controller
395
			generic map (
396
				g => g,
397
				pixel_clock_frequency => 25_000_000,
398
				cfg => work.util.vga_640x480)
399
			port map (
400
				clk    => clk25MHz,
401
				rst    => rst,
402
				row    => row,
403
				column => column,
404
				h_blank => h_blank,
405
				v_blank => v_blank,
406
				h_sync => o_vga.hsync,
407
				v_sync => o_vga.vsync);
408
			o_vga.red   <= "111" when draw = '1' else "000";
409
			o_vga.green <= "111" when (draw = '1' and row < 100 and column < 100) else "000";
410
			o_vga.blue  <= "11";
411
		end block;
412
		end generate;
413
	end block;
414
	--- VGA -----------------------------------------------------------
415

416
	--- Keyboard ------------------------------------------------------
417
	keyboard_0: work.kbd_pkg.keyboard
418
	generic map (g => g, ps2_debounce_counter_size => 8)
419
	port map (
420
		clk              => clk,
421
		rst              => rst,
422

423
		ps2_clk          => ps2_keyboard_clk,
424
		ps2_data         => ps2_keyboard_data,
425

426
		kbd_char_re      => kbd_char_re,
427
		kbd_char_buf_new => kbd_char_buf_new,
428
		kbd_char_buf     => kbd_char_buf);
429
	--- Keyboard ------------------------------------------------------
430

431
	--- LED 8 Segment display -----------------------------------------
432
	ledseg_0: entity work.led_7_segment_display
433
	generic map (
434
		g                      => g,
435
		number_of_led_displays => number_of_led_displays,
436
		use_bcd_not_hex        => false)
437
	port map (
438
		clk        => clk,
439
		rst        => rst,
440

441
		leds_we    => leds_reg_we,
442
		leds       => io_dout,
443

444
		an         => an,
445
		ka         => ka);
446
	--- LED 8 Segment display -----------------------------------------
447

448
	--- Buttons -------------------------------------------------------
449
	button_debouncer: work.util.debounce_block_us
450
	generic map (g => g, N => 5, timer_period_us    => timer_period_us)
451
	port map (
452
		clk   => clk,
453
		di(0) => btnu,
454
		di(1) => btnd,
455
		di(2) => btnc,
456
		di(3) => btnl,
457
		di(4) => btnr,
458
		do(0) => btnu_d,
459
		do(1) => btnd_d,
460
		do(2) => btnc_d,
461
		do(3) => btnl_d,
462
		do(4) => btnr_d);
463

464
	dpad_changed: block
465
		signal changed_signals:     std_ulogic_vector(4 downto 0) := (others => '0');
466
		signal any_changed_signals: std_ulogic := '0';
467
	begin
468
		state_changed: work.util.state_block_changed
469
		generic map (g => g, N => changed_signals'length)
470
		port map (
471
			clk   => clk,
472
			rst   => rst,
473
			di(0) => btnu_d,
474
			di(1) => btnd_d,
475
			di(2) => btnc_d,
476
			di(3) => btnl_d,
477
			di(4) => btnr_d,
478
			do    => changed_signals);
479

480
		any_changed_signals <= '1' when changed_signals /= "00000" else '0';
481

482
		state_changed_reg: work.util.reg
483
		generic map (g => g, N => 1)
484
		port map (
485
			clk   => clk,
486
			rst   => rst,
487
			di(0) => any_changed_signals,
488
			we    => '1',
489
			do(0) => button_changed);
490
	end block;
491

492
	--- Buttons -------------------------------------------------------
493

494
	--- Switches ------------------------------------------------------
495
	sw_debouncer: work.util.debounce_block_us
496
		generic map (g => g, N => sw'length, timer_period_us => timer_period_us)
497
		port map (clk => clk, di => sw, do => sw_d);
498
	--- Switches ------------------------------------------------------
499

500
	--- Memory Interface ----------------------------------------------
501
	ram_interface_0: entity work.ram_interface
502
	generic map (g => g)
503
	port map (
504
		clk               =>  clk,
505
		rst               =>  rst,
506
		mem_addr_16_1     =>  io_dout(io_dout'high downto 1),
507
		mem_addr_16_1_we  =>  mem_addr_16_1_we,
508
		mem_addr_26_17    =>  io_dout(9 downto 0),
509
		mem_addr_26_17_we =>  mem_addr_26_17_we,
510
		mem_control_i     =>  io_dout(15 downto 10),
511
		mem_control_we    =>  mem_control_we,
512
		mem_data_i        =>  io_dout,
513
		mem_data_i_we     =>  mem_data_i_we,
514
		mem_data_o        =>  mem_data_o,
515
		ram_cs            =>  ram_cs,
516
		mem_oe            =>  mem_oe,
517
		mem_wr            =>  mem_wr,
518
		mem_adv           =>  mem_adv,
519
		mem_wait          =>  mem_wait,
520
		flash_cs          =>  flash_cs,
521
		flash_rp          =>  flash_rp,
522
		mem_addr          =>  mem_addr,
523
		mem_data          =>  mem_data);
524
	--- Memory Interface ----------------------------------------------
525

526
-------------------------------------------------------------------------------
527
end architecture;
528

529

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

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

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

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