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 [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 = 8000; 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) 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] COLS_SHADOW; //reg [7:0] kbd_code; wire [6:0] kbd_code; assign kbd_code [2:0] = row_time[7:5]; // COLUMN NUM assign kbd_code [6:3] = row_counter; // ROW NUM wire [7:0] kbd_code_hid; reg is_pressed; reg ram_wr; reg [8:0] ram_adr; wire [7:0] ram_rd; //reg [3:0] init_delay_cnt; //reg [8:0] init_ram_cnt; reg IS_RAM_INIT = 0; /*always @ (negedge CLK) begin COLS_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, ram_wr, ram_adr, temp, ram_adr, ram_rd);//module ram(input clk, wen, input [8:0] addr, input [7:0] wdata, output [7:0] rdata); always @ (negedge CLK) begin if (RESET == 0) begin //for (i = 0; i < 6; i = i + 1) // report[i] = 0; isr = 0; isr_internal = 0; //init_delay_cnt = 0; //init_ram_cnt = 0; row_time = 0; IS_RAM_INIT = 1; ram_adr = 500; report_adress_rd = 5; report_wr_en = 0; //report_byte = 0; end else begin if (FREEZE == 0) begin /*if (REPORT_ADRESS == 0) report_byte <= 10; else if ((REPORT_ADRESS == 1) || (REPORT_ADRESS == 3)) report_byte <= 0; else if (REPORT_ADRESS == 2) report_byte <= report[0]; else report_byte <= report[REPORT_ADRESS-3];*/ /*if (init_delay_cnt != 15) init_delay_cnt = init_delay_cnt + 1; else if (init_ram_cnt < 256) begin ram_wr = 1; ram_adr = init_ram_cnt; temp = 255; init_ram_cnt = init_ram_cnt + 1; end*/ if (IS_RAM_INIT) begin ram_wr = 1; ram_adr = ram_adr + 1; temp = 255; 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 (ram_adr == 130) begin //ram_wr = 0; IS_RAM_INIT = 0; report_wr_en = 0; end end /*else if (init_ram_cnt == 256) begin ram_wr = 0; init_ram_cnt = init_ram_cnt + 1; end*/ else begin row_time = row_time + 1; if (row_time == 0) begin//== ONE_ROW_TIME) begin ram_wr = 0; //row_time <= 0; row_counter = row_counter + 1; ROWS_EN = 1 << row_counter; ram_adr = row_counter; end // ROW 0 - D, 1 - A, 2 - C, 3 - B /*if (row_time == (ROW_STT_PROCESS_TIME - 1)) begin temp = ram_rd; COLS_SHADOW <= COLUMNS; end*/ //if (row_time == 8191/*(ROW_STT_PROCESS_TIME + ONE_COLUMN_PROCESS_TIME * 7 + 1)*/) // ram_wr = 1; //if ((row_time[12:8] == 31) && (row_time[4:0] == 0)) begin if ((row_time[ONE_ROW_TIME_POW:8] == ((1<<(ONE_ROW_TIME_POW-7))-1)) && (row_time[4:0] == 0)) begin //temp = ram_rd; //COLS_SHADOW = COLUMNS; if (row_time[7:5] == 0) begin temp = ram_rd; COLS_SHADOW = COLUMNS; end check_column (row_time[7:5]); if (row_time[7:5] == 7) ram_wr = 1; end //else // kbd_code = 255; /*if (row_time == (ROW_STT_PROCESS_TIME + ONE_COLUMN_PROCESS_TIME * 0)) check_column (0); else if (row_time == (ROW_STT_PROCESS_TIME + ONE_COLUMN_PROCESS_TIME * 2)) check_column (2); else if (row_time == (ROW_STT_PROCESS_TIME + ONE_COLUMN_PROCESS_TIME * 1)) check_column (1); else if (row_time == (ROW_STT_PROCESS_TIME + ONE_COLUMN_PROCESS_TIME * 3)) check_column (3); else if (row_time == (ROW_STT_PROCESS_TIME + ONE_COLUMN_PROCESS_TIME * 4)) check_column (4); else if (row_time == (ROW_STT_PROCESS_TIME + ONE_COLUMN_PROCESS_TIME * 5)) check_column (5); else if (row_time == (ROW_STT_PROCESS_TIME + ONE_COLUMN_PROCESS_TIME * 6)) check_column (6); else if (row_time == (ROW_STT_PROCESS_TIME + ONE_COLUMN_PROCESS_TIME * 7)) check_column (7); else kbd_code = 255;*/ // 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; 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))); report_wr_en = 1; end //else // isr_internal = 0; 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) // IF BUTTON WITH SAME CODE IS IN REPORT isr_internal = 0; // CLEAR INTERNAL INTERRUPT, NO EXT INTERRUPT 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 /*if (kbd_code_hid != 0) begin if (kbd_code_hid[7:3] == 5'b11100) begin //if ((kbd_code_hid > 8'hDF) && (kbd_code_hid < 8'hE8)) begin if (is_pressed) report [0] = report [0] | (1<<(kbd_code_hid & 8'h07)); else report [0] <= report [0] & (~(1<<(kbd_code_hid & 8'h07))); isr = 1; end else begin if (is_pressed) begin isr = 1; if (report [ 1 ] == 0) report [ 1 ] <= kbd_code_hid; else if (report [ 2 ] == 0) report [ 2 ] <= kbd_code_hid; else if (report [ 3 ] == 0) report [ 3 ] <= kbd_code_hid; else if (report [ 4 ] == 0) report [ 4 ] <= kbd_code_hid; else if (report [ 5 ] == 0) report [ 5 ] <= kbd_code_hid; else if (report [ 6 ] == 0) report [ 6 ] <= kbd_code_hid; else isr = 0; end else begin for (i = 1; i < 7; i = i + 1) begin if (report [i] == kbd_code_hid) begin //if (report [i] == kbd_code) begin report [i] = 0; isr = 1; end end end end end // END OF KBD CODE SEND ALG else isr <= 0;*/ end end end end task check_column; input [2:0] column; begin if (COLS_SHADOW[column] != temp[column]) begin //kbd_code = row_counter*8 + column; if ((COLS_SHADOW[column] == 0) && (temp[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] = COLS_SHADOW[column]; end endtask /*assign kbd_r0 = report[0]; assign kbd_r2 = report[1]; assign kbd_r3 = report[2]; assign kbd_r4 = report[3]; assign kbd_r5 = report[4]; assign kbd_r6 = report[5]; assign kbd_r7 = report[6];*/ //assign REPORT_DATA = report_byte; assign INT = isr; SB_RAM40_4K #( .INIT_0(256'h0000_0001_0001_0001_00E7_0058_004C_0053__0001_0001_0001_0001_00E0_0039_00E1_0029), // ROW 0-1 .INIT_1(256'h0001_0001_0001_0001_002C_002A_0019_003B__0001_0001_0001_0001_00E2_0015_0006_003A), // ROW 2-3 .INIT_2(256'h0001_0001_0001_0001_002C_002A_0019_003B__0001_0001_0001_0001_00E2_0015_0006_003A), // ROW 4-5 .INIT_3(256'h0001_0001_0001_0001_002C_002A_0019_003B__0001_0001_0001_0001_00E2_0015_0006_003A), // ROW 6-7 .INIT_4(256'h0001_0001_0001_0001_002C_002A_0019_003B__0001_0001_0001_0001_00E2_0015_0006_003A), // ROW 8-9 .INIT_5(256'h0001_0001_0001_0001_002C_002A_0019_003B__0001_0001_0001_0001_00E2_0015_0006_003A), // ROW 10-11 .INIT_6(256'h0001_0001_0001_0001_002C_002A_0019_003B__0001_0001_0001_0001_00E2_0015_0006_003A), // ROW 12-13 .INIT_7(256'h0001_0001_0001_0001_002C_002A_0019_003B__0001_0001_0001_0001_00E2_0015_0006_003A), // ROW 14-15 .INIT_8(256'h0001_0001_0001_0001_002C_002A_0019_003B__0001_0001_0001_0001_00E2_0015_0006_003A), // ROW 16-17 .INIT_9(256'h0001_0001_0001_0001_002C_002A_0019_003B__0001_0001_0001_0001_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