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