Skip navigation links COURSES > DIGITAL LOGIC DESIGN (EEL3705.SP07.WEB_COHORT1) > COURSE LIBRARY > EXAMPLE CIRCUITS > VGA VIDEO DISPLAY EXAMPLES > TEXT DISPLAY AND KEYBOARD INPUT EXAMPLES > KEYBOARD INPUT & TEXT OUTPUT EDIT VIEW
End navigation links
Keyboard Input & Text Output
Item Primitive PS/2 keyboard input examples
VGA_char_RAM2_v3.zip (3.31 Mb)
VGA_char_RAM2_v31.zip (2.883 Mb)

This extension of the previous VGA text examples adds an extremely primitive capability of reading raw keypress and key release data from a standard 104-key PC-compatible keyboard connected to the UP2 board's PS/2 port. The present version divides the 40x24 character text display into a series of identical, contiguous 256-character-long text segments, where the ASCII character data for these segments is stored in a 256x7-bit dual-ported RAM. The ps2_reader module reads serial byte data from the PS/2 port and (without doing any error checking) outputs the bytes in parallel form. The top-level entity (VGA_char_RAM2) writes the low 7 bits of these bytes to the next sequential location in the character RAM. One can thus see (most of) the data generated by each key-press and key-release event. I have confirmed that the data generated are (usually) consistent with the expected keyboard scan codes. There are several problems with the present design, however: (1) Only the raw key "make and break" codes are returned, rather than something more easily interpreted, such as the ASCII code for the character typed; (2) since the most-significant bit is truncated in displaying the codes, not quite all of the incoming data is seen; (3) it seems that often the wrong byte codes are returned by the ps2_reader module, possibly due to the total lack of error-checking, and/or the possible presence of subtle timing and synchronization errors. The ps2_reader module is rather kludgey and really needs to be reimplemented in a much more careful and systematic fashion. Finally, it is annoying that the text display only has 256 independently modifiable character positions; ideally it should have 40x24=960 locations for full-screen control of the text. Unfortunately, it seems there are not enough hardware resources on the FLEX10K to implement a 960x7-bit dual-ported RAM.

Version 2 of the project (changes confined to ps2_reader) improves the reliability vastly.

Version 3 of the project (changes in VGA_char_RAM2) uses inverse-video to display the full 8-bit value of each byte (if bit 7 is on, then filled and empty pixels in the glyph are interchanged). Unfortunately, this change meant that the size of the character RAM had to be decreased, from 256 7-bit characters to 128 8-bit characters. There is only enough character RAM now to display about 3 40-character lines of text.

Version 3.1 of the project (changes in the top-level file VGA_char_RAM2) adds a delayed_pulse element to avoid race conditions between the incrementing of the address counter and the writing to RAM.

Item Slightly less primitive PS/2 keyboard input example
Simplified Key Decoder.doc (44.5 Kb)
VGA_char_RAM2_v6.zip (3.429 Mb)
VGA_char_RAM2_v61.zip (3.541 Mb)
VGA_char_RAM2_v6r2.zip (1.079 Mb)

This circuit adds to the previous one a module called key_decoder which is a state machine that attempts to translate the raw incoming byte sequences for the keypress and key-release events into single-byte representations of these events using an ASCII-based encoding. The high-order bit of the output byte is turned on if the key is being released; otherwise it is off indicating a key press. The output ASCII characters were generally chosen to correspond to the key being pressed; e.g. the letters A-Z represent the keys labeled as such, SP represents spacebar, CR the Enter key, etc. For keys with more than one symbol printed on them, the usual upper symbol is chosen; e.g. "!" represents the key that has "! 1" printed on it. For special keys without normal ASCII representations such Shift, Alt, Ctrl, and the various function keys, I have chosen fairly arbitrary ASCII representations for them. These are detailed in the Notes mentioned below.

Unfortunately, the present decoder circuit is not very reliable, and often outputs the wrong character. It needs to be made substantially more reliable before it could reasonably be used as the basis for further keyboard-based applications. Also, be aware that it still operates at the level of keypress/key-release events, not typed characters; e.g., hitting shift+4 on the keyboard in an attempt to generate the "$" character will instead generate a sequence of 4 bytes representing the four events (press shift key)(press $/4 key)(release $/4 key)(release shift key). A further state machine would be needed to translate these event sequences into the character the user actually intends to type.

