forth-cpu
/
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
14library ieee,work;
15use ieee.std_logic_1164.all;
16use ieee.numeric_std.all;
17use work.core_pkg.all;
18use work.vga_pkg.all;
19use work.kbd_pkg.ps2_kbd_top;
20use work.util.all;
21use work.uart_pkg.all;
22
23entity top is
24generic(
25g: common_generics := default_settings;
26reset_period_us: natural := 100;
27uart_baud: positive := 115200;
28uart_fifo_depth: positive := 8);
29port
30(
31-- synthesis translate_off
32debug: out cpu_debug_interface;
33-- synthesis translate_on
34
35clk: in std_ulogic := 'X'; -- clock
36-- Buttons
37btnu: in std_ulogic := 'X'; -- button up
38btnd: in std_ulogic := 'X'; -- button down
39btnc: in std_ulogic := 'X'; -- button centre
40btnl: in std_ulogic := 'X'; -- button left
41btnr: in std_ulogic := 'X'; -- button right
42-- Switches
43sw: in std_ulogic_vector(7 downto 0) := (others => 'X'); -- switches
44-- Simple LED outputs
45an: out std_ulogic_vector(3 downto 0) := (others => '0'); -- anodes 7 segment display
46ka: out std_ulogic_vector(7 downto 0) := (others => '0'); -- cathodes 7 segment display
47
48ld: out std_ulogic_vector(7 downto 0) := (others => '0'); -- leds
49
50-- UART
51rx: in std_ulogic := 'X'; -- uart rx
52tx: out std_ulogic := '0'; -- uart tx
53
54-- VGA
55o_vga: out vga_physical_interface;
56
57-- PS/2 Interface
58ps2_keyboard_data: in std_ulogic := '0';
59ps2_keyboard_clk: in std_ulogic := '0';
60
61-- Memory Interface
62ram_cs: out std_ulogic := '1';
63mem_oe: out std_ulogic := '0'; -- negative logic
64mem_wr: out std_ulogic := '0'; -- negative logic
65mem_adv: out std_ulogic := '0'; -- negative logic
66mem_wait: out std_ulogic := '0'; -- positive logic!
67flash_cs: out std_ulogic := '0';
68flash_rp: out std_ulogic := '1';
69mem_addr: out std_ulogic_vector(26 downto 1) := (others => '0');
70mem_data: inout std_logic_vector(15 downto 0) := (others => 'Z'));
71end;
72
73architecture behav of top is
74constant timer_length: positive := 16;
75constant number_of_interrupts: positive := 8;
76constant number_of_led_displays: positive := 4;
77constant timer_period_us: positive := 20000;
78constant use_sine: boolean := false;
79
80-- Signals
81signal rst: std_ulogic := '0';
82-- CPU H2 IO interface signals.
83signal cpu_wait: std_ulogic := '0';
84signal io_wr: std_ulogic := '0';
85signal io_re: std_ulogic := '0';
86signal io_din: std_ulogic_vector(15 downto 0) := (others => '0');
87signal io_dout: std_ulogic_vector(15 downto 0) := (others => '0');
88signal io_daddr: std_ulogic_vector(15 downto 0) := (others => '0');
89
90-- CPU H2 Interrupts
91signal cpu_irc: std_ulogic_vector(number_of_interrupts - 1 downto 0) := (others => '0');
92signal cpu_irc_mask_we: std_ulogic := '0';
93
94signal clk25MHz: std_ulogic:= '0';
95signal clk50MHz: std_ulogic:= '0';
96
97attribute buffer_type: string;
98attribute buffer_type of clk50MHz: signal is "BUFG";
99attribute buffer_type of clk25MHz: signal is "BUFG";
100
101-- Basic IO register
102
103---- LEDs/Switches
104signal ld_we: std_ulogic := '0';
105
106---- VGA
107signal vga_data: std_ulogic_vector(7 downto 0) := (others => '0');
108signal vga_data_we: std_ulogic := '0';
109signal vga_data_busy: std_ulogic := '0';
110
111---- UART
112signal rx_data: std_ulogic_vector(7 downto 0) := (others => '0');
113signal rx_fifo_empty: std_ulogic := '0';
114signal rx_fifo_full: std_ulogic := '0';
115signal rx_data_re: std_ulogic := '0';
116
117signal tx_fifo_full: std_ulogic := '0';
118signal tx_fifo_empty: std_ulogic := '0';
119signal tx_data_we: std_ulogic := '0';
120
121signal uart_clock_tx_we: std_ulogic := '0';
122signal uart_clock_rx_we: std_ulogic := '0';
123signal uart_control_we: std_ulogic := '0';
124---- Timer
125signal timer_control_we: std_ulogic := '0';
126signal timer_counter_o: std_ulogic_vector(timer_length - 4 downto 0) := (others =>'0');
127signal timer_irq: std_ulogic;
128
129---- PS/2
130signal kbd_char_buf_new: std_ulogic := '0';
131signal kbd_char_buf: std_ulogic_vector(6 downto 0) := (others => '0'); -- ASCII char
132signal kbd_char_re: std_ulogic := '0';
133
134---- 8 Segment Display
135signal leds_reg_we: std_ulogic := '0';
136
137---- Buttons
138signal btnu_d: std_ulogic := '0'; -- button up
139signal btnd_d: std_ulogic := '0'; -- button down
140signal btnc_d: std_ulogic := '0'; -- button centre
141signal btnl_d: std_ulogic := '0'; -- button left
142signal btnr_d: std_ulogic := '0'; -- button right
143signal button_changed: std_ulogic := '0'; -- Any of the buttons have changed state
144
145-- Switches
146signal sw_d: std_ulogic_vector(sw'range) := (others => '0');
147
148-- Memory
149signal mem_addr_26_17_we: std_ulogic := '0';
150signal mem_addr_16_1_we: std_ulogic := '0';
151signal mem_data_i_we: std_ulogic := '0';
152signal mem_data_o: std_ulogic_vector(15 downto 0) := (others => '0');
153signal mem_control_we: std_ulogic := '0';
154
155signal sine_we: std_ulogic := '0';
156signal sine: std_ulogic_vector(15 downto 0) := (others => '0');
157
158begin
159-------------------------------------------------------------------------------
160-- The Main components
161-------------------------------------------------------------------------------
162
163cpu_wait <= btnc_d; -- temporary testing measure only!
164
165system_reset: work.util.reset_generator
166generic map (g => g, reset_period_us => reset_period_us)
167port map (
168clk => clk,
169rst => 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).
174cpu_irc(0) <= btnu_d; -- configurable CPU reset (can mask this)
175cpu_irc(1) <= not rx_fifo_empty;
176cpu_irc(2) <= rx_fifo_full;
177cpu_irc(3) <= not tx_fifo_empty;
178cpu_irc(4) <= tx_fifo_full;
179cpu_irc(5) <= kbd_char_buf_new;
180cpu_irc(6) <= timer_irq;
181cpu_irc(7) <= button_changed;
182
183core_0: entity work.core
184generic map (g => g, number_of_interrupts => number_of_interrupts)
185port map (
186-- synthesis translate_off
187debug => debug,
188-- synthesis translate_on
189clk => clk,
190rst => rst,
191stop => cpu_wait,
192io_wr => io_wr,
193io_re => io_re,
194io_din => io_din,
195io_dout => io_dout,
196io_daddr => io_daddr,
197cpu_irc => cpu_irc,
198cpu_irc_mask => io_dout(number_of_interrupts - 1 downto 0),
199cpu_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.
216clk50MHz <= '0' when rst = '1' else not clk50MHz when rising_edge(clk);
217
218---- Clock divider /2. Pixel clock is 25MHz
219clk25MHz <= '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.
223assert not(io_wr = '1' and io_re = '1') report "IO Read/Write issued at same time" severity error;
224
225vga_data <= io_dout(vga_data'range);
226
227io_write: block
228signal selector: std_ulogic_vector(3 downto 0) := (others => '0');
229signal is_write: boolean := false;
230begin
231selector <= io_daddr(4 downto 1);
232is_write <= true when io_wr = '1' else false;
233
234tx_data_we <= io_dout(13) when is_write and selector = x"0" else '0';
235rx_data_re <= io_dout(10) when is_write and selector = x"0" else '0';
236
237vga_data_we <= io_dout(13) when is_write and selector = x"1" else '0';
238kbd_char_re <= io_dout(10) when is_write and selector = x"1" else '0';
239
240timer_control_we <= '1' when is_write and selector = x"2" else '0';
241ld_we <= '1' when is_write and selector = x"3" else '0';
242mem_data_i_we <= '1' when is_write and selector = x"4" else '0';
243
244mem_addr_26_17_we <= '1' when is_write and selector = x"5" else '0';
245mem_control_we <= '1' when is_write and selector = x"5" else '0';
246
247mem_addr_16_1_we <= '1' when is_write and selector = x"6" else '0';
248
249leds_reg_we <= '1' when is_write and selector = x"7" else '0';
250cpu_irc_mask_we <= '1' when is_write and selector = x"8" else '0';
251
252uart_clock_tx_we <= '1' when is_write and selector = x"9" else '0';
253uart_clock_rx_we <= '1' when is_write and selector = x"A" else '0';
254uart_control_we <= '1' when is_write and selector = x"B" else '0';
255
256sine_o: if use_sine generate
257sine_we <= '1' when is_write and selector = x"C" else '0';
258end generate;
259end block;
260
261io_read: process(
262io_wr, io_re, io_daddr,
263sw_d, btnu_d, btnd_d, btnl_d, btnr_d, btnc_d,
264kbd_char_buf_new, kbd_char_buf,
265
266rx_data,
267rx_fifo_empty,
268rx_fifo_full,
269
270tx_fifo_full,
271tx_fifo_empty,
272
273timer_counter_o,
274
275vga_data_busy,
276sine,
277
278mem_data_o)
279begin
280io_din <= (others => '0');
281
282-- The signal io_re is not needed as none of the reads have
283-- any side effects
284
285case io_daddr(3 downto 1) is
286when "000" => -- buttons, plus direct access to UART bit.
287io_din(7 downto 0) <= rx_data;
288io_din(8) <= rx_fifo_empty;
289io_din(9) <= rx_fifo_full;
290io_din(11) <= tx_fifo_empty;
291io_din(12) <= tx_fifo_full;
292when "001" => -- VT100 status and Keyboard
293io_din(6 downto 0) <= kbd_char_buf;
294io_din(8) <= not kbd_char_buf_new;
295io_din(9) <= kbd_char_buf_new;
296io_din(11) <= not vga_data_busy;
297io_din(12) <= vga_data_busy;
298when "010" => -- Timer in
299io_din(timer_counter_o'range) <= timer_counter_o;
300when "011" => -- Switches and buttons
301io_din <= "000" & btnu_d & btnd_d & btnl_d & btnr_d & btnc_d & sw_d;
302when "100" =>
303io_din <= mem_data_o;
304when "101" =>
305if use_sine then
306io_din <= sine;
307end if;
308when others => io_din <= (others => '0');
309end case;
310end process;
311
312--- Sine ----------------------------------------------------------
313sine_gen_0: if use_sine generate
314sine_0: work.util.sine
315generic map(g => g)
316port map(clk => clk, rst => rst, xwe => sine_we, x => io_dout, s => sine);
317end generate;
318--- Sine ----------------------------------------------------------
319
320--- UART ----------------------------------------------------------
321uart_fifo_0: work.uart_pkg.uart_top
322generic map (g => g, baud => uart_baud, use_fifo => true)
323port map (
324clk => clk,
325rst => rst,
326
327tx => tx,
328tx_fifo_full => tx_fifo_full,
329tx_fifo_empty => tx_fifo_empty,
330tx_fifo_we => tx_data_we,
331tx_fifo_data => io_dout(7 downto 0),
332
333rx => rx,
334rx_fifo_re => rx_data_re,
335rx_fifo_data => rx_data,
336rx_fifo_full => rx_fifo_full,
337rx_fifo_empty => rx_fifo_empty,
338
339reg => io_dout,
340clock_reg_tx_we => uart_clock_tx_we,
341clock_reg_rx_we => uart_clock_rx_we,
342control_reg_we => uart_control_we);
343--- UART ----------------------------------------------------------
344
345--- LED Output ----------------------------------------------------
346led_output_reg_0: entity work.reg
347generic map (g => g, N => ld'length)
348port map (
349clk => clk,
350rst => rst,
351we => ld_we,
352di => io_dout(ld'range),
353do => ld);
354--- LED Output ----------------------------------------------------
355
356--- Timer ---------------------------------------------------------
357timer_0: entity work.timer
358generic map (g => g, timer_length => timer_length)
359port map (
360clk => clk,
361rst => rst,
362we => timer_control_we,
363control_i => io_dout,
364counter_o => timer_counter_o,
365irq => timer_irq);
366--- Timer ---------------------------------------------------------
367
368--- VGA -----------------------------------------------------------
369vga_selector: block
370constant use_vt100: boolean := true;
371begin
372gen_vt100_0: if use_vt100 generate
373vt100_0: work.vga_pkg.vt100
374generic map (g => g)
375port map (
376clk => clk,
377clk25MHz => clk25MHz,
378rst => rst,
379we => vga_data_we,
380char => vga_data,
381busy => vga_data_busy,
382o_vga => o_vga);
383end generate;
384
385-- Test code
386-- NOTE: Timing is not the best, VGA monitor loses synchronization
387-- every so often with this module.
388vga_gen_c1: if not use_vt100 generate
389vga_c1: block
390signal row, column: integer := 0;
391signal h_blank, v_blank, draw: std_ulogic := '0';
392begin
393draw <= not h_blank and not v_blank;
394vga_c: work.util.vga_controller
395generic map (
396g => g,
397pixel_clock_frequency => 25_000_000,
398cfg => work.util.vga_640x480)
399port map (
400clk => clk25MHz,
401rst => rst,
402row => row,
403column => column,
404h_blank => h_blank,
405v_blank => v_blank,
406h_sync => o_vga.hsync,
407v_sync => o_vga.vsync);
408o_vga.red <= "111" when draw = '1' else "000";
409o_vga.green <= "111" when (draw = '1' and row < 100 and column < 100) else "000";
410o_vga.blue <= "11";
411end block;
412end generate;
413end block;
414--- VGA -----------------------------------------------------------
415
416--- Keyboard ------------------------------------------------------
417keyboard_0: work.kbd_pkg.keyboard
418generic map (g => g, ps2_debounce_counter_size => 8)
419port map (
420clk => clk,
421rst => rst,
422
423ps2_clk => ps2_keyboard_clk,
424ps2_data => ps2_keyboard_data,
425
426kbd_char_re => kbd_char_re,
427kbd_char_buf_new => kbd_char_buf_new,
428kbd_char_buf => kbd_char_buf);
429--- Keyboard ------------------------------------------------------
430
431--- LED 8 Segment display -----------------------------------------
432ledseg_0: entity work.led_7_segment_display
433generic map (
434g => g,
435number_of_led_displays => number_of_led_displays,
436use_bcd_not_hex => false)
437port map (
438clk => clk,
439rst => rst,
440
441leds_we => leds_reg_we,
442leds => io_dout,
443
444an => an,
445ka => ka);
446--- LED 8 Segment display -----------------------------------------
447
448--- Buttons -------------------------------------------------------
449button_debouncer: work.util.debounce_block_us
450generic map (g => g, N => 5, timer_period_us => timer_period_us)
451port map (
452clk => clk,
453di(0) => btnu,
454di(1) => btnd,
455di(2) => btnc,
456di(3) => btnl,
457di(4) => btnr,
458do(0) => btnu_d,
459do(1) => btnd_d,
460do(2) => btnc_d,
461do(3) => btnl_d,
462do(4) => btnr_d);
463
464dpad_changed: block
465signal changed_signals: std_ulogic_vector(4 downto 0) := (others => '0');
466signal any_changed_signals: std_ulogic := '0';
467begin
468state_changed: work.util.state_block_changed
469generic map (g => g, N => changed_signals'length)
470port map (
471clk => clk,
472rst => rst,
473di(0) => btnu_d,
474di(1) => btnd_d,
475di(2) => btnc_d,
476di(3) => btnl_d,
477di(4) => btnr_d,
478do => changed_signals);
479
480any_changed_signals <= '1' when changed_signals /= "00000" else '0';
481
482state_changed_reg: work.util.reg
483generic map (g => g, N => 1)
484port map (
485clk => clk,
486rst => rst,
487di(0) => any_changed_signals,
488we => '1',
489do(0) => button_changed);
490end block;
491
492--- Buttons -------------------------------------------------------
493
494--- Switches ------------------------------------------------------
495sw_debouncer: work.util.debounce_block_us
496generic map (g => g, N => sw'length, timer_period_us => timer_period_us)
497port map (clk => clk, di => sw, do => sw_d);
498--- Switches ------------------------------------------------------
499
500--- Memory Interface ----------------------------------------------
501ram_interface_0: entity work.ram_interface
502generic map (g => g)
503port map (
504clk => clk,
505rst => rst,
506mem_addr_16_1 => io_dout(io_dout'high downto 1),
507mem_addr_16_1_we => mem_addr_16_1_we,
508mem_addr_26_17 => io_dout(9 downto 0),
509mem_addr_26_17_we => mem_addr_26_17_we,
510mem_control_i => io_dout(15 downto 10),
511mem_control_we => mem_control_we,
512mem_data_i => io_dout,
513mem_data_i_we => mem_data_i_we,
514mem_data_o => mem_data_o,
515ram_cs => ram_cs,
516mem_oe => mem_oe,
517mem_wr => mem_wr,
518mem_adv => mem_adv,
519mem_wait => mem_wait,
520flash_cs => flash_cs,
521flash_rp => flash_rp,
522mem_addr => mem_addr,
523mem_data => mem_data);
524--- Memory Interface ----------------------------------------------
525
526-------------------------------------------------------------------------------
527end architecture;
528
529