You have no items in your shopping cart.

Subtotal: 0.00

Abstract

The main objective of the KBL project is to provide it’s users an easy and straight-forward way to learn, practice and improve the use of the keyboard in typewriting. The proposed solution for reaching this objective is a clean application, with no unnecessary artwork and with a few options for customizing the user-experience. The Spartan3 FPGA Image Processing Kit  based Keyboard  learner system generates and displays random character codes, with a very small possibility of the code being an actual word. This forces the user to keep his eyes on the screen, and not at the keyboard. If the system would use intelligible words, the user would just read them and switch his eyes to the keyboard to type them. The effect of using this system is that users will start typing faster, and with fewer spelling errors, eventually without even looking to the keys.

Demonstration Video

 

Tool required

Software:

  • Xilinx ISE 11.1i

Language:

  • VHDL

Hardware:

Block Diagram for FPGA Implementation of Keyboard Learner using Spartan3 FPGA Image Processing Kit


Block_Dgm_Keyboard_Learner



ARC_Dgm_Keyboard_Learner

Introduction:

The Keyboard Learner gets its user inputs from the PS/2 keyboard. Each input characters must be compared with a generated character, and the score modified accordingly, and displayed. From this single sentence, some of the main components of the design can be easily identified: a random character generator, a keyboard input reader, a comparator, a score updater and a display unit. Also, code sequences must be memorized and the custom settings for the timer and the length of the sequence must be handled. Most of the components are based on registers and counters and use comparators, multiplexers and demultiplexers. Figure 3.1 shows the top level block diagram, with all the components used in the design and the links between them.

Functional Description

This section describes the flow of events that can take place while using the KBL system.

The Menu Screen

The system starts in the Menu Screen – the state signal is set to logical ‘0’. This screen displays on two different lines the labels for the timer (T) and level (L) settings together with their default values. The third line contains the GO label, used to start the application. The first line, corresponding to the timer setting is highlighted (yellow). The system waits for user input.

The user can change the timer value, or switch the selected item to the next line, from where he/she can change the level value, or step to the third line and start the application. A minimum of 3 keys must be pressed in order to get to the Application Screen. These 3 keystrokes are used in the background to generate the first random character sequence and store it, each character in its corresponding register. Therefore, the default level value must be less than or equal to 3, so that all the characters are generated.

The units used during the Menu Screen are: KB_UNIT, MENU, VGA_CTRL, COLORIZER and NUM_CNTR, and, unnoticeably for the user, the RANDOMIZER, CRST and REG_PIPE.

The Application Screen

When in Application Screen, the screen contains the generated character code in the centre and the user score in the upper right corner. Initially the score is null (000). The system waits for the user to type the code displayed.

As each character is typed in, it is compared to the one in the code. If they match, the score is incremented. If not, the score is decremented (if it is still positive). The colours of the typed characters changes with regard to the past comparison results. A green character signifies a correct match, while a red one means that character was mistyped.

If the user has set a non-null timer value, then the ready-for-display registers are cleared after the specified amount of time and the code disappears from screen, the application becoming a memory test.

All the units are functional when the system is in Application Screen.:

⇛The KB_UNIT reads the user input;

⇛The NUM_CNTR iterates the character sequence;

⇛The RANDOMIZER generates a new character code at each key stroke;

⇛The REG_PIPE stores the codes, moves them into the pipe and outputs them to the COUNTER or the COLORIZER;

⇛The COUNTER compares the generated and the read character code and computes the score and sends it to the COLORIZER;

⇛The COLORIZER computes the colour channels value for each character

⇛The VGA_CTRL selects the current character, character line and pixel, and generates the synchronization signals;

⇛The HIDER clears generated code from the screen if the time limit has been reached;

⇛The MENU identifies the ESC (escape) keystroke, and sends the system back in Menu Screen.

Keyboard Learner output image

Keyboard Learner output image

 

Keyboard Learner output image

