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

Subversion Repositories forth-cpu

[/] [forth-cpu/] [trunk/] [top.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 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
 

powered by: WebSVN 2.1.0

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