Skocz do zawartości

PS2_MOUSE część 2


kroszkanorber

Pomocna odpowiedź

----------------------------------------------------------------------------------
--PS2_Controller

--moduł główny

--linia zegarowa kontrolera taktowana generatorem 32kHz !
----------------------------------------------------------------------------------

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


entity PS2_Controller is
    Port ( Reset : in  STD_LOGIC;
           Clk : in  STD_LOGIC;                              --linia zegarowa dla układu kofigurowalnego ok 30 kHz
           PS2_D : inout  STD_LOGIC;                         --linia danych PS2
           PS2_C : inout  STD_LOGIC;                         --linia zegarowa PS2
           PS2_RX_RESET : in  STD_LOGIC;                     --linia wejściowa sterująca zezwoleniem na pracę układu
           PS2_RX_DO : out  STD_LOGIC_VECTOR (7 downto 0);   --dane odebrane od urządzenia PS2
           PS2_RX_STATUS : out  STD_LOGIC;                   --informacja o czsie trwania transmisji (aktywny = '0')
           PS2_RX_ERROR : out  STD_LOGIC;                    --informacja o poprawności odebranych danych (aktywny = '0')
           PS2_TX_WE : in  STD_LOGIC;                        --sygnał dla zapisu danych i ich wysłania (aktywny = '0')
           PS2_TX_DI : in  STD_LOGIC_VECTOR (7 downto 0);    --linia danych wejściowych
           PS2_TX_Status : out  STD_LOGIC );                 --informacja o czsie trwania transmisji (aktywny = '0')
end PS2_Controller;

architecture Behavioral of PS2_Controller is


	COMPONENT PS2_RX
	PORT(
		Reset : IN std_logic;
		Clk : IN std_logic;
		PS2_D : IN std_logic;
		PS2_C : IN std_logic;
		PS2_RX_RESET : IN std_logic;          
		PS2_RX_DO : OUT std_logic_vector(7 downto 0);
		PS2_RX_STATUS : OUT std_logic;
		PS2_RX_ERROR : OUT std_logic
		);
	END COMPONENT;

	COMPONENT PS2_TX
	PORT(
		Reset : IN std_logic;
		Clk : IN std_logic;
		PS2_D : IN std_logic;
		PS2_C : IN std_logic;
		PS2_TX_WE : IN std_logic;
		PS2_TX_DI : IN std_logic_vector(7 downto 0);          
		PS2_Do : OUT std_logic;
		PS2_Co : OUT std_logic;
		PS2_TX_Status : OUT std_logic
		);
	END COMPONENT;
	
	signal PS2_Do : std_logic;
	signal PS2_Co : std_logic;

begin


	Inst_PS2_RX: PS2_RX PORT MAP(
		Reset => Reset,
		Clk => Clk,
		PS2_D => PS2_D,
		PS2_C => PS2_C,
		PS2_RX_RESET => PS2_RX_RESET,
		PS2_RX_DO => PS2_RX_DO,
		PS2_RX_STATUS => PS2_RX_STATUS,
		PS2_RX_ERROR => PS2_RX_ERROR
	);

	Inst_PS2_TX: PS2_TX PORT MAP(
		Reset => Reset,
		Clk => Clk,
		PS2_D => PS2_D,
		PS2_C => PS2_C,
		PS2_Do => PS2_Do,
		PS2_Co => PS2_Co,
		PS2_TX_WE => PS2_TX_WE,
		PS2_TX_DI => PS2_TX_DI,
		PS2_TX_Status => PS2_TX_Status
	);
	
	PS2_D <= '0' when PS2_Do = '0' else 'Z'; --konfiguracja linii sygnałowych PS2 jako linii wejściowych i wyjściowych
	PS2_C <= '0' when PS2_Co = '0' else 'Z';


end Behavioral;
----------------------------------------------------------------------------------
--PS2_RX
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity PS2_RX is
    Port ( Reset : in  STD_LOGIC;
           Clk : in  STD_LOGIC;                              --linia zegarowa dla układu kofigurowalnego ok 30 kHz
           PS2_D : in  STD_LOGIC;                            --linia danych PS2 wejściowa
           PS2_C : in  STD_LOGIC;                            --linia zegarowa PS2 wejściowa
           PS2_RX_RESET : in  STD_LOGIC;                     --linia wejściowa sterująca zezwoleniem na pracę układu
           PS2_RX_DO : out  STD_LOGIC_VECTOR (7 downto 0);   --dane odebrane od urządzenia PS2
           PS2_RX_STATUS : out  STD_LOGIC;                   --informacja o czsie trwania transmisji (aktywny = '0')
           PS2_RX_ERROR : out  STD_LOGIC);                   --informacja o poprawności odebranych danych (aktywny = '0')
