Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

PS2 keyboard interface VHDL

Status
Not open for further replies.

Nexys2

Newbie level 5
Newbie level 5
Joined
Mar 27, 2011
Messages
8
Helped
0
Reputation
0
Reaction score
0
Trophy points
1,281
Activity points
1,339
Hi there,

I'm trying to program my Spartan 3E so I can display the PS2 codes on the 4 digit display. When starting, the display shows 0000. When I press 1,2,3,4 the display shows 1234. But I also want the display to show 1111 when I press four times the 1, and I don't know how to solve this. Anyone ideas?

Code:
----------------------------------------------------------------------------------
-- Company: 
-- Engineer: 
-- 
-- Create Date:    13:11:30 05/17/2010 
-- Design Name: 
-- Module Name:    charshift - Behavioral 
-- Project Name: 
-- Target Devices: 
-- Tool versions: 
-- Description: 
--
-- Dependencies: 
--
-- Revision: 
-- Revision 0.01 - File Created
-- Additional Comments: 
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

---- Uncomment the following library declaration if instantiating
---- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;

entity charshift is
    Port ( clk 		: in   STD_LOGIC;
			  inputchar : in   STD_LOGIC_VECTOR (6 downto 0);
           char1 		: out  STD_LOGIC_VECTOR (6 downto 0);
           char2 		: out  STD_LOGIC_VECTOR (6 downto 0);
           char3 		: out  STD_LOGIC_VECTOR (6 downto 0);
           char4 		: out  STD_LOGIC_VECTOR (6 downto 0) );
end charshift;

architecture Behavioral of charshift is
	signal char1sig : STD_LOGIC_VECTOR (6 downto 0 );
	signal char2sig : STD_LOGIC_VECTOR (6 downto 0 );
	signal char3sig : STD_LOGIC_VECTOR (6 downto 0 );
	signal char4sig : STD_LOGIC_VECTOR (6 downto 0 );
