module matrix_kbd (input CLK, input RESET, input FREEZE, inout [3:0] ROWS, input [3:0] COLUMNS, output [63:0] kbd_report, 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; reg [15:0] row_time = 0; reg [1:0] row_counter; reg [15:0] last_data; reg [7:0] i; reg [63:0] report; reg [5:0] report_free_place; reg isr; reg [3:0] ROWS_EN = 0; reg [3:0] ROWS_OUT = 0; wire [3:0] ROWS_IN; reg [3:0] COLS_SHADOW; reg [7:0] kbd_code; reg is_pressed; always @ (negedge CLK) begin COLS_SHADOW <= COLUMNS; end always @ (posedge CLK) begin if (RESET == 0) begin last_data <= 16'hFFFF; report_free_place <= 6'h3F; report <= 63'h_00_00_00_00_00_00_00_00; end else begin if (FREEZE == 0) begin if (row_time == ONE_ROW_TIME) begin row_time <= 0; row_counter = row_counter + 1; ROWS_EN = 1 << row_counter; end else row_time <= row_time + 1; // ROW 0 - D, 1 - A, 2 - C, 3 - B if (row_time == (ONE_ROW_TIME/2 + 0)) begin if (COLS_SHADOW[0] != last_data[row_counter*4 + 0]) begin case (row_counter) 0: kbd_code = 8'h29; 1: kbd_code = 8'h53; 2: kbd_code = 8'h3A; 3: kbd_code = 8'h3B; // ESC, F1-F2, NUM LOCK default: kbd_code = 1; endcase if ((COLS_SHADOW[0] == 0) && (last_data[row_counter*4 + 0] == 1)) is_pressed = 1; else is_pressed = 0; end else kbd_code = 0; last_data[row_counter*4 + 0] <= COLS_SHADOW[0]; end else if (row_time == (ONE_ROW_TIME/2 + 4)) begin if (COLS_SHADOW[2] != last_data[row_counter*4 + 2]) begin case (row_counter) 0: kbd_code = 8'h39; 1: kbd_code = 8'h58; 2: kbd_code = 8'h15; 3: kbd_code = 8'h2A; // CAPS LOCK, R, BACKSPACE, ENTER default: kbd_code = 1; endcase if ((COLS_SHADOW[2] == 0) && (last_data[row_counter*4 + 2] == 1)) is_pressed = 1; else is_pressed = 0; end else kbd_code = 0; last_data[row_counter*4 + 2] <= COLS_SHADOW[2]; end else if (row_time == (ONE_ROW_TIME/2 + 2)) begin if (COLS_SHADOW[1] != last_data[row_counter*4 + 1]) begin case (row_counter) 0: kbd_code = 8'hE1; 1: kbd_code = 8'h4C; 2: kbd_code = 8'h06; 3: kbd_code = 8'h19; // LEFT SHIFT, C, V, DELETE default: kbd_code = 1; endcase if ((COLS_SHADOW[1] == 0) && (last_data[row_counter*4 + 1] == 1)) is_pressed = 1; else is_pressed = 0; end else kbd_code = 0; last_data[row_counter*4 + 1] <= COLS_SHADOW[1]; end else if (row_time == (ONE_ROW_TIME/2 + 6)) begin if (COLS_SHADOW[3] != last_data[row_counter*4 + 3]) begin case (row_counter) 0: kbd_code = 8'hE0; 1: kbd_code = 8'hE7; 2: kbd_code = 8'hE2; 3: kbd_code = 8'h2C; // LCTRL, LALT, SPACE, RGUI default: kbd_code = 1; endcase if ((COLS_SHADOW[3] == 0) && (last_data[row_counter*4 + 3] == 1)) is_pressed = 1; else is_pressed = 0; end else kbd_code = 0; last_data[row_counter*4 + 3] <= COLS_SHADOW[3]; end else kbd_code = 0; // START PACK I2C_HID REPORT if (kbd_code != 0) begin isr = 1; report[15:8] <= 0; //report[63:56] <= 0; if ((kbd_code > 8'hDF) && (kbd_code < 8'hE8)) begin kbd_code = kbd_code & 8'h07; if (is_pressed) report [7:0] <= report [7:0] | (1<