Project

General

Profile

Download (17.1 KB) Statistics
| Branch: | Tag: | Revision:
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.led_pkg.all;
20
use work.kbd_pkg.ps2_kbd_top;
21
use work.uart_pkg.uart_core;
22
use work.util.state_block_changed;
23

    
24
entity top is
25
	generic(
26
		clock_frequency:      positive := 100_000_000;
27
		uart_baud_rate:       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
		RamCS:    out   std_ulogic := '1';
63
		MemOE:    out   std_ulogic := '0'; -- negative logic
64
		MemWR:    out   std_ulogic := '0'; -- negative logic
65
		MemAdv:   out   std_ulogic := '0'; -- negative logic
66
		MemWait:  out   std_ulogic := '0'; -- positive!
67
		FlashCS:  out   std_ulogic := '0';
68
		FlashRp:  out   std_ulogic := '1';
69
		MemAdr:   out   std_ulogic_vector(26 downto 1) := (others => '0');
70
		MemDB:    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

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

    
89
	-- CPU H2 Interrupts
90
	signal cpu_irq:         std_ulogic := '0';
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_data_n:         std_ulogic_vector(7 downto 0) := (others => '0');
114
	signal rx_fifo_empty:     std_ulogic := '0';
115
	signal rx_fifo_full:      std_ulogic := '0';
116
	signal rx_data_re:        std_ulogic := '0';
117
	signal rx_data_re_n:      std_ulogic := '0';
118

    
119
	signal tx_data:           std_ulogic_vector(7 downto 0) := (others => '0');
120
	signal tx_fifo_full:      std_ulogic := '0';
121
	signal tx_fifo_empty:     std_ulogic := '0';
122
	signal tx_data_we:        std_ulogic := '0';
123

    
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

    
136
	signal leds_reg_we:       std_ulogic := '0';
137

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

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

    
149
	-- Memory
150
	signal mem_addr_26_17_we: std_ulogic := '0';
151
	signal mem_addr_16_1_we:  std_ulogic := '0';
152
	signal mem_data_i_we:     std_ulogic := '0';
153
	signal mem_data_o:        std_ulogic_vector(15 downto 0) := (others => '0');
154
	signal mem_control_we:    std_ulogic := '0';
155
	signal mem_we:            std_ulogic := '0';
156
	signal mem_oe:            std_ulogic := '0';
157
begin
158
-------------------------------------------------------------------------------
159
-- The Main components
160
-------------------------------------------------------------------------------
161

    
162
------- Output assignments (Not in a process) ---------------------------------
163

    
164
	-- @warning These are both temporary measures for testing only!
165
	-- rst        <= btnu_d;
166
	cpu_wait   <= btnc_d;
167

    
168
	irq_block: block
169
		signal rx_fifo_not_empty: std_ulogic := '0';
170
		signal tx_fifo_not_empty: std_ulogic := '0';
171

    
172
		signal rx_fifo_not_empty_edge: std_ulogic := '0';
173
		signal rx_fifo_full_edge:      std_ulogic := '0';
174
		signal tx_fifo_not_empty_edge: std_ulogic := '0';
175
		signal tx_fifo_full_edge:      std_ulogic := '0';
176
		signal kbd_char_buf_new_edge:  std_ulogic := '0';
177
	begin
178
		rx_fifo_not_empty <= not rx_fifo_empty;
179
		tx_fifo_not_empty <= not rx_fifo_empty;
180

    
181
		-- @note It might be best to move this into the IRQ handler,
182
		-- to ensure all inputs are edge triggered.
183
		irq_edges: work.util.rising_edge_detectors
184
		generic map(N => 5)
185
		port map(
186
			clk   => clk,
187
			rst   => rst,
188
			di(0) => rx_fifo_not_empty,
189
			di(1) => rx_fifo_full,
190
			di(2) => tx_fifo_not_empty,
191
			di(3) => tx_fifo_full,
192
			di(4) => kbd_char_buf_new,
193

    
194
			do(0) => rx_fifo_not_empty_edge,
195
			do(1) => rx_fifo_full_edge,
196
			do(2) => tx_fifo_not_empty_edge,
197
			do(3) => tx_fifo_full_edge,
198
			do(4) => kbd_char_buf_new_edge);
199

    
200
		cpu_irc(0) <= '0';
201
		cpu_irc(1) <= rx_fifo_not_empty_edge;
202
		cpu_irc(2) <= rx_fifo_full_edge;
203
		cpu_irc(3) <= tx_fifo_not_empty_edge;
204
		cpu_irc(4) <= tx_fifo_full_edge;
205
		cpu_irc(5) <= kbd_char_buf_new_edge;
206
		cpu_irc(6) <= timer_irq;
207
		cpu_irc(7) <= button_changed;
208

    
209
		cpu_irq    <= '1' when
210
				timer_irq              = '1' or
211
				rx_fifo_not_empty_edge = '1' or
212
				rx_fifo_full_edge      = '1' or
213
				tx_fifo_not_empty_edge = '1' or
214
				tx_fifo_full_edge      = '1' or
215
				kbd_char_buf_new_edge  = '1' or
216
				button_changed         = '1'
217
				else '0';
218
	end block;
219

    
220
	core_0: entity work.core
221
	generic map(number_of_interrupts => number_of_interrupts)
222
	port map(
223
-- synthesis translate_off
224
		debug            => debug,
225
-- synthesis translate_on
226
		clk              => clk,
227
		rst              => rst,
228
		stop             => cpu_wait,
229
		io_wr            => io_wr,
230
		io_re            => io_re,
231
		io_din           => io_din,
232
		io_dout          => io_dout,
233
		io_daddr         => io_daddr,
234
		cpu_irq          => cpu_irq,
235
		cpu_irc          => cpu_irc,
236
		cpu_irc_mask     => io_dout(number_of_interrupts - 1 downto 0),
237
		cpu_irc_mask_we  => cpu_irc_mask_we);
238

    
239
-------------------------------------------------------------------------------
240
-- IO
241
-------------------------------------------------------------------------------
242
	-- Xilinx Application Note:
243
	-- It seems like it buffers the clock correctly here, so no need to
244
	-- use a DCM. However, see:
245
	-- http://electronics.stackexchange.com/questions/112534/using-digital-clock-manager-with-verilog-to-generate-25mhz-clock-from-32mhz-inte
246
	---- Clock divider /2.
247
	clk50MHz <= '0' when rst = '1' else not clk50MHz when rising_edge(clk);
248

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

    
252
	assert not(io_wr = '1' and io_re = '1') report "IO Read/Write issued at same time" severity error;
253
	-- assert not(io_wr = '1' or io_re = '1') or not  io_daddr(0) = '1' report "Unaligned register access" severity error;
254

    
255
	vga_data          <= io_dout(vga_data'range);
256
	tx_data           <= io_dout(tx_data'range);
257

    
258
	io_write: block
259
		signal selector: std_ulogic_vector(3 downto 0) := (others => '0');
260
		signal is_write: boolean := false;
261
	begin
262
		selector          <= io_daddr(4 downto 1);
263
		is_write          <= true when io_wr = '1' else false;
264

    
265
		tx_data_we        <= io_dout(13) when is_write and selector = x"0" else '0';
266
		rx_data_re        <= io_dout(10) when is_write and selector = x"0" else '0';
267

    
268
		vga_data_we       <= io_dout(13) when is_write and selector = x"1" else '0';
269
		kbd_char_re       <= io_dout(10) when is_write and selector = x"1" else '0';
270

    
271
		timer_control_we  <= '1'         when is_write and selector = x"2" else '0';
272
		ld_we             <= '1'         when is_write and selector = x"3" else '0';
273
		mem_data_i_we     <= '1'         when is_write and selector = x"4" else '0';
274

    
275
		mem_addr_26_17_we <= '1'         when is_write and selector = x"5" else '0';
276
		mem_control_we    <= '1'         when is_write and selector = x"5" else '0';
277

    
278
		mem_addr_16_1_we  <= '1'         when is_write and selector = x"6" else '0';
279

    
280
		leds_reg_we       <= '1'         when is_write and selector = x"7" else '0';
281
		cpu_irc_mask_we   <= '1'         when is_write and selector = x"8" else '0';
282
	end block;
283

    
284
	io_read: process(
285
		io_wr, io_re, io_daddr,
286
		sw_d, btnu_d, btnd_d, btnl_d, btnr_d, btnc_d,
287
		kbd_char_buf_new, kbd_char_buf,
288

    
289
		rx_data_n,
290
		rx_fifo_empty,
291
		rx_fifo_full,
292

    
293
		tx_fifo_full,
294
		tx_fifo_empty,
295

    
296
		timer_counter_o,
297

    
298
		vga_data_busy,
299

    
300
		mem_data_o)
301
	begin
302

    
303
		io_din <= (others => '0');
304

    
305
		-- The signal io_re is not needed as none of the reads have
306
		-- any side effects
307
		case io_daddr(3 downto 1) is
308
		when "000" => -- buttons, plus direct access to UART bit.
309
			io_din(7 downto 0) <= rx_data_n;
310
			io_din(8)          <= rx_fifo_empty;
311
			io_din(9)          <= rx_fifo_full;
312
			io_din(11)         <= tx_fifo_empty;
313
			io_din(12)         <= tx_fifo_full;
314
		when "001" => -- VT100 status and Keyboard
315
			io_din(6 downto 0) <= kbd_char_buf;
316
			io_din(8)          <= not kbd_char_buf_new;
317
			io_din(9)          <= kbd_char_buf_new;
318
			io_din(11)         <= not vga_data_busy;
319
			io_din(12)         <= vga_data_busy;
320
		when "010" => -- Timer in
321
			io_din(timer_counter_o'range) <= timer_counter_o;
322
		when "011" => -- Switches and buttons
323
			io_din <= "000" & btnu_d & btnd_d & btnl_d & btnr_d & btnc_d & sw_d;
324
		when "100" =>
325
			io_din             <= mem_data_o;
326
		when others => io_din <= (others => '0');
327
		end case;
328
	end process;
329

    
330
	--- UART ----------------------------------------------------------
331
	-- @todo Move registers inside UART module
332
	uart_rx_data_reg_we_0: work.util.reg
333
		generic map(
334
			N      => 1)
335
		port map(
336
			clk    => clk,
337
			rst    => rst,
338
			we     => '1',
339
			di(0)  => rx_data_re,
340
			do(0)  => rx_data_re_n);
341

    
342
	uart_rx_data_reg_0: work.util.reg
343
		generic map(
344
			N => rx_data_n'high + 1)
345
		port map(
346
			clk => clk,
347
			rst => rst,
348
			we  => rx_data_re_n,
349
			di  => rx_data,
350
			do  => rx_data_n);
351

    
352
	uart_0: work.uart_pkg.uart_top
353
		generic map(
354
			baud_rate       => uart_baud_rate,
355
			clock_frequency => clock_frequency,
356
			fifo_depth      => uart_fifo_depth)
357
		port map(
358
			clk             =>  clk,
359
			rst             =>  rst,
360
			rx_data         =>  rx_data,
361
			rx_fifo_empty   =>  rx_fifo_empty,
362
			rx_fifo_full    =>  rx_fifo_full,
363
			rx_data_re      =>  rx_data_re,
364
			tx_data         =>  tx_data,
365
			tx_fifo_full    =>  tx_fifo_full,
366
			tx_fifo_empty   =>  tx_fifo_empty,
367
			tx_data_we      =>  tx_data_we,
368
			tx              =>  tx,
369
			rx              =>  rx);
370
	--- UART ----------------------------------------------------------
371

    
372
	--- LED Output ----------------------------------------------------
373
	led_output_reg_0: entity work.reg
374
		generic map(N => ld'high + 1)
375
		port map(
376
			clk => clk,
377
			rst => rst,
378
			we  => ld_we,
379
			di  => io_dout(ld'range),
380
			do  => ld);
381
	--- LED Output ----------------------------------------------------
382

    
383
	--- Timer ---------------------------------------------------------
384
	timer_0: entity work.timer
385
	generic map(timer_length => timer_length)
386
	port map(
387
		clk       => clk,
388
		rst       => rst,
389
		we        => timer_control_we,
390
		control_i => io_dout,
391
		counter_o => timer_counter_o,
392
		irq       => timer_irq);
393
	--- Timer ---------------------------------------------------------
394

    
395
	--- VGA -----------------------------------------------------------
396
	vt100_0: work.vga_pkg.vt100
397
	port map(
398
		clk         =>  clk,
399
		clk25MHz    =>  clk25MHz,
400
		rst         =>  rst,
401
		we          =>  vga_data_we,
402
		char        =>  vga_data,
403
		busy        =>  vga_data_busy,
404
		o_vga       =>  o_vga);
405
	--- VGA -----------------------------------------------------------
406

    
407
	--- Keyboard ------------------------------------------------------
408
	keyboard_0: work.kbd_pkg.keyboard
409
	generic map(
410
		clock_frequency           => clock_frequency,
411
		ps2_debounce_counter_size => 8)
412
	port map(
413
		clk              => clk,
414
		rst              => rst,
415

    
416
		ps2_clk          => ps2_keyboard_clk,
417
		ps2_data         => ps2_keyboard_data,
418

    
419
		kbd_char_re      => kbd_char_re,
420
		kbd_char_buf_new => kbd_char_buf_new,
421
		kbd_char_buf     => kbd_char_buf);
422
	--- Keyboard ------------------------------------------------------
423

    
424
	--- LED 8 Segment display -----------------------------------------
425
	ledseg_0: entity work.led_8_segment_display
426
	generic map(
427
		number_of_led_displays => number_of_led_displays,
428
		clock_frequency        => clock_frequency,
429
		use_bcd_not_hex        => false)
430
	port map(
431
		clk        => clk,
432
		rst        => rst,
433

    
434
		leds_we    => leds_reg_we,
435
		leds       => io_dout,
436

    
437
		an         => an,
438
		ka         => ka);
439
	--- LED 8 Segment display -----------------------------------------
440

    
441
	--- Buttons -------------------------------------------------------
442
	button_debouncer: work.util.debounce_block_us
443
	generic map(
444
		N               => 5,
445
		clock_frequency => clock_frequency,
446
		timer_period_us => timer_period_us)
447
	port map(
448
		clk   => clk,
449
		di(0) => btnu,
450
		di(1) => btnd,
451
		di(2) => btnc,
452
		di(3) => btnl,
453
		di(4) => btnr,
454
		do(0) => btnu_d,
455
		do(1) => btnd_d,
456
		do(2) => btnc_d,
457
		do(3) => btnl_d,
458
		do(4) => btnr_d);
459

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

    
476
		any_changed_signals <= '1' when changed_signals /= "00000" else '0';
477

    
478
		state_changed_reg: work.util.reg
479
		generic map(N => 1)
480
		port map(
481
			clk   => clk,
482
			rst   => rst,
483
			di(0) => any_changed_signals,
484
			we    => '1',
485
			do(0) => button_changed);
486
	end block;
487

    
488
	--- Buttons -------------------------------------------------------
489

    
490
	--- Switches ------------------------------------------------------
491
	sw_debouncer: work.util.debounce_block_us
492
		generic map(
493
			N               => sw'high+1,
494
			clock_frequency => clock_frequency,
495
			timer_period_us => timer_period_us)
496
		port map(clk => clk, di => sw, do => sw_d);
497
	--- Switches ------------------------------------------------------
498

    
499
	--- Memory Interface ----------------------------------------------
500
	ram_interface_0: entity work.ram_interface
501
	port map(
502
		clk                =>  clk,
503
		rst                =>  rst,
504
		mem_addr_16_1      =>  io_dout,
505
		mem_addr_16_1_we   =>  mem_addr_16_1_we,
506
		mem_addr_26_17     =>  io_dout(9 downto 0),
507
		mem_addr_26_17_we  =>  mem_addr_26_17_we,
508
		mem_control_i      =>  io_dout(15 downto 10),
509
		mem_control_we     =>  mem_control_we,
510
		mem_data_i         =>  io_dout,
511
		mem_data_i_we      =>  mem_data_i_we,
512
		mem_data_o         =>  mem_data_o,
513
		RamCS              =>  RamCS,
514
		MemOE              =>  MemOE,
515
		MemWR              =>  MemWR,
516
		MemAdv             =>  MemAdv,
517
		MemWait            =>  MemWait,
518
		FlashCS            =>  FlashCS,
519
		FlashRp            =>  FlashRp,
520
		MemAdr             =>  MemAdr,
521
		MemDB              =>  MemDB);
522
	--- Memory Interface ----------------------------------------------
523

    
524
-------------------------------------------------------------------------------
525
end architecture;
526

    
(10-10/21)