Tuesday, December 24, 2013

Keyboard Interface Design

keyboard-interface-design
This section discusses a keyboard interface for reading scan data from the keyboard and producing ASCII codes of the keys pressed. The interface only handles data transmission from the keyboard. The interface reads serial data from the keyboard, detects the Make code when a key is pressed and looks up the Make code in an ASCII conversion table. For simplicity, the look-up table only handles upper-case characters.

Collecting the Make Code

The first part of the interface connects to the keyboard data and clock lines and when a key is pressed, it outputs an 8-bit scan code. The KBdata, KBclock inputs are for the keyboard data and clock inputs, and the 8-bit ScanCode is the main output of this part. 

This part also uses a fast synchronizing clock, SYNclk, and a keyboard reset input, KBreset. In addition to the ScanCode output, this part outputs a signal to indicate that a scan code is ready (ScanRdy) and another output to indicate that a key has been released (KeyReleased). These outputs make distinction between Make and Break states.


// Keyboard Interface Design
----------------------------------------------------------------------------
module KeyboardInterface (KBclk, KBdata, ResetKB, SYNclk, ScanRdy, ScanCode, KeyReleased);
input KBclk;
input KBdata; 

input ResetKB;    
input ReadKB;
input SYNclk; 
output ScanRdy; 
output [7:0] ScanCode;
output KeyReleased; 

reg Clock;
reg StartBitDetected, ScanRdy;
reg [7:0] ScanCode; 
reg [3:0] BitCount;
reg [1:0] CompletionState;
wire KeyReleased;

// SECTION I: SERIAL DATA COLLECTION 
// Generate an internal synchronized clock
        always@(posedge clock) begin 
        if(ResetKB)
        BitCount = 0; StartBitDetected = 0;          
   end else begin 
      if(KBdata == 0 && StartBitDetected == 0) begin
        StartBitDetected = 1; 
        ScanRdy = 0;          
      end else if(StartBitDetected) begin 
        if(BitCount < 8) begin 
           BitCount = BitCount + 1;  
           ScanCode = {KBdata, ScanCode[7:1]};
               end else begin
           StartBitDetected = 0;
           BitCount = 0;
           ScanRdy = 1;
        end
      end
   end

// SECTION II: BREAK STATE RECOGNITION
always@(posedge SYNclk) begin  
  if(ResetKB) CompletionState = 0;
   
   else case(CompletionState)
               0:if(ScanCode == 8'hF0 && ScanRdy == 1) 
         CompletionState = 1;
        else CompletionState = 0;  
      1:if(ScanRdy == 1) 
         CompletionState = 1;
        else CompletionState = 2;
      2:if(ScanRdy == 0) 
         CompletionState = 2;
        else CompletionState = 3;
      3:CompletionState = 0;
 endcase 
  end 

  assign KeyReleased = CompletionState == 3?1 :0;
 
endmodule  


After the declarations, in this part an internal clock (Clock) that is based on the keyboard clock and is synchronized with the board clock is generated. This clock is used in an always block to collect serial data bits and shift them into ScanCode. Another always block in this code, monitors completion of serial data collection (source code of SECTION I) and generates the state of the keys pressed and released (source code of SECTION II).

The first always statement of SECTION I shows the generation of Clock that is equal to the keyboard clock and synchronized with the external system clock, SYNclk. In the always block that follows this block, after detection of the start-bit, on the rising edge of Clock, bit values are read from the keyboard data line (KBdata) and shifted into ScanCode. The shifting continues for 8 bit counts. On the next clock after collecting 8 data bits is complete, ScanRdy is issued, and the collection process returns to its initial state of looking for the next start-bit.

The partial code of SECTION II uses the 2-bit CompletionState to keep track of the scan codes that have been generated. Starting in the initial state, when ScanRdy becomes 1 and F0 is on ScanCode, CompletionState becomes 1. This state is entered when a key is released and the F0 part of the Break code is transmitted. The next time ScanRdy is detected, the second part of the Break code (that is the same as Make) becomes available on ScanCode. In the following clock, the KeyReleased output becomes 1 and remains at this level for a complete clock period.   



References:
  • Digital Design and Implementation with Field Programmable Devices, Zainalabedin Navabi, Kluwer Academic Plubishers, 2005.
  • www.icom.manufacturer.globalsources.com (source image)
     

No comments:

Post a Comment