You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

332 lines
12 KiB

module matrix_kbd ( input CLK, input RESET, input FREEZE, inout [15:0] ROWS, input [7:0] COLUMNS,
input [3:0] REPORT_ADRESS, output [7:0] REPORT_DATA, output INT, output DBG);
//output [7:0] kbd_r0, kbd_r2, kbd_r3, kbd_r4, kbd_r5, kbd_r6, kbd_r7, output INT);
// * - ESC (29), 7 - F1 (3A), 4 - F2 (3B), 1 - NUM_LOCK (53)
// 0 - CAPS LOCK (39), 8 - R (15), 5 - BACKSPACE (2A), 2 - ENTER (58)
// # - LSHIFT (E1), 9 - C (06), 6 - V (19), 3 - DELETE (4C)
// D - LCTRL (E0), C - LALT (E2), B - SPACE (2C), A - RGUI (E7)
parameter ONE_ROW_TIME = 12000;
parameter ROW_STT_PROCESS_TIME = 7000;
parameter ONE_COLUMN_PROCESS_TIME = 50;
parameter ONE_ROW_TIME_POW = 14; // 15 - 65536 tacts or 5.46 ms, 14 - 32768 tacts or 2.73 ms, 13 - 16384 tacts or 1.36 ms,
// 12 - 8191 tacts or 683 mks, 11 - 4096 tacts or 341 mks, 10 - 2048 tacts or 171 mks, 9 - 1024 tacts or 85 mks, 8 - 512 tacts or 43 mks,
// 7 - 256 tacts or 21 mks, other values have no guaranties
parameter ONE_CALC_TIME_POW = 4; // 3 - 16 tacts or 1.3 mks, 4 - 32 tacts or 2.7 mks, 5 - 64 tacts or 5.3 mks, 6 - 128 tacts or 10.7 mks
// ONE_ROW_TIME_POW > (ONE_CALC_TIME_POW - 3); ONE_CALC_TIME_POW > 2 (if 2 or smaller, top module overrun may occur)
parameter CHATTERING_SUPRESSION_TIME = 100;
reg [ONE_ROW_TIME_POW:0] row_time = 0;
reg [3:0] row_counter;
//reg [7:0] temp;
//reg [7:0] i;
//reg [7:0] report [6:0]; // NO BYTE 2
//reg [7:0] report_byte;
reg isr;
reg isr_internal;
reg [15:0] ROWS_EN = 0;
reg [15:0] ROWS_OUT = 0;
wire [15:0] ROWS_IN;
reg [7:0] COLUMN_SHADOW;
// reg [7:0] kbd_code;
wire [6:0] kbd_code;
assign kbd_code [2:0] = row_time[10:8]; // COLUMN NUM
assign kbd_code [6:3] = row_counter; // ROW NUM
wire [7:0] kbd_code_hid;
reg is_pressed;
reg last_wr;
reg [8:0] last_adr;
wire [7:0] last_column;
//reg [3:0] init_delay_cnt;
//reg [8:0] init_ram_cnt;
reg IS_RAM_INIT = 0;
/*always @ (negedge CLK) begin
COLUMN_SHADOW <= COLUMNS;
end*/
wire [7:0] report_data_rd;
reg [3:0] report_adress_rd;
reg [7:0] report_data_wr;
wire [3:0] report_adress_wr;
assign report_adress_wr = report_adress_rd;
assign REPORT_DATA = report_data_rd;
reg report_wr_en;
ram REPORT (CLK, report_wr_en, report_adress_wr, report_data_wr, report_adress_rd, report_data_rd);
ram RAM (CLK, last_wr, last_adr, COLUMN_SHADOW, last_adr, last_column);//module ram(input clk, wen, input [8:0] addr, input [7:0] wdata, output [7:0] rdata);
reg tmr_wr_en;
reg [7:0] tmr_to_ram;
wire [7:0] tmr_from_ram;
//reg [7:0] tmr_adr;
wire [6:0] tmr_adr;
//assign tmr_adr[6:3] = kbd_code;
assign tmr_adr [6:3] = row_counter;
//assign tmr_adr [2:0] = 0;
assign tmr_adr [2:0] = row_time[10:8]; //row_time[3:1];
ram CHATTERING_SUPRESSION_TIMERS (CLK, tmr_wr_en, tmr_adr, tmr_to_ram, tmr_adr, tmr_from_ram);
reg is_ghost;
always @ (negedge CLK) begin
if (RESET == 0) begin
isr = 0;
isr_internal = 0;
row_time = 0;
row_counter = 0;
IS_RAM_INIT = 1;
last_adr = 500;
report_adress_rd = 5;
report_wr_en = 0;
COLUMN_SHADOW = 255;
end
else begin
if (FREEZE == 0) begin
if (IS_RAM_INIT) begin
last_wr = 1;
tmr_wr_en = 1;
last_adr = last_adr + 1;
COLUMN_SHADOW = 255;
tmr_to_ram = 0;
row_counter = last_adr[6:3];
row_time[10:8] = last_adr[2:0];
report_adress_rd = report_adress_rd + 1;
if (report_adress_rd == 0)
report_data_wr = 10;
else
report_data_wr = 0;//report_adress_rd & 1;
report_wr_en = 1;
if (last_adr == 130) begin
tmr_wr_en = 0;
last_wr = 0;
IS_RAM_INIT = 0;
report_wr_en = 0;
end
end
else begin
if (row_time == ONE_ROW_TIME) begin
row_time = 0;
row_counter = row_counter + 1;
COLUMN_SHADOW <= COLUMNS; // LATCH STATE OF THE COLUMNS IN CURRENT ROW
//last_adr = 0;
end
else begin
if (row_time == 0) begin//== ONE_ROW_TIME) begin
last_wr = 0;
ROWS_EN = 1 << ((row_counter+1) & 15);
last_adr = row_counter;
end
row_time = row_time + 1;
end
if ((row_time[ONE_ROW_TIME_POW:11] == 0) && (row_time[7:0] < 140)) begin
// if (COLUMN_SHADOW [row_time [10:8]] == 0) begin // START OF KEY PRESS PROCESSING
// if (row_time [7:0] == 0) // AT START OF EACH COLUMN PROCESS
// is_ghost = 0;
// end
// else begin
if (COLUMN_SHADOW [row_time [10:8]] == 0) begin
if (row_time [7] == 0) begin
is_ghost = 0;
end
else if (row_time [6:0] == 0)
last_adr = row_counter;
else if ((row_time [6:0] == 1) && (is_ghost == 0)) begin
// if (last_column[row_time[10:8]] == 1) begin
// is_pressed = 1;
// report_adress_rd = 2; // ADRESS TO MODIFIERS
// isr_internal = 1; // INTERNAL ISR AT NEXT TACT
// end
if (tmr_from_ram < CHATTERING_SUPRESSION_TIME)
tmr_to_ram = tmr_from_ram + 1;
else if (tmr_from_ram == CHATTERING_SUPRESSION_TIME) begin
isr_internal = 1;
is_pressed = 1;
report_adress_rd = 2;
tmr_to_ram = tmr_from_ram;
end
else
tmr_to_ram = tmr_from_ram;
end
end
else begin
last_adr = row_counter;
tmr_to_ram = 0;
if (row_time [7:0] == 1) begin
if (last_column[row_time[10:8]] == 0) begin
isr_internal = 1;
is_pressed = 0;
report_adress_rd = 2;
end
end
end
// last_adr = row_counter;
// if (row_time[7:0] == 128) begin
// if (COLUMN_SHADOW[row_time[10:8]] != last_column[row_time[10:8]]) begin
// if ((COLUMN_SHADOW[row_time[10:8]] == 0) && (last_column[row_time[10:8]] == 1)) is_pressed = 1;
// else is_pressed = 0;
// isr_internal = 1; // INTERNAL ISR AT NEXT TACT
// report_adress_rd = 2; // ADRESS TO MODIFIERS
// end
// end
// if (row_time[7:0] == 130)
// tmr_wr_en = 1;
// else if (row_time[7:0] == 132)
// tmr_wr_en = 0;
//
// if (row_time[10:8] == 7) begin
// if (row_time[7:0] == 130)
// last_wr = 1;
// else if (row_time[7:0] == 132)
// last_wr = 0;
// end
end
else if ((row_time[ONE_ROW_TIME_POW:11] == 0) && (row_time[7:0] == 250)) begin
tmr_wr_en = 1;
if (row_time[10:8] == 7)
last_wr = 1;
end
else if ((row_time[ONE_ROW_TIME_POW:11] == 0) && (row_time[7:0] == 252)) begin
tmr_wr_en = 0;
last_wr = 0;
end
// if ((row_time[ONE_ROW_TIME_POW:8] == 1/*((1<<(ONE_ROW_TIME_POW-7))-1)*/) && (row_time[4:0] == 0)) begin
// //if (row_time[7:5] == 0) begin
// // temp = last_column;
// //end
// check_column (row_time[7:5]);
// if (row_time[7:5] == 7)
// last_wr = 1;
// end
// START PACK I2C_HID REPORT
else if ((isr_internal == 1)/* && (row_time[4:0] > 1)*/) begin
if (report_wr_en == 1) begin
report_wr_en = 0;
isr_internal = 0;
isr = 1;
if (is_pressed)
tmr_to_ram = tmr_to_ram + 1;
end
else if (kbd_code_hid == 0) // IF KEY NOT EXIST, DO NOTHING
isr_internal = 0;
else if (kbd_code_hid[7:3] == 5'b11100) begin // BYTE WITH MODIFIERS IS READ AT START OF ALG
if (is_pressed)
report_data_wr = report_data_rd | (1<<(kbd_code_hid & 8'h07));
else
report_data_wr = report_data_rd & (~(1<<(kbd_code_hid & 8'h07)));
if (report_data_wr == report_data_rd) begin
isr_internal = 0;
if (is_pressed)
tmr_to_ram = tmr_to_ram + 1;
end
else
report_wr_en = 1;
end
else if (report_adress_rd == 2) // IF BUTTON IS NOT MODIFIER, SET ADRESS TO FIRST BUTTON BYTE
report_adress_rd = 4;
else if (report_adress_rd == 10) // IF TOO MUTCH ADRESSES SEEK, END ALG (BUTTONS ARE IN ADRESSES 4-9)
isr_internal = 0;
else begin
if (is_pressed) begin
if (report_data_rd == kbd_code_hid) begin // IF BUTTON WITH SAME CODE IS IN REPORT
isr_internal = 0; // CLEAR INTERNAL INTERRUPT, NO EXT INTERRUPT
tmr_to_ram = tmr_to_ram + 1;
end
else if (report_data_rd == 0) begin // IF FREE ADRESS FOUND
report_data_wr = kbd_code_hid; // WRITE CODE TO THIS ADRESS
report_wr_en = 1;
end
else
report_adress_rd = report_adress_rd + 1; // IF NO FREE PLACE, CONTINUE SEEK
end
else begin // BUTTON RELEASED
if (report_data_rd == kbd_code_hid) begin // IF ADRESS WITH THIS CODE FOUND
report_data_wr = 0; // WRITE 0 TO THIS ADRESS (BTN RELEASED)
report_wr_en = 1;
end
else
report_adress_rd = report_adress_rd + 1; // IF THIS CODE NOT FOUND, CONTINUE SEEK
end
end
end
else begin// if (isr_internal == 0) begin
report_adress_rd = REPORT_ADRESS /*- 1*/; // IF REPORT FILLING PROCESS IS ENDED, SET ADRESS FROM TOP MODULE
isr <= 0;
end
end
end
end
end
task check_column;
input [2:0] column;
begin
if (COLUMN_SHADOW[column] != last_column[column]) begin
//kbd_code = row_counter*8 + column;
if ((COLUMN_SHADOW[column] == 0) && (last_column[column] == 1)) is_pressed = 1;
else is_pressed = 0;
isr_internal = 1; // INTERNAL ISR AT NEXT TACT
report_adress_rd = 2; // ADRESS TO MODIFIERS
end
//else kbd_code = 255;
//temp[column] = COLUMN_SHADOW[column];
end
endtask
assign INT = isr;
SB_RAM40_4K #(
.INIT_0(256'h0062_005D_0049_0045_0060_005A_0054_004F__0052_0000_004A_004D_0057_0058_0048_0050), // ROW 0-1
.INIT_1(256'h0063_005E_004B_004E_0061_005B_0055_0056__0000_005C_004C_0044_005F_0059_0053_0051), // ROW 2-3
.INIT_2(256'h0029_002B_0035_001E_0014_0004_001D_0000__00E2_0000_0000_0046_0047_0000_0000_00E6), // ROW 4-5
.INIT_3(256'h0000_00E1_0000_0000_0000_00E1_00E5_0000__0000_0000_00E0_0000_0000_0000_00E4_0000), // ROW 6-7
.INIT_4(256'h003E_002A_0042_0043_0000_0031_0028_002C__0034_002F_002D_0027_0013_0033_0000_0038), // ROW 8-9
.INIT_5(256'h0000_0040_0041_0026_0012_000F_0037_0000__003F_0030_002E_0025_000C_000E_0036_0000), // ROW 10-11
.INIT_6(256'h0000_0039_003A_001F_001A_0016_001B_0000__000B_001C_0023_0024_0018_000D_0010_0011), // ROW 12-13
.INIT_7(256'h000A_0017_0022_0021_0015_0009_0019_0005__003D_003C_003B_0020_0008_0007_0006_0000), // ROW 14-15
//.INIT_8(256'h0000_0000_0000_0000_002C_002A_0019_003B__0000_0000_0000_0000_00E2_0015_0006_003A), // ROW 16-17
//.INIT_9(256'h0000_0000_0000_0000_002C_002A_0019_003B__0000_0000_0000_0000_00E2_0015_0006_003A), // ROW 18-19
.WRITE_MODE(1),
.READ_MODE(1)
) kbd_codes (
.RDATA(kbd_code_hid),
.RADDR(kbd_code),
.RCLK(CLK),
.RCLKE(1'b1),
.RE(1'b1),
.WADDR(8'b0),
.WCLK(1'b0),
.WCLKE(1'b0),
.WDATA(8'b0),
.WE(1'b0)
);
SB_IO #(
.PIN_TYPE(6'b 1010_01),
.PULLUP(1'b 0)
) rows_io [15:0] (
.PACKAGE_PIN(ROWS),
.OUTPUT_ENABLE(ROWS_EN),
.D_OUT_0(ROWS_OUT),
.D_IN_0(ROWS_IN)
);
endmodule