mirror of
https://github.com/Gehstock/Mist_FPGA.git
synced 2026-01-23 02:37:52 +00:00
414 lines
12 KiB
Systemverilog
414 lines
12 KiB
Systemverilog
module LaserKeyboard(
|
||
input wire CLK50MHZ,
|
||
input wire [15:0] CPU_A,
|
||
input wire RESET,
|
||
input wire CASS_IN,
|
||
input wire PS2_KBCLK,
|
||
input wire PS2_KBDAT
|
||
);
|
||
|
||
|
||
// keyboard
|
||
reg [4:0] KB_CLK;
|
||
reg [16:0] RESET_KEY_COUNT;
|
||
wire [7:0] SCAN;
|
||
wire PRESS;
|
||
wire PRESS_N;
|
||
wire EXTENDED;
|
||
reg BOOTROM_EN;
|
||
reg [7:0] BOOTROM_BANK;
|
||
reg AUTOSTARTROM_EN;
|
||
reg [7:0] AUTOSTARTROM_BANK;
|
||
reg [63:0] KEY;
|
||
reg [9:0] KEY_EX;
|
||
reg [11:0] KEY_Fxx;
|
||
wire [7:0] KEY_DATA;
|
||
//reg [63:0] LAST_KEY;
|
||
//reg CAPS_CLK;
|
||
//reg CAPS;
|
||
wire A_KEY_PRESSED;
|
||
|
||
reg [7:0] LATCHED_KEY_DATA;
|
||
|
||
// emu keyboard
|
||
wire [63:0] EMU_KEY;
|
||
wire [9:0] EMU_KEY_EX;
|
||
wire EMU_KEY_EN;
|
||
// keyboard
|
||
|
||
/*****************************************************************************
|
||
* Convert PS/2 keyboard to ASCII keyboard
|
||
******************************************************************************/
|
||
|
||
/*
|
||
KD5 KD4 KD3 KD2 KD1 KD0 扫描用地址
|
||
A0 R Q E W T 68FEH 0
|
||
A1 F A D CTRL S G 68FDH 8
|
||
A2 V Z C SHFT X B 68FBH 16
|
||
A3 4 1 3 2 5 68F7H 24
|
||
A4 M 空格 , . N 68EFH 32
|
||
A5 7 0 8 - 9 6 68DFH 40
|
||
A6 U P I RETN O Y 68BFH 48
|
||
A7 J ; K : L H 687FH 56
|
||
*/
|
||
|
||
// 7: 0
|
||
// 15: 8
|
||
// 23:16
|
||
// 31:24
|
||
// 39:32
|
||
// 47:40
|
||
// 55:48
|
||
// 63:56
|
||
|
||
|
||
|
||
// 键盘检测的方法,就是循环地问每一行线发送低电平信号,也就是用该地址线为“0”的地址去读取数据。
|
||
// 例如,检测第一行时,使A0为0,其余为1;加上选通IC4的高五位地址01101,成为01101***11111110B(A8~A10不起作用,
|
||
// 可为任意值,故68FEH,69FEH,6AFEH,6BFEH,6CFEH,6DFEH,6EFEH,6FFEH均可)。
|
||
// 读 6800H 判断是否有按键按下。
|
||
|
||
// The method of keyboard detection is to cyclically ask each line to send a low level signal,
|
||
// that is, to read the data with the address line "0".
|
||
// For example, when detecting the first line, make A0 0 and the rest 1; plus the high five-bit address 01101 of the strobe IC4,
|
||
// become 01101***11111110B (A8~A10 does not work,
|
||
// It can be any value, so 68FEH, 69FEH, 6AFEH, 6BFEH, 6CFEH, 6DFEH, 6EFEH, 6FFEH can be).
|
||
// Read 6800H to determine if there is a button press.
|
||
|
||
// 键盘选通,整个竖列有一个选通的位置被按下,对应值为0。
|
||
// The keyboard is strobed, and a strobe position is pressed in the entire vertical column, and the corresponding value is 0.
|
||
|
||
// 键盘扩展
|
||
// 加入方向键盘
|
||
// Keyboard extension
|
||
|
||
// left: ctrl M 37 KEY_EX[5]
|
||
// right: ctrl , 35 KEY_EX[6]
|
||
// up: ctrl . 33 KEY_EX[4]
|
||
// down: ctrl space 36 KEY_EX[7]
|
||
// esc: ctrl - 42 KEY_EX[3]
|
||
// backspace: ctrl M 37 KEY_EX[8]
|
||
|
||
// R-Shift
|
||
|
||
|
||
wire [63:0] KEY_C = EMU_KEY_EN?EMU_KEY:KEY;
|
||
wire [9:0] KEY_EX_C = EMU_KEY_EN?EMU_KEY_EX:KEY_EX;
|
||
|
||
//wire KEY_CTRL_ULRD = (KEY_EX[7:4]==4'b1111);
|
||
wire KEY_CTRL_ULRD_BRK = (KEY_EX[8:3]==6'b111111);
|
||
|
||
wire KEY_DATA_BIT5 = (CPU_A[7:0]|{KEY_C[61], KEY_C[53], KEY_C[45], KEY_C[37]&KEY_EX_C[5]&KEY_EX_C[8], KEY_C[29], KEY_C[21], KEY_C[13], KEY_C[ 5]})==8'hff;
|
||
wire KEY_DATA_BIT4 = (CPU_A[7:0]|{KEY_C[60], KEY_C[52], KEY_C[44], KEY_C[36]&KEY_EX_C[7], KEY_C[28], KEY_C[20], KEY_C[12], KEY_C[ 4]})==8'hff;
|
||
wire KEY_DATA_BIT3 = (CPU_A[7:0]|{KEY_C[59], KEY_C[51], KEY_C[43], KEY_C[35]&KEY_EX_C[6], KEY_C[27], KEY_C[19], KEY_C[11], KEY_C[ 3]})==8'hff;
|
||
wire KEY_DATA_BIT2 = (CPU_A[7:0]|{KEY_C[58], KEY_C[50], KEY_C[42]&KEY_EX_C[3], KEY_C[34], KEY_C[26], KEY_C[18]&KEY_EX_C[0], KEY_C[10]&KEY_CTRL_ULRD_BRK, KEY_C[ 2]})==8'hff;
|
||
wire KEY_DATA_BIT1 = (CPU_A[7:0]|{KEY_C[57], KEY_C[49], KEY_C[41], KEY_C[33]&KEY_EX_C[4], KEY_C[25], KEY_C[17], KEY_C[ 9], KEY_C[ 1]})==8'hff;
|
||
wire KEY_DATA_BIT0 = (CPU_A[7:0]|{KEY_C[56], KEY_C[48], KEY_C[40], KEY_C[32], KEY_C[24], KEY_C[16], KEY_C[ 8], KEY_C[ 0]})==8'hff;
|
||
|
||
/*
|
||
wire KEY_DATA_BIT5 = (CPU_A[7:0]|{KEY[61], KEY[53], KEY[45], KEY[37], KEY[29], KEY[21], KEY[13], KEY[ 5]})==8'hff;
|
||
wire KEY_DATA_BIT4 = (CPU_A[7:0]|{KEY[60], KEY[52], KEY[44], KEY[36], KEY[28], KEY[20], KEY[12], KEY[ 4]})==8'hff;
|
||
wire KEY_DATA_BIT3 = (CPU_A[7:0]|{KEY[59], KEY[51], KEY[43], KEY[35], KEY[27], KEY[19], KEY[11], KEY[ 3]})==8'hff;
|
||
wire KEY_DATA_BIT2 = (CPU_A[7:0]|{KEY[58], KEY[50], KEY[42], KEY[34], KEY[26], KEY[18], KEY[10], KEY[ 2]})==8'hff;
|
||
wire KEY_DATA_BIT1 = (CPU_A[7:0]|{KEY[57], KEY[49], KEY[41], KEY[33], KEY[25], KEY[17], KEY[ 9], KEY[ 1]})==8'hff;
|
||
wire KEY_DATA_BIT0 = (CPU_A[7:0]|{KEY[56], KEY[48], KEY[40], KEY[32], KEY[24], KEY[16], KEY[ 8], KEY[ 0]})==8'hff;
|
||
*/
|
||
|
||
wire KEY_DATA_BIT7 = 1'b1; // 没有空置,具体用途没有理解
|
||
//wire KEY_DATA_BIT6 = CASS_IN;
|
||
wire KEY_DATA_BIT6 = ~CASS_IN;
|
||
|
||
assign KEY_DATA = { KEY_DATA_BIT7, KEY_DATA_BIT6, KEY_DATA_BIT5, KEY_DATA_BIT4, KEY_DATA_BIT3, KEY_DATA_BIT2, KEY_DATA_BIT1, KEY_DATA_BIT0 };
|
||
|
||
/*
|
||
assign KEY_DATA = (CPU_A[0]==1'b0) ? KEY[ 7: 0] :
|
||
(CPU_A[1]==1'b0) ? KEY[15: 8] :
|
||
(CPU_A[2]==1'b0) ? KEY[23:16] :
|
||
(CPU_A[3]==1'b0) ? KEY[31:24] :
|
||
(CPU_A[4]==1'b0) ? KEY[39:32] :
|
||
(CPU_A[5]==1'b0) ? KEY[47:40] :
|
||
(CPU_A[6]==1'b0) ? KEY[55:48] :
|
||
(CPU_A[7]==1'b0) ? KEY[63:56] :
|
||
8'hff;
|
||
|
||
assign KEY_DATA =
|
||
(CPU_A[7]==1'b0) ? KEY[63:56] :
|
||
(CPU_A[6]==1'b0) ? KEY[55:48] :
|
||
(CPU_A[5]==1'b0) ? KEY[47:40] :
|
||
(CPU_A[4]==1'b0) ? KEY[39:32] :
|
||
(CPU_A[3]==1'b0) ? KEY[31:24] :
|
||
(CPU_A[2]==1'b0) ? KEY[23:16] :
|
||
(CPU_A[1]==1'b0) ? KEY[15: 8] :
|
||
(CPU_A[0]==1'b0) ? KEY[ 7: 0] :
|
||
8'hff;
|
||
*/
|
||
|
||
|
||
assign A_KEY_PRESSED = (KEY[63:0] == 64'hFFFFFFFFFFFFFFFF) ? 1'b0:1'b1;
|
||
|
||
always @(posedge KB_CLK[3] or negedge RESET)
|
||
begin
|
||
if(~RESET)
|
||
begin
|
||
KEY <= 64'hFFFFFFFFFFFFFFFF;
|
||
KEY_EX <= 10'h3FF;
|
||
KEY_Fxx <= 12'h000;
|
||
// CAPS_CLK <= 1'b0;
|
||
RESET_KEY_COUNT <= 17'h1FFFF;
|
||
|
||
BOOTROM_BANK <= 0;
|
||
BOOTROM_EN <= 1'b0;
|
||
|
||
AUTOSTARTROM_BANK <= 0;
|
||
AUTOSTARTROM_EN <= 1'b0;
|
||
end
|
||
else
|
||
begin
|
||
//KEY[?] <= CAPS;
|
||
if(RESET_KEY_COUNT[16]==1'b0)
|
||
RESET_KEY_COUNT <= RESET_KEY_COUNT+1;
|
||
|
||
case(SCAN)
|
||
/*8'h07:
|
||
begin
|
||
KEY_Fxx[11] <= PRESS; // F12 RESET
|
||
if(PRESS && (KEY[10]==PRESS_N))
|
||
begin
|
||
BOOTROM_EN <= 1'b0;
|
||
BOOTROM_BANK <= 0;
|
||
AUTOSTARTROM_EN <= 1'b0;
|
||
AUTOSTARTROM_BANK <= 0;
|
||
RESET_KEY_COUNT <= 17'h0;
|
||
end
|
||
end
|
||
8'h78: KEY_Fxx[10] <= PRESS; // F11
|
||
8'h09: KEY_Fxx[ 9] <= PRESS; // F10 CASS STOP
|
||
8'h01: KEY_Fxx[ 8] <= PRESS; // F9 CASS PLAY
|
||
8'h0A:
|
||
begin
|
||
KEY_Fxx[ 7] <= PRESS; // F8 Ctrl or L-Shift BOOT 8
|
||
if(PRESS && (KEY[18]==PRESS_N))
|
||
begin
|
||
BOOTROM_EN <= 1'b1;
|
||
BOOTROM_BANK <= 39;
|
||
RESET_KEY_COUNT <= 17'h0;
|
||
end
|
||
else
|
||
if(PRESS && (KEY[10]==PRESS_N))
|
||
begin
|
||
AUTOSTARTROM_EN <= 1'b1;
|
||
AUTOSTARTROM_BANK <= 23;
|
||
RESET_KEY_COUNT <= 17'h0;
|
||
end
|
||
end
|
||
8'h83:
|
||
begin
|
||
KEY_Fxx[ 6] <= PRESS; // F7 Ctrl or L-Shift BOOT 7
|
||
if(PRESS && (KEY[18]==PRESS_N))
|
||
begin
|
||
BOOTROM_EN <= 1'b1;
|
||
BOOTROM_BANK <= 38;
|
||
RESET_KEY_COUNT <= 17'h0;
|
||
end
|
||
else
|
||
if(PRESS && (KEY[10]==PRESS_N))
|
||
begin
|
||
AUTOSTARTROM_EN <= 1'b1;
|
||
AUTOSTARTROM_BANK <= 22;
|
||
RESET_KEY_COUNT <= 17'h0;
|
||
end
|
||
end
|
||
8'h0B:
|
||
begin
|
||
KEY_Fxx[ 5] <= PRESS; // F6 Ctrl or L-Shift BOOT 6
|
||
if(PRESS && (KEY[18]==PRESS_N))
|
||
begin
|
||
BOOTROM_EN <= 1'b1;
|
||
BOOTROM_BANK <= 37;
|
||
RESET_KEY_COUNT <= 17'h0;
|
||
end
|
||
else
|
||
if(PRESS && (KEY[10]==PRESS_N))
|
||
begin
|
||
AUTOSTARTROM_EN <= 1'b1;
|
||
AUTOSTARTROM_BANK <= 21;
|
||
RESET_KEY_COUNT <= 17'h0;
|
||
end
|
||
end
|
||
8'h03:
|
||
begin
|
||
KEY_Fxx[ 4] <= PRESS; // F5 Ctrl or L-Shift BOOT 5
|
||
if(PRESS && (KEY[18]==PRESS_N))
|
||
begin
|
||
BOOTROM_EN <= 1'b1;
|
||
BOOTROM_BANK <= 36;
|
||
RESET_KEY_COUNT <= 17'h0;
|
||
end
|
||
else
|
||
if(PRESS && (KEY[10]==PRESS_N))
|
||
begin
|
||
AUTOSTARTROM_EN <= 1'b1;
|
||
AUTOSTARTROM_BANK <= 20;
|
||
RESET_KEY_COUNT <= 17'h0;
|
||
end
|
||
end
|
||
8'h0C:
|
||
begin
|
||
KEY_Fxx[ 3] <= PRESS; // F4 Ctrl or L-Shift BOOT 4
|
||
if(PRESS && (KEY[18]==PRESS_N))
|
||
begin
|
||
BOOTROM_EN <= 1'b1;
|
||
BOOTROM_BANK <= 35;
|
||
RESET_KEY_COUNT <= 17'h0;
|
||
end
|
||
else
|
||
if(PRESS && (KEY[10]==PRESS_N))
|
||
begin
|
||
AUTOSTARTROM_EN <= 1'b1;
|
||
AUTOSTARTROM_BANK <= 19;
|
||
RESET_KEY_COUNT <= 17'h0;
|
||
end
|
||
end
|
||
8'h04:
|
||
begin
|
||
KEY_Fxx[ 2] <= PRESS; // F3 Ctrl or L-Shift BOOT 3
|
||
if(PRESS && (KEY[18]==PRESS_N))
|
||
begin
|
||
BOOTROM_EN <= 1'b1;
|
||
BOOTROM_BANK <= 34;
|
||
RESET_KEY_COUNT <= 17'h0;
|
||
end
|
||
else
|
||
if(PRESS && (KEY[10]==PRESS_N))
|
||
begin
|
||
AUTOSTARTROM_EN <= 1'b1;
|
||
AUTOSTARTROM_BANK <= 18;
|
||
RESET_KEY_COUNT <= 17'h0;
|
||
end
|
||
end
|
||
8'h06:
|
||
begin
|
||
KEY_Fxx[ 1] <= PRESS; // F2 Ctrl or L-Shift BOOT 2
|
||
if(PRESS && (KEY[18]==PRESS_N))
|
||
begin
|
||
BOOTROM_EN <= 1'b1;
|
||
BOOTROM_BANK <= 33;
|
||
RESET_KEY_COUNT <= 17'h0;
|
||
end
|
||
else
|
||
if(PRESS && (KEY[10]==PRESS_N))
|
||
begin
|
||
AUTOSTARTROM_EN <= 1'b1;
|
||
AUTOSTARTROM_BANK <= 17;
|
||
RESET_KEY_COUNT <= 17'h0;
|
||
end
|
||
end
|
||
8'h05:
|
||
begin
|
||
KEY_Fxx[ 0] <= PRESS; // F1 Ctrl or L-Shift BOOT 1
|
||
if(PRESS && (KEY[18]==PRESS_N))
|
||
begin
|
||
BOOTROM_EN <= 1'b1;
|
||
BOOTROM_BANK <= 32;
|
||
RESET_KEY_COUNT <= 17'h0;
|
||
end
|
||
else
|
||
if(PRESS && (KEY[10]==PRESS_N))
|
||
begin
|
||
AUTOSTARTROM_EN <= 1'b1;
|
||
AUTOSTARTROM_BANK <= 16;
|
||
RESET_KEY_COUNT <= 17'h0;
|
||
end
|
||
end*/
|
||
|
||
8'h16: KEY[28] <= PRESS_N; // 1 !
|
||
8'h1E: KEY[25] <= PRESS_N; // 2 @
|
||
8'h26: KEY[27] <= PRESS_N; // 3 #
|
||
8'h25: KEY[29] <= PRESS_N; // 4 $
|
||
8'h2E: KEY[24] <= PRESS_N; // 5 %
|
||
8'h36: KEY[40] <= PRESS_N; // 6 ^
|
||
8'h3D: KEY[45] <= PRESS_N; // 7 &
|
||
// 8'h0D: KEY[?] <= PRESS_N; // TAB
|
||
8'h3E: KEY[43] <= PRESS_N; // 8 *
|
||
8'h46: KEY[41] <= PRESS_N; // 9 (
|
||
8'h45: KEY[44] <= PRESS_N; // 0 )
|
||
8'h4E: KEY[42] <= PRESS_N; // - _
|
||
// 8'h55: KEY[?] <= PRESS_N; // = +
|
||
8'h66: KEY_EX[8] <= PRESS_N; // backspace
|
||
// 8'h0E: KEY[?] <= PRESS_N; // ` ~
|
||
// 8'h5D: KEY[?] <= PRESS_N; // \ |
|
||
8'h49: KEY[33] <= PRESS_N; // . >
|
||
8'h4b: KEY[57] <= PRESS_N; // L
|
||
8'h44: KEY[49] <= PRESS_N; // O
|
||
// 8'h11 KEY[?] <= PRESS_N; // line feed (really right ALT (Extended) see below
|
||
8'h5A: KEY[50] <= PRESS_N; // CR
|
||
// 8'h54: KEY[?] <= PRESS_N; // [ {
|
||
// 8'h5B: KEY[?] <= PRESS_N; // ] }
|
||
8'h52: KEY[58] <= PRESS_N; // ' "
|
||
8'h1D: KEY[ 1] <= PRESS_N; // W
|
||
8'h24: KEY[ 3] <= PRESS_N; // E
|
||
8'h2D: KEY[ 5] <= PRESS_N; // R
|
||
8'h2C: KEY[ 0] <= PRESS_N; // T
|
||
8'h35: KEY[48] <= PRESS_N; // Y
|
||
8'h3C: KEY[53] <= PRESS_N; // U
|
||
8'h43: KEY[51] <= PRESS_N; // I
|
||
8'h1B: KEY[ 9] <= PRESS_N; // S
|
||
8'h23: KEY[11] <= PRESS_N; // D
|
||
8'h2B: KEY[13] <= PRESS_N; // F
|
||
8'h34: KEY[ 8] <= PRESS_N; // G
|
||
8'h33: KEY[56] <= PRESS_N; // H
|
||
8'h3B: KEY[61] <= PRESS_N; // J
|
||
8'h42: KEY[59] <= PRESS_N; // K
|
||
8'h22: KEY[17] <= PRESS_N; // X
|
||
8'h21: KEY[19] <= PRESS_N; // C
|
||
8'h2a: KEY[21] <= PRESS_N; // V
|
||
8'h32: KEY[16] <= PRESS_N; // B
|
||
8'h31: KEY[32] <= PRESS_N; // N
|
||
8'h3a: KEY[37] <= PRESS_N; // M
|
||
8'h41: KEY[35] <= PRESS_N; // , <
|
||
8'h15: KEY[ 4] <= PRESS_N; // Q
|
||
8'h1C: KEY[12] <= PRESS_N; // A
|
||
8'h1A: KEY[20] <= PRESS_N; // Z
|
||
8'h29: KEY[36] <= PRESS_N; // Space
|
||
// 8'h4A: KEY[?] <= PRESS_N; // / ?
|
||
8'h4C: KEY[60] <= PRESS_N; // ; :
|
||
8'h4D: KEY[52] <= PRESS_N; // P
|
||
8'h14: KEY[10] <= PRESS_N; // Ctrl either left or right
|
||
8'h12: KEY[18] <= PRESS_N; // L-Shift
|
||
8'h59: KEY_EX[0] <= PRESS_N; // R-Shift
|
||
8'h11:
|
||
begin
|
||
if(~EXTENDED)
|
||
KEY_EX[1] <= PRESS_N; // Repeat really left ALT
|
||
else
|
||
KEY_EX[2] <= PRESS_N; // LF really right ALT
|
||
end
|
||
8'h76: KEY_EX[3] <= PRESS_N; // Esc
|
||
8'h75: KEY_EX[4] <= PRESS_N; // up
|
||
8'h6B: KEY_EX[5] <= PRESS_N; // left
|
||
8'h74: KEY_EX[6] <= PRESS_N; // right
|
||
8'h72: KEY_EX[7] <= PRESS_N; // down
|
||
endcase
|
||
end
|
||
end
|
||
|
||
|
||
|
||
|
||
always @ (posedge CLK50MHZ) // 50MHz
|
||
KB_CLK <= KB_CLK + 1'b1; // 50/32 = 1.5625 MHz
|
||
|
||
ps2_keyboard KEYBOARD(
|
||
.RESET_N(~RESET),
|
||
.CLK(KB_CLK[4]),
|
||
.PS2_CLK(PS2_KBCLK),
|
||
.PS2_DATA(PS2_KBDAT),
|
||
.RX_SCAN(SCAN),
|
||
.RX_PRESSED(PRESS),
|
||
.RX_EXTENDED(EXTENDED)
|
||
);
|
||
|
||
assign PRESS_N = ~PRESS;
|
||
|
||
|
||
endmodule
|