FPGA projects, Verilog projects, VHDL projects

[FPGA tutorial] How to interface a mouse with Basys 3 FPGA

Last time, I presented an FPGA tutorial on how to control the 4-digit 7-segment display on the Basys 3 FPGA board. Full Verilog and VHDL code for displaying a 4-digit number on the 7-segment display of FPGA Basys 3 were also provided.

This FPGA tutorial tells you how to interface a mouse with Xilinx Basys 3 FPGA board. The FPGA tutorial also provides a Verilog code for interfacing a mouse with FPGA Basys 3.

How to interface a mouse with FPGA Basys 3

The on-board Auxiliary Function Microcontroller PIC24FJ128 allows Basys 3 FPGA to have USB HID host capability. Once the FPGA is programmed, the microcontroller is in USB HID host mode which can interface the FPGA with a mouse or keyboard connected to the USB type-A connector (J2) as shown in the following picture.
How to interface a mouse with Basys 3 FPGA
As illustrated in the picture above, the microcontroller's PS2_CLK and PS2_DAT signals are used to implement a PS/2 interface for communication with a mouse or keyboard. The other signals are to program the FPGA  from a USB pen drive connected to the USB-HID port (J2) when the JP1 programming mode jumper is set to "USB". 
In this FPGA tutorial, we only focus on the PS/2 interface of the onboard microcontroller for communication with a mouse. In this case, the microcontroller behaves like a PS/2 bus and a mouse that connected to the USB-HID port can use the two-wire (clock and data) serial bus (PS/2 protocol) to communicate with the FPGA as the host. The mouse sends clock and data signals to the FPGA when it is moved as shown in the following figure; otherwise, these signals are held high.
PS2 device to host timing diagram
The 11-bit word data includes a ‘0’ start bit, 8 bits of data (LSB first), an odd parity bit, and followed by a ‘1’ stop bit. Three 11-bit words are transferred from the mouse to the FPGA, as shown in the following figure.
Mouse data format to FPGA
The three-byte movement data of the mouse include a mouse status byte, X-direction byte, and Y-direction byte. The data are valid only at the falling edge of the clock signal. The X-direction and Y-direction bytes are used to display the relative coordinate of the mouse which moving to the right/left generates positive/negative X and moving to the top/bottom generates positive/negative Y. The XS and YS bits in the mouse status byte are used as the 'sign' bits of the X and Y. The higher the X and Y the faster the speed of the mouse; the XY and YY bits indicate the movement overflow. The L and R bits in the mouse status byte are used to indicate if the Left and Right button of the mouse is pressed. 
In short, the mouse always sends 33-bit data signals as formatted in the figure above to Basys 3 FPGA whenever the mouse is moved. The Left button click status is shown in the second bit of the data while the third bit indicates the Right button click status of the mouse. The X and Y coordinates are sent from the 13th-to-20th and 24th-to-30th bits of the 33-bit data, respectively.

In this FPGA tutorial, a Verilog code for interfacing a mouse with FPGA Basys 3 is presented. Every time the left button of the mouse is clicked, a 4-digit number that is displayed on the 7-segment display of the Basys 3 FPGA Board is increased by one. On the other hand, the right click button of the mouse decrements the displayed number by one. 

Verilog code for interfacing a mouse with Basys 3 FPGA board:

// fpga4student.com: FPGA projects, Verilog projects, VHDL projects
// FPGA tutorial: How to interface a mouse with Basys 3 FPGA 
// Verilog code for interfacing a mouse with the Basys 3 FPGA board 
module mouse_basys3_FPGA(
    input clock_100Mhz, // 100 Mhz clock source on Basys 3 FPGA
    input reset, // reset
    input Mouse_Data, // Mouse PS2 data
    input Mouse_Clk, // Mouse PS2 Clock
    output reg [3:0] Anode_Activate, // anode signals of the 7-segment LED display
    output reg [6:0] LED_out// cathode patterns of the 7-segment LED display
    );
    reg [5:0] Mouse_bits; // count number of bits receiving from the PS2 mouse 
    reg [26:0] one_second_counter; // counter for generating 1 second clock enable
    wire one_second_enable;// one second enable for counting numbers
    reg [15:0] displayed_number; // Number to be increased and decreased by the mouse 
    reg [3:0] LED_BCD;
 // Signals for displaying on 7-segment LED of Basys 3 FPGA 
    reg [20:0] refresh_counter; // the first 19-bit for creating 190Hz refresh rate
             // the other 2-bit for creating 4 LED-activating signals
    wire [1:0] LED_activating_counter; 
 // counting the number of bits receiving from the Mouse Data 
 // 33 bits to be received from the Mouse 
    always @(posedge Mouse_Clk or posedge reset)
    begin
        if(reset==1)
            Mouse_bits <= 0;
        else if(Mouse_bits <=31) 
            Mouse_bits <= Mouse_bits + 1;
        else 
             Mouse_bits <= 0;
    end
 // Increase/Decrease the number when pressing Left/Right Mouse 
    always @(negedge Mouse_Clk or posedge reset)
    begin
        if(reset)
            displayed_number <= 0;
        else begin
            if(Mouse_bits==1) begin
                if(Mouse_Data==1) // if The mouse is left clicked, increase the number 
                   displayed_number <= displayed_number + 1;
            end
            else if(Mouse_bits==2) begin
               if(Mouse_Data==1&&displayed_number>0)// if The mouse is right clicked, decrease the number 
                   displayed_number <= displayed_number - 1;
                end
        end 
    end    
     // refreshing the 4-digit 7-segment display on Basys 3 FPGA 
    always @(posedge clock_100Mhz or posedge reset)
    begin 
        if(reset==1)
            refresh_counter <= 0;
        else
            refresh_counter <= refresh_counter + 1;
    end 
    assign LED_activating_counter = refresh_counter[20:19];
    // anode activating signals for 4 LEDs
    // decoder to generate anode signals 
    always @(*)
    begin
        case(LED_activating_counter)
        2'b00: begin
            Anode_Activate = 4'b0111; 
            // activate LED1 and Deactivate LED2, LED3, LED4
            LED_BCD = displayed_number/1000;
            // the first digit of the 16-bit number
              end
        2'b01: begin
            Anode_Activate = 4'b1011; 
            // activate LED2 and Deactivate LED1, LED3, LED4
            LED_BCD = (displayed_number % 1000)/100;
            // the second digit of the 16-bit number
              end
        2'b10: begin
            Anode_Activate = 4'b1101; 
            // activate LED3 and Deactivate LED2, LED1, LED4
            LED_BCD = ((displayed_number % 1000)%100)/10;
            // the third digit of the 16-bit number
                end
        2'b11: begin
            Anode_Activate = 4'b1110; 
            // activate LED4 and Deactivate LED2, LED3, LED1
            LED_BCD = ((displayed_number % 1000)%100)%10;
            // the fourth digit of the 16-bit number    
               end
        endcase
    end
    // Cathode patterns of the 7-segment LED display 
    always @(*)
    begin
        case(LED_BCD)
        4'b0000: LED_out = 7'b0000001; // "0"     
        4'b0001: LED_out = 7'b1001111; // "1" 
        4'b0010: LED_out = 7'b0010010; // "2" 
        4'b0011: LED_out = 7'b0000110; // "3" 
        4'b0100: LED_out = 7'b1001100; // "4" 
        4'b0101: LED_out = 7'b0100100; // "5" 
        4'b0110: LED_out = 7'b0100000; // "6" 
        4'b0111: LED_out = 7'b0001111; // "7" 
        4'b1000: LED_out = 7'b0000000; // "8"     
        4'b1001: LED_out = 7'b0000100; // "9" 
        default: LED_out = 7'b0000001; // "0"
        endcase
    end
 endmodule

Pin constraint file for interfacing a mouse with the Basys 3 FPGA:

# fpga4student.com: FPGA projects, Verilog projects, VHDL projects
# FPGA tutorial: How to interface a mouse with Basys 3 FPGA 
# Verilog code for interfacing a mouse with the Basys 3 FPGA board  
##USB HID (PS/2)
 set_property PACKAGE_PIN C17 [get_ports Mouse_Clk]                        
     set_property IOSTANDARD LVCMOS33 [get_ports Mouse_Clk]
     set_property PULLUP true [get_ports Mouse_Clk]
 set_property PACKAGE_PIN B17 [get_ports Mouse_Data]                    
     set_property IOSTANDARD LVCMOS33 [get_ports Mouse_Data]    
     set_property PULLUP true [get_ports Mouse_Data]
# Clock signal
set_property PACKAGE_PIN W5 [get_ports clock_100Mhz]       
 set_property IOSTANDARD LVCMOS33 [get_ports clock_100Mhz]
set_property PACKAGE_PIN R2 [get_ports reset]     
 set_property IOSTANDARD LVCMOS33 [get_ports reset]
#seven-segment LED display
set_property PACKAGE_PIN W7 [get_ports {LED_out[6]}]                    
   set_property IOSTANDARD LVCMOS33 [get_ports {LED_out[6]}]
set_property PACKAGE_PIN W6 [get_ports {LED_out[5]}]                    
   set_property IOSTANDARD LVCMOS33 [get_ports {LED_out[5]}]
set_property PACKAGE_PIN U8 [get_ports {LED_out[4]}]                    
   set_property IOSTANDARD LVCMOS33 [get_ports {LED_out[4]}]
set_property PACKAGE_PIN V8 [get_ports {LED_out[3]}]                    
   set_property IOSTANDARD LVCMOS33 [get_ports {LED_out[3]}]
set_property PACKAGE_PIN U5 [get_ports {LED_out[2]}]                    
   set_property IOSTANDARD LVCMOS33 [get_ports {LED_out[2]}]
set_property PACKAGE_PIN V5 [get_ports {LED_out[1]}]                    
   set_property IOSTANDARD LVCMOS33 [get_ports {LED_out[1]}]
set_property PACKAGE_PIN U7 [get_ports {LED_out[0]}]                    
   set_property IOSTANDARD LVCMOS33 [get_ports {LED_out[0]}]
set_property PACKAGE_PIN U2 [get_ports {Anode_Activate[0]}]                    
   set_property IOSTANDARD LVCMOS33 [get_ports {Anode_Activate[0]}]
set_property PACKAGE_PIN U4 [get_ports {Anode_Activate[1]}]                    
   set_property IOSTANDARD LVCMOS33 [get_ports {Anode_Activate[1]}]
set_property PACKAGE_PIN V4 [get_ports {Anode_Activate[2]}]               
   set_property IOSTANDARD LVCMOS33 [get_ports {Anode_Activate[2]}]
set_property PACKAGE_PIN W4 [get_ports {Anode_Activate[3]}]          
   set_property IOSTANDARD LVCMOS33 [get_ports {Anode_Activate[3]}]

Video demo of the Verilog code for interfacing a mouse with Basys 3 FPGA:



Video demo of a wireless mouse interfacing with FPGA:


Download the whole Vivado project file: here.
Recommended FPGA projects for students:
Verilog VHDL Tool

4 comments:

  1. Hello, I've uploaded this onto my Basys3 board but it does not work for me. Do you have any recommendations on particular aspects I should be careful with?

    ReplyDelete
    Replies
    1. 1. Make sure you move the mouse while clicking.
      2. Make sure you reset the circuit before running. Reset=1 to reset the circuit, then reset = 0 for operation

      Delete
    2. It is also not working in my case. The display only shows 0.000, when i reset it to be 0.~~~, it still doesn't detect the mouse's displacement.

      Delete
    3. I just uploaded the whole Vivado project file which is demonstrated on FPGA in the video. You can download and try again.

      Delete