Keyboard Learner output image

 

Source Code

VHDL Code for Keyboard Learner using Spartan6 FPGA Project Kit

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

-- The KBL top module
entity learner is
	 Port (  mclk 	: in std_logic;		-- master clock
		kd, kc 	: in std_logic;		-- keyboard input: keyboard data, keyboard clock
		rst	: in std_logic;		-- master reset
		hs	: out std_logic;	-- horizontal synchronization output
		vs	: out std_logic;	-- verical synchronization output
		red, grn, blu : out std_logic	-- colour channels output
	 );
end learner;

architecture Behavioral of learner is

component randomizer is											-- generates the character sequence
    Port ( clk : in  STD_LOGIC;				-- master clock
           	rst : in  STD_LOGIC;				-- asyncronous reset
           oe : in  STD_LOGIC;				-- asyncronous output enable
           ascig : out  STD_LOGIC_VECTOR (5 downto 0));	-- generated character code
end component;

component kb_unit is												-- component that reads the user input
    Port ( clk : in  STD_LOGIC;				-- master clock
           rst : in  STD_LOGIC;				-- master reset
           kc : in  STD_LOGIC;				-- keyboard clock
           kd : in  STD_LOGIC;				-- keyboard data
           kbexec : in  STD_LOGIC;			-- keyboard execution enable
           scancode : out  STD_LOGIC_VECTOR (7 downto 0);-- scan code of the pressed key
           ascii : out  STD_LOGIC_VECTOR (5 downto 0);	-- character code corresponding to the scan code
           numclk : out  STD_LOGIC);		-- number clock - a positive impulse at each keystroke
end component kb_unit;

component num_cntr is											-- counts the keystrokes => current index in the sequence
    Port ( numclk : in  STD_LOGIC;			-- number clock
           crst : in  STD_LOGIC;				-- counter reset
           level : in  STD_LOGIC_VECTOR (2 downto 0);	-- length of character sequence
           num : out  STD_LOGIC_VECTOR (2 downto 0));-- current index in the sequence
end component num_cntr;

component vgactrl is												-- goes through the screen pixels and enables display
    Port ( clk : in std_logic;				-- master clock input
	kbexec : out std_logic;			-- keyboard execution enable
           hs : out std_logic;				-- horizontal synchronization signal
           vs : out std_logic;				-- vertical synchronization signal
           text : out std_logic; 				-- text display enable
           pixel : out std_logic_vector(2 downto 0);	-- pixel selector
           line : out std_logic_vector(2 downto 0);	-- line selector
 col : out std_logic_vector(6 downto 0);	-- current column
 row : out std_logic_vector(5 downto 0));	-- current row
end component;

component counter is												-- counts the user points
    Port ( ascig : in std_logic_vector(5 downto 0);	-- generated character code to be compared
ascik : in std_logic_vector(5 downto 0);	-- read from keyboard character code to be compared
	clk, rst, ce : in std_logic;			-- clock (numclk), master reset and chip enable
           ascip : out std_logic_vector(17 downto 0);	-- character codes for the 3 digits of the score
			  ok : out std_logic);		-- comparison result
end component;

component reg_pipe is											-- stores and transmits character codes
    Port ( ascig : in  STD_LOGIC_VECTOR (5 downto 0);	-- generated character code
           ascii : in  STD_LOGIC_VECTOR (5 downto 0);		-- typed character code
			  rst : in STD_LOGIC;			-- master reset
			  crst : in std_logic;			-- counter reset
           num : in  STD_LOGIC_VECTOR(2 downto 0);		-- current index in the sequence
           numclk : in  STD_LOGIC;				-- number clock
           level : in  STD_LOGIC_VECTOR(2 downto 0);		-- length of character sequence
           hide : in  STD_LOGIC;					-- hide command
ok : in std_logic;					-- comparison result
           cascig : out  STD_LOGIC_VECTOR (5 downto 0);	-- comparison register output
           rascig : out  STD_LOGIC_VECTOR (23 downto 0);	-- ready-for-display registers output
           kasci : out  STD_LOGIC_VECTOR (23 downto 0);	-- keyboard registers output
	status : out std_logic_vector(3 downto 0));		-- comparisons history status register output