Version 5.1 improves the reliability somewhat, but there still are frequent problems.

Version 6 solves the reliability problem completely - the key decoder works perfectly now (except that when Num Lock is turned on, some undocumented sequences are sent for the Home, Insert, etc. keys). The problem with the earlier versions was just that the setup time constraint for writing the output to RAM wasn't met. The present version makes sure that its output is valid significantly prior to the rising edge that it uses to signal that the output is ready.

Version 6.1 (archive filename VGA_char_RAM2_v61.zip) adds a falling-edge-triggered "delayed_pulse_fe" element clocking the RAM address counter. This avoids races between the actual write to RAM and the incrementing of the counter.

Version 6.2 (archive filename VGA_char_RAM2_v6r2.zip) vastly simplifies the key decoder design (new entity version key_decoder_v2) and in a way that allows it to handle certain key combinations (e.g. NumLock+Home, Shift+PrntScrn) that were not properly handled previously. As an added benefit, the Pause/Break key now generates a make+break sequence rather than just a make code, so applications don't have to treat it specially. The new design is documented in the "Simplified Key Decoder.doc" Word document. It seems to work perfectly based on testing done to date.

For some additional notes to help you understand how all this works, see the documents in COURSE LIBRARY > SUPPLEMENTAL NOTES > USING THE PS/2 PORT FOR KEYBOARD OR MOUSE INPUT.
Item Display pressed/released state of all keys
VGA_char_RAM3_v1.zip (1.1 Mb)
VGA_char_RAM3_v4.zip (7.174 Mb)
VGA_char_RAM3_v5.zip (9.142 Mb)
This greatly cleaned-up and simplified version of VGA_char_RAM uses a rather different output modality from the earlier versions. Rather than displaying a trail of the last 128 make/break events that occurred, instead it fills the screen with one huge ASCII table, and brightens the character at each location while the corresponding keyboard key (according to my key-to-ASCII mapping) is being held down. To accomplish this, it must receive make/break events from the key_decoder, and keep track (in a RAM) of whether each key most recently underwent a "make" or a "break" event. Fortunately, this only requires a 128-bit RAM, so it uses 1/8th the RAM of VGA_char_RAM2. This leaves more space on the chip for additional design elements. This design could be a good starting point for a video game in which the holding-down of various keyboard keys is supposed to continuously cause some action, e.g., motion of the player's token on the screen.

Version 4 fixes several bugs and renders the currently-pressed keys using inverse video rather than brightening. (The stipple pattern in the earlier versions didn't come out looking very good.) The example still contains some subtle timing problems and does not look perfect, but it basically works. Also, the RAM is apparently not initialized properly. Still, it is a reasonable starting point.

Version 5 improves the display quality somewhat, and enables the user to clear the contents of RAM (resetting the state of all the keys) using the FLEX_PB1 pushbutton. There are still a few glitches. But it is worth playing around with.

Item Permit text input from keyboard
text_entry_v2.zip (6.257 Mb)
text_entry.zip (3.992 Mb)

This (incomplete, but working) example is intended to become a complete text-entry demonstration. So far it just displays my raw ASCII keycodes for the keys pressed. 

Version 2 initializes the character RAM properly upon startup, highlights the current cursor position using inverse video, and uses a modified version of the keycode-to-ASCII map, which permits the expected character to be displayed in more cases - in particular, now working correctly are the unshifted keys that normally generate backquote (`), square brackets ([ ]), backslash (\), semicolon (;), apostrophe ('), comma (,), equals (=), and keypad plus (+).  The function keys also now all generate control characters, although that mapping is highly arbitrary.  But you can now type pretty much any ASCII sequence that you want, excluding most lowercase letters, as well as colon (:), less than (<), quotation marks ("), tilde (~), vertical bar (|), and the EM (end-of-medium), SUB (substitute), and RS (record separator) control characters. 

For more complete coverage of the ASCII character set in the output, later versions are intended to handle the SHIFT and CAPS LOCK keys properly, and to generate arbitrary ASCII control characters by toggling bit 6 of the output character if the control key is depressed.  Also, we will eventually do something sensible in terms of text formatting with keys such as Enter, Tab, Backspace, Insert, Delete, Home, End, Page Up, Page Down, Keypad Enter, and the arrow keys.

OK