begin

	char1 <= char1sig;
	char2 <= char2sig;
	char3 <= char3sig;
	char4 <= char4sig;
	
	process(clk)
	begin
		if ( clk = '1' and clk'event)	then
			if (inputchar /= char1sig) and (inputchar /= "1111111") then   
				char1sig <= inputchar;
				char2sig <= char1sig;
				char3sig <= char2sig;
				char4sig <= char3sig;			
			else if (inputchar = char1sig) and (inputchar /= "1111111") then 
				--??
				--??
				--??
			end if;
								
		end if;
	end process;
	
	

end Behavioral;

inputchar is the 7 bit variable to display 1 digit.
 

hi

process(clk)
begin
if ( clk = '1' and clk'event) then
if (inputchar /= "1111111") then
char1sig <= inputchar;
char2sig <= char1sig;
char3sig <= char2sig;
char4sig <= char3sig;
else
char1sig <= char1sig ;
char2sig <= char2sig;
char3sig <= char3sig;
char4sig <= char4sig;
end if;

end if;
 

Thnx but it's not working. When I press a number on the keyboard, al the four digits change into that number. My purpose is to display for example 1234 when I press 1,2,3,4 but also 5566 when I press 5,5,6,6. Much appreciation for any other suggestions :)
 

it should work) my simulation shows me the correct work, "11111111" is a state on line when nothing send, am i right?
 

In the original code instead of using a proper delay to avoid a key being detected many times
you have used a condition that only reads the pressed button if it was different from the last key pressed,
so every key was only detected once.
You have to use some kind of counter (delay) so that the input is not read with the clock rate (which is very fast),
this is why the code from kirill fills the screen with 1111.

Alex
 

I thought that keyboard send a packet with key number

---------- Post added at 17:25 ---------- Previous post was at 17:19 ----------

alexan_e :
I should regard it like a joke?
 
I'm not sure how it is send but since he presses 1 and the screen is filled with 1s he has a problem with the character read many times instead of one so probably has to add a delay.

Alex
 

i agree, if he has high working frequency of his design(f design > f transmitting), this behaviour should happend.
 

I've made a counter with a frequency of 5 Hz and the code is working :). But when I don't press any button, the screen is filling itself with the previous pressed numbers but I want the screen to stop shifting the digits when no button is pressed. Thanks for the help.
 

Keep your original code and remove

Code:
if [COLOR="red"](inputchar /= char1sig) and[/COLOR] (inputchar /= "1111111") then   
				char1sig <= inputchar;
				char2sig <= char1sig;
				char3sig <= char2sig;
				char4sig <= char3sig;	
[COLOR="red"]else if (inputchar = char1sig) and (inputchar /= "1111111") then 
				--??
				--??
				--??[/COLOR]
			end if;

Alex

---------- Post added at 17:53 ---------- Previous post was at 17:43 ----------

I've made a counter with a frequency of 5 Hz and the code is working :). But when I don't press any button, the screen is filling itself with the previous pressed numbers but I want the screen to stop shifting the digits when no button is pressed. Thanks for the help.

I think you are doing something with the counter, there should be a check for counter and inputchar /= "1111111",
can you post the code?

Alex
 

Already tried that but my display is still filling itself with the last pressed button, in other words, it doesn't stop when I don't press a button. Is my clock divider correct (50 MHz/ 10000000 = 5 Hz)?

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

---- Uncomment the following library declaration if instantiating
---- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;

entity charshift is
    Port ( clk 		: in   STD_LOGIC;
			  inputchar : in   STD_LOGIC_VECTOR (6 downto 0);
           char1 		: out  STD_LOGIC_VECTOR (6 downto 0);
           char2 		: out  STD_LOGIC_VECTOR (6 downto 0);
           char3 		: out  STD_LOGIC_VECTOR (6 downto 0);
           char4 		: out  STD_LOGIC_VECTOR (6 downto 0) );
end charshift;

architecture Behavioral of charshift is
	signal char1sig : STD_LOGIC_VECTOR (6 downto 0 );
	signal char2sig : STD_LOGIC_VECTOR (6 downto 0 );
	signal char3sig : STD_LOGIC_VECTOR (6 downto 0 );
	signal char4sig : STD_LOGIC_VECTOR (6 downto 0 );
begin

	char1 <= char1sig;
	char2 <= char2sig;
	char3 <= char3sig;
	char4 <= char4sig;
	
	process(clk)
	begin
		if ( clk = '1' and clk'event)	then
			if (inputchar /= "1111111") then
				char1sig <= inputchar;
				char2sig <= char1sig;
				char3sig <= char2sig;
				char4sig <= char3sig;
					
			end if;
					
		end if;
	end process;
	
	

end Behavioral;
 
Last edited:

How can it "walk" now when it didn't before, if "1111111" is the signal when no key is pressed then it shouldn't happen.
I also don't see a delay (as a counter at least), where did you change your clock frequency to /10000000

Alex
 

How can it "walk" now when it didn't before, if "1111111" is the signal when no key is pressed then it shouldn't happen.
I also don't see a delay (as a counter at least), where did you change your clock frequency to /10000000

Alex

Here is my code for changing the PS2 scancode into code for the display:
Code:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

---- Uncomment the following library declaration if instantiating
---- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;

entity PS2tochar is
    Port ( sc   : in   STD_LOGIC_VECTOR (7 downto 0);
           sevenseg : out  STD_LOGIC_VECTOR (6 downto 0) );
end PS2tochar;

architecture Behavioral of PS2tochar is

	Signal char : STD_LOGIC_VECTOR (7 downto 0);

begin

process(sc)
begin

	case sc is
	
	WHEN "01000101" => sevenseg <= "1000000"; -- 0
	WHEN "00010110" => sevenseg <= "1111001"; -- 1
	WHEN "00011110" => sevenseg <= "0100100"; -- 2
	WHEN "00100110" => sevenseg <= "0110000"; -- 3
	WHEN "00100101" => sevenseg <= "0011001"; -- 4
	WHEN "00101110" => sevenseg <= "0010010"; -- 5
	WHEN "00110110" => sevenseg <= "0000010"; -- 6
	WHEN "00111101" => sevenseg <= "1111000"; -- 7
	WHEN "00111110" => sevenseg <= "0000000"; -- 8
	WHEN "01000110" => sevenseg <= "0010000"; -- 9
	WHEN OTHERS     => sevenseg <= "1111111";
	
	end case;

end process;

end Behavioral;
So "1111111" is being sent when no button is pressed.

I've made a clock divider block with the folowing code:
Code:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

---- Uncomment the following library declaration if instantiating
---- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;

entity clkdivider2 is
    Port ( A : in  STD_LOGIC;
           B : out  STD_LOGIC);
end clkdivider2;

architecture Behavioral of clkdivider2 is
	signal D : STD_LOGIC;
	signal count: integer;
	signal divide: integer := 1000000; 
begin

Process (A)
begin

	B <= D;
	
	if  falling_edge(A) then
		
		count <= count + 1;
		
		if count = divide then
			D <= not D;
			count <= 0;
		end if;
		
	end if;
end process;
end Behavioral;

When I add (inputchar /= char1sig) to my code, he stops 'walking'. I think the scancode remain in his memory so there is never the code "1111111", am I correct?
 
Last edited:

If you clock is 50MHz and you invert D every 1000000 clocks then D has a frequency of (50M/1M)/2 =25Hz,
you have a half period every 1000000 times.

I can't understand what is going wrong but this code wouldn't "walk" if inputchar was "1111111"

Code:
if (inputchar /= "1111111") then
				char1sig <= inputchar;
				char2sig <= char1sig;
				char3sig <= char2sig;
				char4sig <= char3sig;

if you add (inputchar /= char1sig) then you will not be able to detect the same character again.

Alex
 

If you clock is 50MHz and you invert D every 1000000 clocks then D has a frequency of (50M/1M)/2 =25Hz,
you have a half period every 1000000 times.

I can't understand what is going wrong but this code wouldn't "walk" if inputchar was "1111111"

Code:
if (inputchar /= "1111111") then
				char1sig <= inputchar;
				char2sig <= char1sig;
				char3sig <= char2sig;
				char4sig <= char3sig;


if you add (inputchar /= char1sig) then you will not be able to detect the same character again.

Alex

You're right, my bad. My code is walking because the scan code remains the same. I've choosen to display the scancode on the led's and when I don't press a button, the scancode is visible of the last pressed button. Is there a way I can reset the scan code after I pressed a button?
 

Probably, you want to detect release codes as well as press codes?
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top