end component reg_pipe;

component hider is												-- clears the generated sequence from the screen
    Port ( mclk : in  STD_LOGIC;			-- master clock
           crst : in  STD_LOGIC;				-- counter reset
           state : in  STD_LOGIC;				-- current state(screen)
           num : in  STD_LOGIC_VECTOR (2 downto 0);	-- current index in the sequence
           level : in  STD_LOGIC_VECTOR (2 downto 0);	-- length of the character sequence
	timer : in STD_LOGIC_VECTOR (1 downto 0);	-- timer value
           hide : out  STD_LOGIC);				-- hide command
end component hider;

component menu is													-- handles the user settings menu screen
    Port ( clk : in  STD_LOGIC;					-- clock (number clock)
			  rst : in STD_LOGIC;									-- reset
           scancode : in  STD_LOGIC_VECTOR (7 downto 0);	-- scan code of the pressed key
           level : out  STD_LOGIC_VECTOR (2 downto 0);	-- length of the character sequence
           timer : out  STD_LOGIC_VECTOR (1 downto 0);	-- timer value
           state : out  STD_LOGIC;					-- current state (screen)
           start : out  STD_LOGIC;					-- start application signal
	selmenu : out std_logic_vector(1 downto 0));	-- selected menu item
end component;

component colorizer is											-- computes the output and the color channels for each character
	Port ( num : in std_logic_vector(2 downto 0);		-- current index in the sequence
			 row : in std_logic_vector(5 downto 0);	-- current row
			 col : in std_logic_vector(6 downto 0);	-- current column
			 status : in std_logic_vector(3 downto 0);	-- comparisons history status 
			 text : in std_logic;				-- text display enable
			 pixel : in std_logic_vector(2 downto 0);	-- selected pixel
			 line : in std_logic_vector(2 downto 0);	-- selected line
			 state : in std_logic;				-- current state (screen)
			 selmenu : in std_logic_vector(1 downto 0);	-- selected menu item
			 level : in  STD_LOGIC_VECTOR (2 downto 0);-- length of the character sequence
          timer : in  STD_LOGIC_VECTOR (1 downto 0);		-- timer value
			 
			 rascig : in std_logic_vector(23 downto 0);	-- ready-for-display character codes
			 kasci : in std_logic_vector(23 downto 0);	-- keyboard-read character codes
			 ascip : in std_logic_vector(17 downto 0);	-- user score character codes
			 
			 red, grn, blu : out std_logic);			-- colour channels
end component;

signal col : std_logic_vector(6 downto 0) := "0000000";	-- current column
signal row : std_logic_vector(5 downto 0) := "000000";	-- current row

signal ascii : std_logic_vector(5 downto 0) := "000000";	-- user input character code
signal ascig : std_logic_vector(5 downto 0) := "000000";	-- generated character code

signal cascig : std_logic_vector(5 downto 0) := "000000";-- generated character code selected for comparison

signal rascig : std_logic_vector(23 downto 0);			-- ready-for-display character codes
signal kasci : std_logic_vector(23 downto 0);				-- keyboard-read character codes
signal ascip : std_logic_vector(17 downto 0) := "011011011011011011";	-- user score character codes

signal scancode : std_logic_vector(7 downto 0) := "00000000";	-- scan code of the pressed key
signal kbexec : std_logic := '0';					-- keyboard execution enable
--signal sseg : std_logic_vector(6 downto 0) := "0000000";	-- for debug

signal text : std_logic := '0';						-- text display enable
signal line : std_logic_vector(2 downto 0) := "000";		-- selected character line
signal pixel : std_logic_vector(2 downto 0) := "000";		-- selected pixel in line

