Monday, 31 July 2017

VHDL PS2 keyboard and mouse FPGA board interface Xilinx Spartan 3 LED implementation + code



                                           Version using the mouse to move the LEDs

                                            Version using the Keyboard to move the LEDs
MASTER MODULE PS2 MOUSE
 library ieee;  
 use ieee.std_logic_1164.all;  
 use ieee.numeric_std.all;  
 entity mouse_led is  
 port (  
 clk, reset: in std_logic;  
 ps2d, ps2c : inout std_logic;  
 led: out std_logic_vector ( 7 downto 0)  
 ) ;  
 end mouse_led;  
 architecture arch of mouse_led is  
 signal p_reg , p_next : unsigned (9 downto 0 ) ;  
 signal xm: std_logic_vector (8 downto 0 ) ;  
 signal m_done_tick: std_logic;  
 signal btnm: std_logic_vector (2 downto 0) ;  
 begin  
 -- in s t a n t i a t i o n  
 mouse_unit: entity work.mouse(arch)  
 port map(clk=>clk, reset=>reset ,  
 ps2d=>ps2d, ps2c=>ps2c,  
 xm=>xm, ym=>open , btnm=>btnm ,  
 m_done_tick=>m_done_tick);  
 -- r e g is t e r  
 process (clk , reset)  
 begin  
 if reset= '1' then  
 p_reg <= ( others => '0' ) ;  
 elsif (clk'event and clk='1') then  
 p_reg <= p_next;  
 end if ;  
 end process ;  
 -- c o u n t e r  
 p_next <= p_reg when m_done_tick= '0' else  
 "0000000000" when btnm(0)='1' else -- l e f t b u t t o n  
 "1111111111" when btnm(1)='1' else -- r i g h t b u t t o n  
 p_reg + unsigned(xm(8) & xm);  
 with p_reg(9 downto 7) select  
 led <=   
     "10000000" when "000",  
            "01000000" when "001",  
            "00100000" when "010",  
            "00010000" when "011",  
            "00001000" when "100",  
            "00000100" when "101",  
            "00000010" when "110",  
            "00000001" when others;  
 end arch;  

FINITE STATE MACHINE MOUSE MODULE
 library ieee;  
 use ieee.std_logic_1164.all;  
 use ieee.numeric_std.all;  
 entity mouse is  
 port (  
 clk, reset: in std_logic;  
 ps2d, ps2c : inout std_logic ;  
 xm, ym: out std_logic_vector ( 8 downto 0 ) ;  
 btnm: out std_logic_vector (2 downto 0 ) ;  
 m_done_tick : out std_logic  
 ) ;  
 end mouse;  
 architecture arch of mouse is  
 constant STRM: std_logic_vector ( 7 downto 0 ) := "11110100" ;  
 -- stream command F4  
 type state_type is (init1, init2, init3,  
 pack1 , pack2, pack3, done) ;  
 signal state_reg , state_next : state_type;  
 signal rx_data: std_logic_vector ( 7 downto 0 ) ;  
 signal rx_done_tick , tx_done_tick: std_logic;  
 signal wr_ps2 : std_logic;  
 signal x_reg , y_reg : std_logic_vector ( 8 downto 0) ;  
 signal x_next , y_next : std_logic_vector (8 downto 0 ) ;  
 signal btn_reg , btn_next : std_logic_vector ( 2 downto 0 ) ;  
 begin  
 -- in s t a n t i a t i o n  
 ps2_rxtx_unit : entity work.ps2_rxtx (arch)  
 port map(clk=>clk , reset=>reset , wr_ps2=>wr_ps2,  
 din=>STRM , dout=>rx_data ,  
 ps2d=>ps2d, ps2c=>ps2c,  
 rx_done_tick=>rx_done_tick,  
 tx_done_tick=>tx_done_tick);  
 --s t a t e and d a t a r e g is t e r s  
 process (clk, reset)  
 begin  
                if reset = '1' then  
                state_reg <= init1;  
                x_reg <= ( others =>'0' ) ;  
                y_reg <= ( others => '0' ) ;  
                btn_reg <= ( others => '0' ) ;  
                elsif (clk'event and clk='1') then  
                state_reg <= state_next ;  
                x_reg <= x_next;  
                y_reg <= y_next;  
                btn_reg <= btn_next ;  
                end if ;  
 end process ;  
 -- n e x t - s t a t e 1 o g i c  
 process (state_reg ,rx_done_tick, tx_done_tick,  
 x_reg ,y_reg, btn_reg, rx_data)  
 begin  
 wr_ps2 <= '0' ;  
 m_done_tick <= '0' ;  
 x_next <= x_reg;  
 y_next <= y_reg;  
 btn_next <= btn_reg ;  
 state_next <= state_reg;  
 case state_reg is  
 when init1 =>  
 wr_ps2 <= '1';  
 state_next <= init2 ;  
 when init2 => -- w a i t f o r s e n d t o c o m p l e t e  
 if tx_done_tick = '1' then  
 state_next <= init3 ;  
 end if ;  
 when init3 => -- w a i t f o r a c k n o w l e d g e p a c k e t  
 if rx_done_tick = '1' then  
 state_next <= pack1 ;  
 end if ;  
 when pack1 => -- w a i t f o r 1 s t d a t a p a c k e t  
 if rx_done_tick = '1' then  
 state_next <= pack2 ;  
 y_next ( 8 ) <= rx_data ( 5 ) ;  
 x_next (8) <= rx_data ( 4 ) ;  
 btn_next <= rx_data ( 2 downto 0 ) ;  
 end if ;  
 when pack2 => -- w a i t f o r 2 n d d a t a p a c k e t  
 if rx_done_tick = '1' then  
 state_next <= pack3 ;  
 x_next ( 7 downto 0) <= rx_data ;  
 end if ;  
 when pack3 => -- w a i t f o r 3 r d d a t a p a c k e t  
 if rx_done_tick = '1' then  
 state_next <= done ;  
 y_next ( 7 downto 0 ) <= rx_data ;  
 end if ;  
 when done =>  
 m_done_tick <= '1' ;  
 state_next <= pack1 ;  
 end case ;  
 end process ;  
 xm <= x_reg ;  
 ym <= y_reg ;  
 btnm <= btn_reg ;  
 end arch ;  

RX TX MODULE
 library ieee;  
 use ieee.std_logic_1164.all;  
 entity ps2_rxtx is  
 port (  
 clk, reset: in std_logic;  
 wr_ps2 : std_logic;  
 din: in std_logic_vector ( 7 downto 0) ;  
 dout : out std_logic_vector ( 7 downto 0 ) ;  
 rx_done_tick : out std_logic ;  
 tx_done_tick: out std_logic;  
 ps2d, ps2c : inout std_logic  
 );  
 end ps2_rxtx;  
 architecture arch of ps2_rxtx is  
 signal tx_idle : std_logic;  
 begin  
 ps2_tx_unit : entity work.ps2_tx  
                                    port map(clk=>clk, reset=>reset , wr_ps2=>wr_ps2,  
                                    din=>din, ps2d=>ps2d, ps2c=>ps2c,  
                                    tx_idle=>tx_idle, tx_done_tick=>tx_done_tick);  
 ps2_rx_unit : entity work.ps2_rx(arch)  
                                    port map(clk=>clk , reset=>reset , rx_en=>tx_idle,  
                                    ps2d=>ps2d, ps2c=>ps2c,  
                                    rx_done_tick=>rx_done_tick, dout=>dout);  
 end arch;  

TX FSM MODULE
 library ieee;  
 use ieee.std_logic_1164.all;  
 use ieee.numeric_std.all;  
 entity ps2_tx is  
 port (  
 clk, reset: in std_logic;  
 din: in std_logic_vector (7 downto 0) ;  
 wr_ps2: std_logic;  
 ps2d, ps2c : inout std_logic ;  
 tx_idle: out std_logic;  
 tx_done_tick: out std_logic  
 ) ;  
 end ps2_tx;  
 architecture arch of ps2_tx is  
 type statetype is (idle, rts, start, data, stop);  
 signal state_reg , state_next: statetype;  
 signal filter_reg , filter_next : std_logic_vector ( 7 downto 0 ) ;  
 signal f_ps2c_reg ,f_ps2c_next: std_logic;  
 signal b_reg , b_next : std_logic_vector (8 downto 0 ) ;  
 signal c_reg , c_next : unsigned (12 downto 0) ;  
 signal n_reg ,n_next : unsigned (3 downto 0) ;  
 signal par: std_logic;  
 signal tri_c , tri_d: std_logic ;  
 signal fall_edge : std_logic ;  
 signal ps2c_out , ps2d_out : std_logic;  
 begin --__ ______________________-_--____________________________________________-_--_-_--_--_- _ _ _ ~ ~ ~ ~ ~ _ ~ ~ ~  
 -- f i l t e r a n d f a l l i n g - e d g e t i c k g e n e r a t i o n f o r ps2c  
 --. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  
 process (clk , reset)  
 begin  
 if reset= '1' then  
      filter_reg <= ( others => '0' ) ;  
      f_ps2c_reg <= '0' ;  
 elsif (clk'event and clk= '1' ) then  
   filter_reg <= filter_next;  
      f_ps2c_reg <= f_ps2c_next;  
 end if;  
 end process;  
 filter_next <= ps2c & filter_reg ( 7 downto 1);  
 f_ps2c_next <= '1' when filter_reg = "11111111" else  
         '0' when filter_reg = "00000000" else  
         f_ps2c_reg ;  
 fall_edge <= f_ps2c_reg and ( not f_ps2c_next ) ;  
 -- f s m d  
 -- registers  
 process ( clk , reset)  
 begin  
 if reset = '1' then  
      state_reg <= idle ;  
      c_reg <= ( others => '0' ) ;  
      n_reg <= ( others => '0' ) ;  
      b_reg <= ( others => '0' ) ;  
 elsif ( clk'event and clk = '1' ) then  
      state_reg <= state_next ;  
      c_reg <= c_next ;  
      n_reg <= n_next ;  
      b_reg <= b_next ;  
 end if ;  
 end process ;  
 -- odd par i t y b i t  
 par <= not ( din (7) xor din (6) xor din (5) xor din (4) xor  
                      din (3) xor din (2) xor din (1) xor din (0) );   
 -- f s m d n e x t - s t a t e l o g i c and data p a t h l o g i c  
 process ( state_reg , n_reg , b_reg , c_reg , wr_ps2 ,  
                 din , par , fall_edge )  
 begin  
 state_next <= state_reg ;  
 c_next <= c_reg ;  
 n_next <= n_reg ;  
 b_next <= b_reg ;  
 tx_done_tick <= '0' ;  
 ps2c_out <= '1';  
 ps2d_out <= '1' ;  
 tri_c <= '0' ;  
 tri_d <= '0' ;  
 tx_idle <= '0' ;  
 case state_reg is  
      when idle =>  
                          tx_idle <= '1' ;  
                          if wr_ps2 = '1' then       
                               b_next <= par & din ;  
                               c_next <= ( others => '1' ) ; -- 2 * 1 3 - 1  
                               state_next <= rts ;  
                          end if ;  
      when rts => -- r e q u e s t t o s e n d  
                          ps2c_out <= '0' ;  
                          tri_c <= '1';  
                          c_next <= c_reg - 1;  
                          if(c_reg = 0 ) then  
                               state_next <= start ;  
                          end if ;  
      when start => -- a s s e rtstart bit  
                               ps2d_out <= '0' ;  
                               tri_d <= '1' ;  
                               if fall_edge = '1' then  
                                         n_next <= "1000" ;  
                                         state_next <= data ;  
                               end if ;  
      when data => -- 8 data + I par i t y  
                          ps2d_out <= b_reg (0) ;  
                          tri_d <= '1' ;  
                          if fall_edge = '1' then  
                               b_next <= '0' & b_reg ( 8 downto 1);  
                               if n_reg = 0 then  
                                    state_next <= stop ;  
                               else  
                                    n_next <= n_reg - 1;  
                               end if ;  
                          end if ;  
      when stop => -- assume f l o a t i n g h i g h f o r ps2d  
                          if fall_edge = '1' then  
                               state_next <= idle ;  
                               tx_done_tick <='1';  
                          end if ;  
 end case ;  
 end process ;  
 --tri_state_buffers  
 ps2c <= ps2c_out when tri_c = '1' else 'Z' ;  
 ps2d <= ps2d_out when tri_d = '1' else 'Z' ;  
 --  
 end arch ;  

RX FSM MODULE
 library IEEE;  
 use IEEE.STD_LOGIC_1164.ALL;  
 use ieee.numeric_std.all;  
 entity ps2_rx is  
  port (  
 clk, reset: in std_logic;  
 ps2d, ps2c: in std_logic; -- k e y d a t a , k e y c l o c k  
 rx_en : in std_logic ;  
 rx_done_tick: out std_logic;  
 dout: out std_logic_vector (7 downto 0)  
 ) ;  
 end ps2_rx;  
 architecture arch of ps2_rx is  
 type statetype is (idle, dps, load);  
 signal state_reg , state_next : statetype;  
 signal filter_reg , filter_next : std_logic_vector (7 downto 0 ) ;  
 signal f_ps2c_reg, f_ps2c_next : std_logic ;  
 signal n_reg , n_next : unsigned (3 downto 0) ;  
 signal fall_edge : std_logic ;  
 signal b_reg , b_next : std_logic_vector (10 downto 0 ) ;  
 begin  
 --______________________________________________________________________________________-_-_--_-_--_ __  
 -- f i l t e r and f a l l i n g e d g e t i c k g e n e r a t i o n f o r ps2c  
 process ( clk , reset )  
 begin  
 if reset = '1' then  
 filter_reg <= ( others => '0' ) ;  
 f_ps2c_reg <= '0' ;  
 elsif ( clk'event and clk = '1' ) then  
 filter_reg <= filter_next ;  
 f_ps2c_reg <= f_ps2c_next ;  
 end if ;  
 end process ;  
 filter_next <= ps2c & filter_reg ( 7 downto 1);  
 f_ps2c_next <= '1' when filter_reg = "11111111" else  
         '0' when filter_reg = "00000000" else  
                          f_ps2c_reg ;  
 fall_edge <= f_ps2c_reg and ( not f_ps2c_next ) ;  
 --______-_______-_-_-_-_-_-_-__-_---_--_------_--_--- --------------  
 --45 -- f s m d t o e x t r a c t t h e 8 - b i t d a t a  
 --____ _-______-______-_-________________________-_-______-____-_-__-_--------------- ---------_-_------  
 ---_ r e g is t e r s  
 process ( clk , reset )  
 begin  
 if reset = '1' then  
 state_reg <= idle ;  
 n_reg <= ( others => '0' ) ;  
 b_reg <= ( others => '0' ) ;  
 elsif ( clk'event and clk = '1' ) then  
 state_reg <= state_next ;  
 n_reg <= n_next ;  
 b_reg <= b_next ;  
 end if ;  
 end process ;  
 -- n e x t - s t a t e l o g i c  
 process ( state_reg , n_reg,b_reg, fall_edge , rx_en , ps2d )  
 begin  
 rx_done_tick <= '0' ;  
 state_next <= state_reg ;  
 n_next <= n_reg ;  
 b_next <= b_reg ;  
 case state_reg is  
 when idle =>  
 if fall_edge = '1' and rx_en = '1' then  
 --s h if t i n s t a r t b i t  
 b_next <= ps2d & b_reg ( 10 downto 1);  
 n_next <= "1001" ;  
 state_next <= dps ;  
 end if ;  
 when dps => -- 8 d a t a + I p a r i t y + 1 s t o p  
 if fall_edge = '1' then  
 b_next <= ps2d & b_reg ( 10 downto 1 ) ;  
 if n_reg = 0 then  
 state_next <= load ;  
 else  
 n_next <= n_reg - 1;  
 end if ;  
 end if ;  
 when load =>  
 -- I e x t r a c l o c k t o c o m p l e t e f h e l a s t s h if t  
 state_next <= idle ;  
 rx_done_tick <='1';  
 end case ;  
 end process ;  
 -- o u t p u t  
 dout <= b_reg ( 8 downto 1); -- d a t a b i t s  
 end arch ;  

CONSTRAINT FILE
 #Created by Constraints Editor (xc3s250e-tq144-4) - 2017/07/29  
 NET "clk" LOC = "P129"; #TNM_NET = clk;  
 TIMESPEC TS_clk = PERIOD "clk" 50 MHz HIGH 50%;  
 #8I/Os_2 (Input)  
 NET "reset" LOC = "p124" ;  
 #16I/Os_1 (output)  
 NET "ps2d" LOC = "p126" ;  
 NET "ps2c" LOC = "p125" ;  
 #16I/Os_1 (output)  
 NET "led[0]" LOC = "p94" ;  
 NET "led[1]" LOC = "p93" ;  
 NET "led[2]" LOC = "p92" ;  
 NET "led[3]" LOC = "p91" ;  
 NET "led[4]" LOC = "p88" ;  
 NET "led[5]" LOC = "p87" ;  
 NET "led[6]" LOC = "p86" ;  
 NET "led[7]" LOC = "p85" ;  

TUTORIAL ON HOW TO ADD CLOCK TIMING CONSTRAINTS IN A MODULE

No comments:

Post a Comment