The Atom Keyboard

The Atom reads the keyboard data from the memory map, as 10 rows of 6 columns.
Where there are two characters shown the second is the shifted character.
Characters that may cause trouble due to PS/2 keyboard incompatibilities are coloured red.
The row is selected by writing to the 6502's memory-mapped 8255 port A at address 0xB000.
The data are read selected by reading to the 8255 port B at address 0xB001.

Row   Data (read)
    7 6 5 4 3 2 1 0
0   s
h
i
f
t
c
t
r
l
ESC Q G - = 3 #  
1   Z P F , < 2 "  
2   Y O E ; + 1 !
3   X N D : * 0
4   W M C 9 ) del lock
5   V L B 8 ( copy up
6   U K A 7 ' ret ]
7   T J @ 6 &   \
8   S I / ? 5 %   [
9   R H . > 4 $   sp

PS/2 Scan code to Atom Matrix conversion

PC
kbd
--> PS/2
interface
-scan-code-> FIFO -> Atom Keyboard
Matrix Encoder
<-- 4-bit row addr
--> 6-bit row data
--> 2-bit shift and ctrl
Atom
8255
chip
           
<-- <-control-codes-   <-- encoder <-- status for LEDs

Interfacing

A simple way would be to connect the FPGA to the Atom's 8255 I/O pins.

A better way might be to implement the 8255 chip in VHDL, and simply connect to the data bus and chip select. The 8255 is capable of three modes of operation and programmable direction, but the Atom uses the 8255 in mode zero - simple I/O - and the I/O directions are fixed. So the complexity of the 8255 in the Atom can be reduced to 24 simple I/O signals within the FPGA, and not all of them need to physical I/O pins.

Interfacing

The PS/2 code to Atom matrix is like so (all codes in hex)
s indicates the state of the PC's shift key
--- indicates no matrix position.

	PS/2	Ascii	Matrix (S=shift, C=bit column, R=byte row
Shift	scan	char	Atom SRC
s	66	08	???	// Backspace ("backspace" key)
s	0d	09	???	// Horizontal Tab
s	5a	0d	s61	// Carriage return ("enter" key)
s	76	1b	s05	// Escape ("esc" key)
s	29	20	s90	// Space
1	16	21	121	// !
1	52	22	111	// "
1	26	23	101	// #
1	25	24	192	// $
1	2e	25	182	// %
1	3d	26	172	// &
0	52	27	---	// ' (under the @ key)
1	46	28	152	// (
1	45	29	142	// )
1	3e	2a	132	// *
1	55	2b	122	// +
0	41	2c	012	// ,
0	4e	2d	002	// -
0	49	2e	093	// .
0	4a	2f	083	// /
0	45	30	031	// 0
0	16	31	021	// 1
0	1e	32	011	// 2
0	26	33	001	// 3
0	25	34	092	// 4
0	2e	35	082	// 5
0	36	36	072	// 6
0	3d	37	062	// 7
0	3e	38	052	// 8
0	46	39	042	// 9
1	4c	3a	032	// :
0	4c	3b	022	// ;
1	41	3c	112	// <
0	55	3d	102	// =
1	49	3e	193	// >
1	4a	3f	183	// ?
1	1e	40	073	// @
1	1c	41	063	// A
1	32	42	053	// B
1	21	43	043	// C
1	23	44	033	// D
1	24	45	023	// E
1	2b	46	013	// F
1	34	47	003	// G
1	33	48	094	// H
1	43	49	084	// I
1	3b	4a	074	// J
1	42	4b	064	// K
1	4b	4c	054	// L
1	3a	4d	044	// M
1	31	4e	034	// N
1	44	4f	024	// O
1	4d	50	014	// P
1	15	51	004	// Q
1	2d	52	095	// R
1	1b	53	085	// S
1	2c	54	075	// T
1	3c	55	065	// U
1	2a	56	055	// V
1	1d	57	045	// W
1	22	58	035	// X
1	35	59	025	// Y
1	1a	5a	015	// Z
0	54	5b	s60	// [
0	5d	5c	s50	// \
0	5b	5d	s40	// ]
1	36	5e	s--	// ^ (Not on Atom)
1	4e	5f	s--	// _ (Not on Atom)
0	0e	60	s--	// ` (left of the '1' key). (Not on Atom)
0	1c	61	173	// a
0	32	62	163	// b
0	21	63	153	// c
0	23	64	143	// d
0	24	65	133	// e
0	2b	66	123	// f
0	34	67	113	// g
0	33	68	194	// h
0	43	69	184	// i
0	3b	6a	174	// j
0	42	6b	164	// k
0	4b	6c	154	// l
0	3a	6d	144	// m
0	31	6e	134	// n
0	44	6f	124	// o
0	4d	70	114	// p
0	15	71	104	// q
0	2d	72	195	// r
0	1b	73	185	// s
0	2c	74	175	// t
0	3c	75	165	// u
0	2a	76	155	// v
0	1d	77	145	// w
0	22	78	135	// x
0	35	79	125	// y
0	1a	7a	115	// z
1	54	7b	s--	// { (Not on Atom)
1	5d	7c	s--	// | (Not on Atom)
1	5b	7d	s--	// } (Not on Atom)
1	0e	7e	s--	// ~ (Not on Atom)
s	71	7f	s41	// (Delete OR DEL on numeric keypad)
				// Specials:
X	F0			// Indicates the next key code is for the key release

The PC defaults to lower case a-z, and the shift key produces upper-case.
The Atom defaults to upper case A-Z, and the shift key produces inverted A-Z.
Thus the PC's shift sense has to be inverted for these characters.