signal numclk : std_logic := '0';				-- number clock
signal num : std_logic_vector(2 downto 0) := "000";		-- current index in the sequence (number of keystrokes)

signal level : std_logic_vector(2 downto 0) := "100";		-- length of character sequence
signal timer : std_logic_vector(1 downto 0) := "00";		-- timer value
signal hide : std_logic := '0';					-- hide command
signal selmenu : std_logic_vector(1 downto 0) := "00";	-- selected menu item

signal state : std_logic := '0';					-- current state (screen)
signal crst : std_logic := '0';					-- counter reset
signal start : std_logic := '0';					-- start application signal

signal ok  : std_logic := '0';					-- comparison result
signal status : std_logic_vector(3 downto 0) := "0000";	-- comparisons history

begin
	-- component instantiation
	random0 : randomizer port map(
		clk => mclk,
		rst => rst,
		oe => numclk,					-- output enable on keystroke
		ascig => ascig);
		
	reg_pipe0 : reg_pipe port map(
		ascig => ascig,
		ascii => ascii,
		rst => rst,
		crst => crst,
		num => num,
		numclk => numclk,
		level => level,
		hide => hide,
		ok => ok,
		cascig => cascig,
		rascig => rascig,
		kasci => kasci,
		status => status);
		
	kbunit0 : kb_unit port map(
		clk => mclk,
      rst => rst,
		kc => kc,
		kd => kd,
		kbexec => kbexec,
		scancode => scancode,
		ascii => ascii,
		numclk => numclk);
		
	num_cntr0 : num_cntr port map(
		numclk => numclk,
      crst => crst,
      level => level,
      num => num);

	pcount0: counter port map(
		ascig => cascig,
		ascik => ascii,
		clk => numclk,				-- compares inputs and modifies at each keystroke
		rst => crst,
		ce => state,
		ascip => ascip,
		ok => ok);

	vgactrl0: vgactrl port map(
		clk => mclk,
		kbexec => kbexec,
		hs => hs,
		vs => vs,
		text => text,
		pixel => pixel,
		line  => line,
		col => col,
		row => row);

	menu0 : menu port map(
		clk => numclk,
		rst => rst,
		scancode => scancode,-- sensitive to menu operations keystrokes: SPACE, ENTER, ESC
		level => level,
		timer => timer,
		state => state,
		start => start,
		selmenu => selmenu);
	
	hider0 : hider port map(
		mclk => mclk,
		crst => crst,
		state => state,
		num => num,
		level => level,
		timer => timer,
		hide => hide);
		
	color0: colorizer port map(
		num => num,
		row => row,
		col => col,
		status => status,
		text => text, 
		pixel => pixel,
		line => line,
		state => state,
		selmenu => selmenu,
		level => level,
		timer => timer,
		
		rascig => rascig,
		kasci => kasci,
		ascip => ascip,
		
		red => red, 
		grn => grn, 
		blu => blu);
		
	-- counters reset
	crst <= rst or start;				-- reset on global reset or when state changes from menu screen to application screen

end Behavioral;

Conclusion

Typewriting skills are an important asset for anyone in the modern society. There are many tools and systems (hardware and software) for learning, developing and improving this ability. The Keyboard Learner is one of them. It achieves its goal of being a self-educational tool by its simplicity and ease of use at a low cost.

The additional option of using a limited display time period makes out of KBL not only an educational tool, but also a memory game, fun for children in growing phase, when developing attention and memory capability is very important.

The project uses a hierarchical and modular design implemented in Spartan3 FPGA Image Processing Kit, which has the advantage of being easy to follow and understand. It is event oriented, so it can be easily translated into natural language. The reusability of independent units is not one of the project’s strong points. This is caused by the high dependency between components and can be seen as a drawback. On the other hand, the components are designed to be dedicated to the specific role that they have within the Keyboard Learner.