aboutsummaryrefslogtreecommitdiff
path: root/src/main-keyboard.vhd
blob: 14fd24f049e19905031bdc67cc8217e13fe437c4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;

entity main is
	port(
		CLK100: in std_logic; -- system clock
		PS2_CLK: in std_logic; -- async ps/2 clock input
		PS2_DAT: in std_logic; -- async ps/2 data input
		DD: out std_logic_vector(7 downto 0); -- display segment data
		DS: out std_logic_vector(3 downto 0)); -- display select
end main;

architecture Behavioral of main is
	component ps2sync
		port(
			CLK: in std_logic; -- system clock
			PS2_CLK: in std_logic; -- async ps/2 clock input
			PS2_DAT: in std_logic; -- async ps/2 data input
			DAT: out std_logic_vector(7 downto 0); -- scancode data
			NEW_DAT: out std_logic); -- if scancode was just completed (1 for once clock cycle)
	end component;
	component scancodefilter
		port(
			CLK: in std_logic; -- system clock
			DAT: in std_logic_vector(7 downto 0); -- scancode input
			NEW_DAT: in std_logic; -- new scancode input
			BCD: out std_logic_vector(3 downto 0); -- bcd digit 0-9 or dash (0xB) for keypress
			SHIFT: out std_logic); -- shift display (1 for one clock cycle per key down press)
	end component;
	component dispshift
		port(
			CLK: in std_logic; -- system clock
			S: in std_logic; -- shift
			D: in std_logic_vector(3 downto 0); -- shift input (data)
			N0, N1, N2, N3: out std_logic_vector(3 downto 0)); -- shift outputs
	end component;
	component bcd2disp
		port (
			CLK: in std_logic; -- system clock
			N0, N1, N2, N3: in std_logic_vector(3 downto 0); -- shift inputs
			DD: out std_logic_vector(7 downto 0); -- display data
			DS: out std_logic_vector(3 downto 0)); -- display select
	end component;
	signal SYNC_DAT: std_logic_vector(7 downto 0); -- ps2sync <-> scancodefilter
	signal SYNC_DAT_NEW: std_logic; -- ps2sync <-> scancodefilter
	signal BCD_NEW: std_logic_vector(3 downto 0); -- scancodefilter <-> dispshift
	signal BCD_SHIFT: std_logic; -- scancodefilter <-> dispshift
	signal N0, N1, N2, N3: std_logic_vector(3 downto 0); -- inputs for display
	signal DISP_CLK: std_logic_vector(16 downto 0); -- clock counter for display clock
	-- clock period = (2 << 16) / 100_000_000 = 1.31 ms per display / 5.24 ms full refresh
begin
	-- convert async ps2 signals into synchronous lines
	ps2: component ps2sync
		port map (
			CLK => CLK100,
			PS2_CLK => PS2_CLK,
			PS2_DAT => PS2_DAT,
			DAT => SYNC_DAT,
			NEW_DAT => SYNC_DAT_NEW);
	
	-- filter key up scancodes, and convert non-numeric keys into "-" (0xB)
	filter: component scancodefilter
		port map(
			CLK => CLK100,
			DAT => SYNC_DAT,
			NEW_DAT => SYNC_DAT_NEW,
			BCD => BCD_NEW,
			SHIFT => BCD_SHIFT);
	
	-- display 'shift register'
	shift_register: component dispshift
		port map(
			CLK => CLK100,
			S => BCD_SHIFT,
			D => BCD_NEW,
			N0 => N0,
			N1 => N1,
			N2 => N2,
			N3 => N3);

	-- display driver clock divider
	process(CLK100)
	begin
		if rising_edge(CLK100) then
			DISP_CLK <= (DISP_CLK + 1);
		end if;
	end process;

	-- numbers N0-N3 to displays 0-3
	disp: component bcd2disp
		port map (
			CLK => DISP_CLK(16),
			N0 => N3,
			N1 => N2,
			N2 => N1,
			N3 => N0,
			DD => DD,
			DS => DS);
end Behavioral;