MacPlus_MiSTer/ps2_kbd.sv

655 lines
13 KiB
Systemverilog

`timescale 1ns / 100ps
/*
* PS2 Keyboard to Mac interface module
*/
module ps2_kbd
(
input clk,
input ce,
input reset,
input [10:0] ps2_key,
output reg capslock,
input [7:0] data_out,
input strobe_out,
output [7:0] data_in,
output strobe_in
);
reg [8:0] keymac;
reg key_pending;
reg [21:0] pacetimer;
reg inquiry_active;
reg cmd_inquiry;
reg cmd_instant;
reg cmd_model;
reg cmd_test;
/* Latch commands from Mac */
always@(posedge clk or posedge reset) begin
if (reset) begin
cmd_inquiry <= 0;
cmd_instant <= 0;
cmd_model <= 0;
cmd_test <= 0;
end else if(ce) begin
if (strobe_out) begin
cmd_inquiry <= 0;
cmd_instant <= 0;
cmd_model <= 0;
cmd_test <= 0;
case(data_out)
8'h10: cmd_inquiry <= 1;
8'h14: cmd_instant <= 1;
8'h16: cmd_model <= 1;
8'h36: cmd_test <= 1;
endcase
end
end
end
/* Divide our clock to pace our responses to the Mac. tick_short ticks
* when we can respond to a command, and tick_long ticks when an inquiry
* command shall timeout
*/
always@(posedge clk or posedge reset) begin
if (reset)
pacetimer <= 0;
else if(ce) begin
/* reset counter on command from Mac */
if (strobe_out)
pacetimer <= 0;
else if (!tick_long)
pacetimer <= pacetimer + 1'd1;
end
end
wire tick_long = pacetimer == 22'h3fffff;
wire tick_short = pacetimer == 22'h000fff;
/* Delay inquiry responses to after tick_short */
always@(posedge clk or posedge reset) begin
if (reset)
inquiry_active <= 0;
else if(ce) begin
if (strobe_out | strobe_in)
inquiry_active <= 0;
else if (tick_short)
inquiry_active <= cmd_inquiry;
end
end
wire pop_key = (cmd_instant & tick_short) | (inquiry_active & tick_long) | (inquiry_active & key_pending);
/* Reply to Mac */
assign strobe_in = ((cmd_model | cmd_test) & tick_short) | pop_key;
/* Data to Mac */
assign data_in = cmd_test ? 8'h7d :
cmd_model ? 8'h03 :
key_pending ? (keymac[8] ? 8'h79 : keymac[7:0]) :
8'h7b;
wire depress = ~ps2_key[9];
wire extended = ps2_key[8];
wire ignore_capslock = {extended,ps2_key[7:0]} == 9'h058 && capslock;
/* Handle key_pending, and multi-byte keypad responses */
always @(posedge clk) begin
reg old_stb;
if (reset) begin
key_pending <= 0;
old_stb <= ps2_key[10];
capslock <= 0;
end
else if(ce) begin
if (cmd_model | cmd_test) key_pending <= 0;
else if (pop_key) begin
if (keymac[8]) keymac[8] <= 0;
else key_pending <= 0;
end else begin
old_stb <= ps2_key[10];
if(old_stb != ps2_key[10]) begin
/* Capslock handling */
if(ps2_key[7:0] == 8'h58 && !extended && !depress) capslock <= ~capslock;
if(!key_pending && !ignore_capslock) begin
key_pending <= 1;
keymac <= {key_code[8],depress,key_code[6:0]};
end
end
end
end
end
//use BRAM for table
wire [8:0] key_code = code[key_addr];
reg [8:0] key_addr;
always @(posedge clk) key_addr <= {extended,ps2_key[7:0]};
wire [8:0] code[512] =
'{
/* 000 */ 9'h07b,
/* 001 */ 9'h07b, //F9
/* 002 */ 9'h07b,
/* 003 */ 9'h07b, //F5
/* 004 */ 9'h07b, //F3
/* 005 */ 9'h07b, //F1
/* 006 */ 9'h07b, //F2
/* 007 */ 9'h07b, //F12 <OSD>
/* 008 */ 9'h07b,
/* 009 */ 9'h07b, //F10
/* 00a */ 9'h07b, //F8
/* 00b */ 9'h07b, //F6
/* 00c */ 9'h07b, //F4
/* 00d */ 9'h061, //TAB
/* 00e */ 9'h065, //~ (`)
/* 00f */ 9'h07b,
/* 010 */ 9'h07b,
/* 011 */ 9'h06f, //LEFT ALT (command)
/* 012 */ 9'h071, //LEFT SHIFT
/* 013 */ 9'h07b,
/* 014 */ 9'h07b, //CTRL (not mapped)
/* 015 */ 9'h019, //q
/* 016 */ 9'h025, //1
/* 017 */ 9'h07b,
/* 018 */ 9'h07b,
/* 019 */ 9'h07b,
/* 01a */ 9'h00d, //z
/* 01b */ 9'h003, //s
/* 01c */ 9'h001, //a
/* 01d */ 9'h01b, //w
/* 01e */ 9'h027, //2
/* 01f */ 9'h07b,
/* 020 */ 9'h07b,
/* 021 */ 9'h011, //c
/* 022 */ 9'h00f, //x
/* 023 */ 9'h005, //d
/* 024 */ 9'h01d, //e
/* 025 */ 9'h02b, //4
/* 026 */ 9'h029, //3
/* 027 */ 9'h07b,
/* 028 */ 9'h07b,
/* 029 */ 9'h063, //SPACE
/* 02a */ 9'h013, //v
/* 02b */ 9'h007, //f
/* 02c */ 9'h023, //t
/* 02d */ 9'h01f, //r
/* 02e */ 9'h02f, //5
/* 02f */ 9'h07b,
/* 030 */ 9'h07b,
/* 031 */ 9'h05b, //n
/* 032 */ 9'h017, //b
/* 033 */ 9'h009, //h
/* 034 */ 9'h00b, //g
/* 035 */ 9'h021, //y
/* 036 */ 9'h02d, //6
/* 037 */ 9'h07b,
/* 038 */ 9'h07b,
/* 039 */ 9'h07b,
/* 03a */ 9'h05d, //m
/* 03b */ 9'h04d, //j
/* 03c */ 9'h041, //u
/* 03d */ 9'h035, //7
/* 03e */ 9'h039, //8
/* 03f */ 9'h07b,
/* 040 */ 9'h07b,
/* 041 */ 9'h057, //<,
/* 042 */ 9'h051, //k
/* 043 */ 9'h045, //i
/* 044 */ 9'h03f, //o
/* 045 */ 9'h03b, //0
/* 046 */ 9'h033, //9
/* 047 */ 9'h07b,
/* 048 */ 9'h07b,
/* 049 */ 9'h05f, //>.
/* 04a */ 9'h059, //FORWARD SLASH
/* 04b */ 9'h04b, //l
/* 04c */ 9'h053, //;
/* 04d */ 9'h047, //p
/* 04e */ 9'h037, //-
/* 04f */ 9'h07b,
/* 050 */ 9'h07b,
/* 051 */ 9'h07b,
/* 052 */ 9'h04f, //'"
/* 053 */ 9'h07b,
/* 054 */ 9'h043, //[
/* 055 */ 9'h031, // =
/* 056 */ 9'h07b,
/* 057 */ 9'h07b,
/* 058 */ 9'h073, //CAPSLOCK
/* 059 */ 9'h071, //RIGHT SHIFT
/* 05a */ 9'h049, //ENTER
/* 05b */ 9'h03d, //]
/* 05c */ 9'h07b,
/* 05d */ 9'h055, //BACKSLASH
/* 05e */ 9'h07b,
/* 05f */ 9'h07b,
/* 060 */ 9'h07b,
/* 061 */ 9'h071, //international left shift cut out (German '<>' key), 0x56 Set#1 code
/* 062 */ 9'h07b,
/* 063 */ 9'h07b,
/* 064 */ 9'h07b,
/* 065 */ 9'h07b,
/* 066 */ 9'h067, //BACKSPACE
/* 067 */ 9'h07b,
/* 068 */ 9'h07b,
/* 069 */ 9'h127, //KP 1
/* 06a */ 9'h07b,
/* 06b */ 9'h12d, //KP 4
/* 06c */ 9'h133, //KP 7
/* 06d */ 9'h07b,
/* 06e */ 9'h07b,
/* 06f */ 9'h07b,
/* 070 */ 9'h125, //KP 0
/* 071 */ 9'h103, //KP .
/* 072 */ 9'h129, //KP 2
/* 073 */ 9'h12f, //KP 5
/* 074 */ 9'h131, //KP 6
/* 075 */ 9'h137, //KP 8
/* 076 */ 9'h07b, //ESCAPE
/* 077 */ 9'h07b, //NUMLOCK (Mac keypad clear?)
/* 078 */ 9'h07b, //F11 <OSD>
/* 079 */ 9'h10d, //KP +
/* 07a */ 9'h12b, //KP 3
/* 07b */ 9'h11d, //KP -
/* 07c */ 9'h105, //KP *
/* 07d */ 9'h139, //KP 9
/* 07e */ 9'h07b, //SCROLL LOCK / KP )
/* 07f */ 9'h07b,
/* 080 */ 9'h07b,
/* 081 */ 9'h07b,
/* 082 */ 9'h07b,
/* 083 */ 9'h07b, //F7
/* 084 */ 9'h07b,
/* 085 */ 9'h07b,
/* 086 */ 9'h07b,
/* 087 */ 9'h07b,
/* 088 */ 9'h07b,
/* 089 */ 9'h07b,
/* 08a */ 9'h07b,
/* 08b */ 9'h07b,
/* 08c */ 9'h07b,
/* 08d */ 9'h07b,
/* 08e */ 9'h07b,
/* 08f */ 9'h07b,
/* 090 */ 9'h07b,
/* 091 */ 9'h07b,
/* 092 */ 9'h07b,
/* 093 */ 9'h07b,
/* 094 */ 9'h07b,
/* 095 */ 9'h07b,
/* 096 */ 9'h07b,
/* 097 */ 9'h07b,
/* 098 */ 9'h07b,
/* 099 */ 9'h07b,
/* 09a */ 9'h07b,
/* 09b */ 9'h07b,
/* 09c */ 9'h07b,
/* 09d */ 9'h07b,
/* 09e */ 9'h07b,
/* 09f */ 9'h07b,
/* 0a0 */ 9'h07b,
/* 0a1 */ 9'h07b,
/* 0a2 */ 9'h07b,
/* 0a3 */ 9'h07b,
/* 0a4 */ 9'h07b,
/* 0a5 */ 9'h07b,
/* 0a6 */ 9'h07b,
/* 0a7 */ 9'h07b,
/* 0a8 */ 9'h07b,
/* 0a9 */ 9'h07b,
/* 0aa */ 9'h07b,
/* 0ab */ 9'h07b,
/* 0ac */ 9'h07b,
/* 0ad */ 9'h07b,
/* 0ae */ 9'h07b,
/* 0af */ 9'h07b,
/* 0b0 */ 9'h07b,
/* 0b1 */ 9'h07b,
/* 0b2 */ 9'h07b,
/* 0b3 */ 9'h07b,
/* 0b4 */ 9'h07b,
/* 0b5 */ 9'h07b,
/* 0b6 */ 9'h07b,
/* 0b7 */ 9'h07b,
/* 0b8 */ 9'h07b,
/* 0b9 */ 9'h07b,
/* 0ba */ 9'h07b,
/* 0bb */ 9'h07b,
/* 0bc */ 9'h07b,
/* 0bd */ 9'h07b,
/* 0be */ 9'h07b,
/* 0bf */ 9'h07b,
/* 0c0 */ 9'h07b,
/* 0c1 */ 9'h07b,
/* 0c2 */ 9'h07b,
/* 0c3 */ 9'h07b,
/* 0c4 */ 9'h07b,
/* 0c5 */ 9'h07b,
/* 0c6 */ 9'h07b,
/* 0c7 */ 9'h07b,
/* 0c8 */ 9'h07b,
/* 0c9 */ 9'h07b,
/* 0ca */ 9'h07b,
/* 0cb */ 9'h07b,
/* 0cc */ 9'h07b,
/* 0cd */ 9'h07b,
/* 0ce */ 9'h07b,
/* 0cf */ 9'h07b,
/* 0d0 */ 9'h07b,
/* 0d1 */ 9'h07b,
/* 0d2 */ 9'h07b,
/* 0d3 */ 9'h07b,
/* 0d4 */ 9'h07b,
/* 0d5 */ 9'h07b,
/* 0d6 */ 9'h07b,
/* 0d7 */ 9'h07b,
/* 0d8 */ 9'h07b,
/* 0d9 */ 9'h07b,
/* 0da */ 9'h07b,
/* 0db */ 9'h07b,
/* 0dc */ 9'h07b,
/* 0dd */ 9'h07b,
/* 0de */ 9'h07b,
/* 0df */ 9'h07b,
/* 0e0 */ 9'h07b, //ps2 extended key
/* 0e1 */ 9'h07b,
/* 0e2 */ 9'h07b,
/* 0e3 */ 9'h07b,
/* 0e4 */ 9'h07b,
/* 0e5 */ 9'h07b,
/* 0e6 */ 9'h07b,
/* 0e7 */ 9'h07b,
/* 0e8 */ 9'h07b,
/* 0e9 */ 9'h07b,
/* 0ea */ 9'h07b,
/* 0eb */ 9'h07b,
/* 0ec */ 9'h07b,
/* 0ed */ 9'h07b,
/* 0ee */ 9'h07b,
/* 0ef */ 9'h07b,
/* 0f0 */ 9'h07b, //ps2 release code
/* 0f1 */ 9'h07b,
/* 0f2 */ 9'h07b,
/* 0f3 */ 9'h07b,
/* 0f4 */ 9'h07b,
/* 0f5 */ 9'h07b,
/* 0f6 */ 9'h07b,
/* 0f7 */ 9'h07b,
/* 0f8 */ 9'h07b,
/* 0f9 */ 9'h07b,
/* 0fa */ 9'h07b, //ps2 ack code
/* 0fb */ 9'h07b,
/* 0fc */ 9'h07b,
/* 0fd */ 9'h07b,
/* 0fe */ 9'h07b,
/* 0ff */ 9'h07b,
/* 100 */ 9'h07b,
/* 101 */ 9'h07b,
/* 102 */ 9'h07b,
/* 103 */ 9'h07b,
/* 104 */ 9'h07b,
/* 105 */ 9'h07b,
/* 106 */ 9'h07b,
/* 107 */ 9'h07b,
/* 108 */ 9'h07b,
/* 109 */ 9'h07b,
/* 10a */ 9'h07b,
/* 10b */ 9'h07b,
/* 10c */ 9'h07b,
/* 10d */ 9'h07b,
/* 10e */ 9'h07b,
/* 10f */ 9'h07b,
/* 110 */ 9'h07b,
/* 111 */ 9'h06f, //RIGHT ALT (command)
/* 112 */ 9'h07b,
/* 113 */ 9'h07b,
/* 114 */ 9'h07b,
/* 115 */ 9'h07b,
/* 116 */ 9'h07b,
/* 117 */ 9'h07b,
/* 118 */ 9'h07b,
/* 119 */ 9'h07b,
/* 11a */ 9'h07b,
/* 11b */ 9'h07b,
/* 11c */ 9'h07b,
/* 11d */ 9'h07b,
/* 11e */ 9'h07b,
/* 11f */ 9'h075, //WINDOWS OR APPLICATION KEY (option)
/* 120 */ 9'h07b,
/* 121 */ 9'h07b,
/* 122 */ 9'h07b,
/* 123 */ 9'h07b,
/* 124 */ 9'h07b,
/* 125 */ 9'h07b,
/* 126 */ 9'h07b,
/* 127 */ 9'h07b,
/* 128 */ 9'h07b,
/* 129 */ 9'h07b,
/* 12a */ 9'h07b,
/* 12b */ 9'h07b,
/* 12c */ 9'h07b,
/* 12d */ 9'h07b,
/* 12e */ 9'h07b,
/* 12f */ 9'h07b,
/* 130 */ 9'h07b,
/* 131 */ 9'h07b,
/* 132 */ 9'h07b,
/* 133 */ 9'h07b,
/* 134 */ 9'h07b,
/* 135 */ 9'h07b,
/* 136 */ 9'h07b,
/* 137 */ 9'h07b,
/* 138 */ 9'h07b,
/* 139 */ 9'h07b,
/* 13a */ 9'h07b,
/* 13b */ 9'h07b,
/* 13c */ 9'h07b,
/* 13d */ 9'h07b,
/* 13e */ 9'h07b,
/* 13f */ 9'h07b,
/* 140 */ 9'h07b,
/* 141 */ 9'h07b,
/* 142 */ 9'h07b,
/* 143 */ 9'h07b,
/* 144 */ 9'h07b,
/* 145 */ 9'h07b,
/* 146 */ 9'h07b,
/* 147 */ 9'h07b,
/* 148 */ 9'h07b,
/* 149 */ 9'h07b,
/* 14a */ 9'h11b, //KP /
/* 14b */ 9'h07b,
/* 14c */ 9'h07b,
/* 14d */ 9'h07b,
/* 14e */ 9'h07b,
/* 14f */ 9'h07b,
/* 150 */ 9'h07b,
/* 151 */ 9'h07b,
/* 152 */ 9'h07b,
/* 153 */ 9'h07b,
/* 154 */ 9'h07b,
/* 155 */ 9'h07b,
/* 156 */ 9'h07b,
/* 157 */ 9'h07b,
/* 158 */ 9'h07b,
/* 159 */ 9'h07b,
/* 15a */ 9'h119, //KP ENTER
/* 15b */ 9'h07b,
/* 15c */ 9'h07b,
/* 15d */ 9'h07b,
/* 15e */ 9'h07b,
/* 15f */ 9'h07b,
/* 160 */ 9'h07b,
/* 161 */ 9'h07b,
/* 162 */ 9'h07b,
/* 163 */ 9'h07b,
/* 164 */ 9'h07b,
/* 165 */ 9'h07b,
/* 166 */ 9'h07b,
/* 167 */ 9'h07b,
/* 168 */ 9'h07b,
/* 169 */ 9'h07b, //END
/* 16a */ 9'h07b,
/* 16b */ 9'h10d, //ARROW LEFT
/* 16c */ 9'h07b, //HOME
/* 16d */ 9'h07b,
/* 16e */ 9'h07b,
/* 16f */ 9'h07b,
/* 170 */ 9'h07b, //INSERT = HELP
/* 171 */ 9'h10f, //DELETE (KP clear?)
/* 172 */ 9'h111, //ARROW DOWN
/* 173 */ 9'h07b,
/* 174 */ 9'h105, //ARROW RIGHT
/* 175 */ 9'h11b, //ARROW UP
/* 176 */ 9'h07b,
/* 177 */ 9'h07b,
/* 178 */ 9'h07b,
/* 179 */ 9'h07b,
/* 17a */ 9'h07b, //PGDN <OSD>
/* 17b */ 9'h07b,
/* 17c */ 9'h07b, //PRTSCR <OSD>
/* 17d */ 9'h07b, //PGUP <OSD>
/* 17e */ 9'h07b, //ctrl+break
/* 17f */ 9'h07b,
/* 180 */ 9'h07b,
/* 181 */ 9'h07b,
/* 182 */ 9'h07b,
/* 183 */ 9'h07b,
/* 184 */ 9'h07b,
/* 185 */ 9'h07b,
/* 186 */ 9'h07b,
/* 187 */ 9'h07b,
/* 188 */ 9'h07b,
/* 189 */ 9'h07b,
/* 18a */ 9'h07b,
/* 18b */ 9'h07b,
/* 18c */ 9'h07b,
/* 18d */ 9'h07b,
/* 18e */ 9'h07b,
/* 18f */ 9'h07b,
/* 190 */ 9'h07b,
/* 191 */ 9'h07b,
/* 192 */ 9'h07b,
/* 193 */ 9'h07b,
/* 194 */ 9'h07b,
/* 195 */ 9'h07b,
/* 196 */ 9'h07b,
/* 197 */ 9'h07b,
/* 198 */ 9'h07b,
/* 199 */ 9'h07b,
/* 19a */ 9'h07b,
/* 19b */ 9'h07b,
/* 19c */ 9'h07b,
/* 19d */ 9'h07b,
/* 19e */ 9'h07b,
/* 19f */ 9'h07b,
/* 1a0 */ 9'h07b,
/* 1a1 */ 9'h07b,
/* 1a2 */ 9'h07b,
/* 1a3 */ 9'h07b,
/* 1a4 */ 9'h07b,
/* 1a5 */ 9'h07b,
/* 1a6 */ 9'h07b,
/* 1a7 */ 9'h07b,
/* 1a8 */ 9'h07b,
/* 1a9 */ 9'h07b,
/* 1aa */ 9'h07b,
/* 1ab */ 9'h07b,
/* 1ac */ 9'h07b,
/* 1ad */ 9'h07b,
/* 1ae */ 9'h07b,
/* 1af */ 9'h07b,
/* 1b0 */ 9'h07b,
/* 1b1 */ 9'h07b,
/* 1b2 */ 9'h07b,
/* 1b3 */ 9'h07b,
/* 1b4 */ 9'h07b,
/* 1b5 */ 9'h07b,
/* 1b6 */ 9'h07b,
/* 1b7 */ 9'h07b,
/* 1b8 */ 9'h07b,
/* 1b9 */ 9'h07b,
/* 1ba */ 9'h07b,
/* 1bb */ 9'h07b,
/* 1bc */ 9'h07b,
/* 1bd */ 9'h07b,
/* 1be */ 9'h07b,
/* 1bf */ 9'h07b,
/* 1c0 */ 9'h07b,
/* 1c1 */ 9'h07b,
/* 1c2 */ 9'h07b,
/* 1c3 */ 9'h07b,
/* 1c4 */ 9'h07b,
/* 1c5 */ 9'h07b,
/* 1c6 */ 9'h07b,
/* 1c7 */ 9'h07b,
/* 1c8 */ 9'h07b,
/* 1c9 */ 9'h07b,
/* 1ca */ 9'h07b,
/* 1cb */ 9'h07b,
/* 1cc */ 9'h07b,
/* 1cd */ 9'h07b,
/* 1ce */ 9'h07b,
/* 1cf */ 9'h07b,
/* 1d0 */ 9'h07b,
/* 1d1 */ 9'h07b,
/* 1d2 */ 9'h07b,
/* 1d3 */ 9'h07b,
/* 1d4 */ 9'h07b,
/* 1d5 */ 9'h07b,
/* 1d6 */ 9'h07b,
/* 1d7 */ 9'h07b,
/* 1d8 */ 9'h07b,
/* 1d9 */ 9'h07b,
/* 1da */ 9'h07b,
/* 1db */ 9'h07b,
/* 1dc */ 9'h07b,
/* 1dd */ 9'h07b,
/* 1de */ 9'h07b,
/* 1df */ 9'h07b,
/* 1e0 */ 9'h07b, //ps2 extended key(duplicate, see $e0)
/* 1e1 */ 9'h07b,
/* 1e2 */ 9'h07b,
/* 1e3 */ 9'h07b,
/* 1e4 */ 9'h07b,
/* 1e5 */ 9'h07b,
/* 1e6 */ 9'h07b,
/* 1e7 */ 9'h07b,
/* 1e8 */ 9'h07b,
/* 1e9 */ 9'h07b,
/* 1ea */ 9'h07b,
/* 1eb */ 9'h07b,
/* 1ec */ 9'h07b,
/* 1ed */ 9'h07b,
/* 1ee */ 9'h07b,
/* 1ef */ 9'h07b,
/* 1f0 */ 9'h07b, //ps2 release code(duplicate, see $f0)
/* 1f1 */ 9'h07b,
/* 1f2 */ 9'h07b,
/* 1f3 */ 9'h07b,
/* 1f4 */ 9'h07b,
/* 1f5 */ 9'h07b,
/* 1f6 */ 9'h07b,
/* 1f7 */ 9'h07b,
/* 1f8 */ 9'h07b,
/* 1f9 */ 9'h07b,
/* 1fa */ 9'h07b, //ps2 ack code(duplicate see $fa)
/* 1fb */ 9'h07b,
/* 1fc */ 9'h07b,
/* 1fd */ 9'h07b,
/* 1fe */ 9'h07b,
/* 1ff */ 9'h07b
};
endmodule