end PS2_RX;

architecture Behavioral of PS2_RX is

	signal D : std_logic_vector (10 downto 0);                --rejestr przesuwny służący do odbioru danych od urządzenia PS2
	signal Error : std_logic;                                 --sygnał generujący błąd poprawności odbioru danych
	signal Reset1 : std_logic;                                --sygnał pomocniczy dla zapisu danych do rejestru przesuwnego
	signal Parity : std_logic_vector (7 downto 0);            --generator parzystości dla danych wejściowych pochodzących od urządzenia PS2

begin

	process (Reset, Reset1, PS2_D, PS2_C, PS2_RX_RESET)       --odbiór danych od urządzenia PS2
	begin
		if Reset = '0' or PS2_RX_RESET = '0' or Reset1 = '0' then
			D <= (others => '1');
		else
			if PS2_C'event and PS2_C = '0' then
				D <= PS2_D & D(10 downto 1);
			end if;
		end if;
	end process;
	
	process(Clk, D, Reset, PS2_RX_RESET)                      --dekoder odebranych danych od urządzenia PS2
	begin
		if Reset = '0' or PS2_RX_RESET = '0' then
			PS2_RX_ERROR <= '0';
			PS2_RX_STATUS <= '0';
		else
			if Clk'event and Clk = '0' then
				if D(0) = '0' and D(10) = '1' then
					PS2_RX_DO <= D(8 downto 1);
					PS2_RX_ERROR <= Error;
					PS2_RX_STATUS <= '1';
					Reset1 <= '0';
				else
					PS2_RX_STATUS <= '0';
					Reset1 <= '1';
				end if;
			end if;
		end if;
	end process;
	
	Error <= '1' when D(0) = '0'                             --generator poprawności odebranych danych
					  and Parity(7) = '0'
					  and D(10) = '1'
				    else '0';

	Parity(0) <= D(1) xor D(2);                              --generator parzystości odebranych danych
	Parity(1) <= D(3) xor D(4);
	Parity(2) <= D(5) xor D(6);
	Parity(3) <= D(7) xor D(8);
	Parity(4) <= Parity(0) xor Parity(1);
	Parity(5) <= Parity(2) xor Parity(3);
	Parity(6) <= Parity(4) xor Parity(5);
	Parity(7) <= Parity(6) xor D(9);

end Behavioral;
----------------------------------------------------------------------------------
-- PS2_TX
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;


entity PS2_TX is
    Port ( Reset : in  STD_LOGIC;
           Clk : in  STD_LOGIC;                              --linia zegarowa dla układu kofigurowalnego ok 30 kHz
           PS2_D : in  STD_LOGIC;                            --linia danych PS2 wejściowa
           PS2_C : in  STD_LOGIC;                            --linia zegarowa PS2 wejściowa
           PS2_Do : out  STD_LOGIC;                          --linia danych PS2 wyjściowa
           PS2_Co : out  STD_LOGIC;                          --linia zegarowa PS2 wyjściowa
           PS2_TX_WE : in  STD_LOGIC;                        --sygnał dla zapisu danych i ich wysłania (aktywny = '0')
           PS2_TX_DI : in  STD_LOGIC_VECTOR (7 downto 0);    --linia danych wejściowych
           PS2_TX_Status : out  STD_LOGIC );                 --informacja o czsie trwania transmisji (aktywny = '0')
end PS2_TX;

architecture Behavioral of PS2_TX is

	signal Cnt_RTS : std_logic_vector (2 downto 0) := "101";  --licznik pomocniczy dla wysłania danych do urządzenia PS2
	signal D : std_logic_vector (9 downto 0) := "1111111111"; --rejestr przesuwny służący do wysłanie danych do urządzenia PS2
	signal ParityGen : std_logic_vector (6 downto 0);         --generator parzystości dla danych do urządzenia PS2
	signal Parity : std_logic;                                --zanegowany sygnał parzystości
	signal Status : std_logic := '1';                         --sygnał pomocniczy wskazyjący ukończoną transmisję danych

begin

	ParityGen(0) <= PS2_TX_DI(0) xor PS2_TX_DI(1);            --generator parzystości danych wejściowych
	ParityGen(1) <= PS2_TX_DI(2) xor PS2_TX_DI(3);
	ParityGen(2) <= PS2_TX_DI(4) xor PS2_TX_DI(5);
	ParityGen(3) <= PS2_TX_DI(6) xor PS2_TX_DI(7);
	ParityGen(4) <= ParityGen(0) xor ParityGen(1);
	ParityGen(5) <= ParityGen(2) xor ParityGen(3);
	ParityGen(6) <= ParityGen(4) xor ParityGen(5);
	Parity <= not ParityGen(6);
	
	process(Clk, Reset, PS2_TX_WE)                             --licznik pomocniczy służący do wygenerowania sygnałów RTS i wysłania danych
	begin
		if Reset = '0' then
			Cnt_RTS <= "101";
		elsif  PS2_TX_WE = '0' then
			Cnt_RTS <= "000";
		else
			if Clk'event and Clk = '0' then
				if Cnt_RTS = "101" then
					null;
				else
					Cnt_RTS <= Cnt_RTS + '1';
				end if;
			end if;
		end if;
	end process;
	
	with Cnt_RTS select                                       --wybór sygnału dla zegara systemowego służący do wygenerowania sygnału reqest to send
		PS2_Co <= '0' when "001",
					 '0' when "010",
					 '0' when "011",
					 '0' when "100",
					 '1' when others;
	
	with Cnt_RTS select                                       -- wybór sygnału dla linii danych zezwalająca na wysłanie danych do urządzenia PS2
		PS2_Do <= D(0) when "100",
					 D(0) when "101",
					 '1' when others;
					 
	process(PS2_C, PS2_D, Reset, PS2_TX_DI, PS2_TX_WE, Cnt_RTS, Parity)
	begin
		if Reset = '0' then
			Status <= '1';
			D <= (others => '1');
		elsif PS2_TX_WE = '0'  then                           --sygnał zapisujący dane do rejestru przesuwnego
			Status <= '0';                                     --sygnał zajętości modułu transmisji danych do urządzenia PS2 
			D <= Parity & PS2_TX_DI & '0';
		else
			if Cnt_RTS = "101" then                            --zezwolenie na wysłanie danych po zainicjowaniu linii.
				if PS2_C'event and PS2_C = '0' then             --zegar z opóźnieniem względem zegara systemowego od urządzenia PS2
					if D = "1111111111" and PS2_D = '0' and Status = '0' then --koniec przesyłu danych
						Status <= '1';                            --sygnał zakończonej transmisji
					else
						D <= '1' & D(9 downto 1);
					end if;
				end if;
			end if;
		end if;
	end process;
	
	process(Clk, Status, PS2_D, PS2_C, Reset)                --procedura dla sygnału zewnętrznego informująca o transmisji danych
	begin
		if Status = '0' then
			PS2_TX_Status <= '0';
		elsif Reset = '0' then
			PS2_TX_Status <= '1';
		else
			if Clk'event and Clk = '0' then
				if PS2_C = '1' and PS2_D = '1' and  Status = '1' then
					PS2_TX_Status <= '1';
				end if;
			end if;
		end if;
	end process;


end Behavioral;

Kod VHDL składa się z 3 modułów.

1 Moduł główny o nazwie PS2_Controller, 2 Moduł PS2_TX do wysyłania danych, 3 Moduł PS2_RX do odbioru danych.

Aby kod funkcjonował poprawnie i był w pełni funkcjonalny trzeba zainstalować trzy moduły.

Wysyłanie danych do urządzenia ps2 nie jest skomplikowane.

Na szynę PS2_TX_DI podajemy dane które chcemy wysłać.

Na linię PS2_TX_WE podajemy stan niski(w tym momencie zostaną zatrzaśnięte dane asynchronicznie do rejestru i wyzerowany licznik pomocniczy służący do wysłania sygnału reqest to send). Następnie podać stan wysoki który zezwoli na wysłanie danych do urządzenia PS2.

Na linii PS2_TX_WE Stan wysoki jest stanem oczekiwania na instrukcje od Hosta (np kontroler avr, lub inny)

PS2_TX_Status i PS2_RX_Status to linie informujące o trwaniu( logiczne 0 ) procesu lub jego zakończeniu( logiczne 1 ).

PS2_RX_ERROR jest linią informującą o błędnych danych odczytanych z urządzenia PS2

Kontroler PS2 używałem z klawiaturą i myszą, oba urządzenia obsługuje bez problemów.

image.thumb.png.b8a0873d0bbaa1f865c5036cf5727e19.png

Pozdrawiam

  • Lubię! 2
Link do komentarza
Share on other sites

Bądź aktywny - zaloguj się lub utwórz konto!

Tylko zarejestrowani użytkownicy mogą komentować zawartość tej strony

Utwórz konto w ~20 sekund!

Zarejestruj nowe konto, to proste!

Zarejestruj się »

Zaloguj się

Posiadasz własne konto? Użyj go!

Zaloguj się »
×
×
  • Utwórz nowe...

Ważne informacje

Ta strona używa ciasteczek (cookies), dzięki którym może działać lepiej. Więcej na ten temat znajdziesz w Polityce Prywatności.