├── Basys3.xdc ├── README.md ├── ps2_mouse.v ├── ps2_signal.v ├── ps2_signal_map.v └── ps2_validator.v /Basys3.xdc: -------------------------------------------------------------------------------- 1 | ## This file is a general .xdc for the Basys3 rev B board 2 | ## To use it in a project: 3 | ## - uncomment the lines corresponding to used pins 4 | ## - rename the used ports (in each line, after get_ports) according to the top level signal names in the project 5 | 6 | ## Clock signal 7 | set_property PACKAGE_PIN W5 [get_ports clk] 8 | set_property IOSTANDARD LVCMOS33 [get_ports clk] 9 | create_clock -add -name sys_clk_pin -period 10.00 -waveform {0 5} [get_ports clk] 10 | 11 | ## Switches 12 | set_property PACKAGE_PIN V17 [get_ports {sw[0]}] 13 | set_property IOSTANDARD LVCMOS33 [get_ports {sw[0]}] 14 | set_property PACKAGE_PIN V16 [get_ports {sw[1]}] 15 | set_property IOSTANDARD LVCMOS33 [get_ports {sw[1]}] 16 | set_property PACKAGE_PIN W16 [get_ports {sw[2]}] 17 | set_property IOSTANDARD LVCMOS33 [get_ports {sw[2]}] 18 | set_property PACKAGE_PIN W17 [get_ports {sw[3]}] 19 | set_property IOSTANDARD LVCMOS33 [get_ports {sw[3]}] 20 | set_property PACKAGE_PIN W15 [get_ports {sw[4]}] 21 | set_property IOSTANDARD LVCMOS33 [get_ports {sw[4]}] 22 | set_property PACKAGE_PIN V15 [get_ports {sw[5]}] 23 | set_property IOSTANDARD LVCMOS33 [get_ports {sw[5]}] 24 | set_property PACKAGE_PIN W14 [get_ports {sw[6]}] 25 | set_property IOSTANDARD LVCMOS33 [get_ports {sw[6]}] 26 | set_property PACKAGE_PIN W13 [get_ports {sw[7]}] 27 | set_property IOSTANDARD LVCMOS33 [get_ports {sw[7]}] 28 | set_property PACKAGE_PIN V2 [get_ports {sw[8]}] 29 | set_property IOSTANDARD LVCMOS33 [get_ports {sw[8]}] 30 | set_property PACKAGE_PIN T3 [get_ports {sw[9]}] 31 | set_property IOSTANDARD LVCMOS33 [get_ports {sw[9]}] 32 | set_property PACKAGE_PIN T2 [get_ports {sw[10]}] 33 | set_property IOSTANDARD LVCMOS33 [get_ports {sw[10]}] 34 | set_property PACKAGE_PIN R3 [get_ports {sw[11]}] 35 | set_property IOSTANDARD LVCMOS33 [get_ports {sw[11]}] 36 | set_property PACKAGE_PIN W2 [get_ports {sw[12]}] 37 | set_property IOSTANDARD LVCMOS33 [get_ports {sw[12]}] 38 | set_property PACKAGE_PIN U1 [get_ports {sw[13]}] 39 | set_property IOSTANDARD LVCMOS33 [get_ports {sw[13]}] 40 | set_property PACKAGE_PIN T1 [get_ports {sw[14]}] 41 | set_property IOSTANDARD LVCMOS33 [get_ports {sw[14]}] 42 | set_property PACKAGE_PIN R2 [get_ports {sw[15]}] 43 | set_property IOSTANDARD LVCMOS33 [get_ports {sw[15]}] 44 | 45 | 46 | ## LEDs 47 | set_property PACKAGE_PIN U16 [get_ports {led[0]}] 48 | set_property IOSTANDARD LVCMOS33 [get_ports {led[0]}] 49 | set_property PACKAGE_PIN E19 [get_ports {led[1]}] 50 | set_property IOSTANDARD LVCMOS33 [get_ports {led[1]}] 51 | set_property PACKAGE_PIN U19 [get_ports {led[2]}] 52 | set_property IOSTANDARD LVCMOS33 [get_ports {led[2]}] 53 | set_property PACKAGE_PIN V19 [get_ports {led[3]}] 54 | set_property IOSTANDARD LVCMOS33 [get_ports {led[3]}] 55 | set_property PACKAGE_PIN W18 [get_ports {led[4]}] 56 | set_property IOSTANDARD LVCMOS33 [get_ports {led[4]}] 57 | set_property PACKAGE_PIN U15 [get_ports {led[5]}] 58 | set_property IOSTANDARD LVCMOS33 [get_ports {led[5]}] 59 | set_property PACKAGE_PIN U14 [get_ports {led[6]}] 60 | set_property IOSTANDARD LVCMOS33 [get_ports {led[6]}] 61 | set_property PACKAGE_PIN V14 [get_ports {led[7]}] 62 | set_property IOSTANDARD LVCMOS33 [get_ports {led[7]}] 63 | set_property PACKAGE_PIN V13 [get_ports {led[8]}] 64 | set_property IOSTANDARD LVCMOS33 [get_ports {led[8]}] 65 | set_property PACKAGE_PIN V3 [get_ports {led[9]}] 66 | set_property IOSTANDARD LVCMOS33 [get_ports {led[9]}] 67 | set_property PACKAGE_PIN W3 [get_ports {led[10]}] 68 | set_property IOSTANDARD LVCMOS33 [get_ports {led[10]}] 69 | set_property PACKAGE_PIN U3 [get_ports {led[11]}] 70 | set_property IOSTANDARD LVCMOS33 [get_ports {led[11]}] 71 | set_property PACKAGE_PIN P3 [get_ports {led[12]}] 72 | set_property IOSTANDARD LVCMOS33 [get_ports {led[12]}] 73 | set_property PACKAGE_PIN N3 [get_ports {led[13]}] 74 | set_property IOSTANDARD LVCMOS33 [get_ports {led[13]}] 75 | set_property PACKAGE_PIN P1 [get_ports {led[14]}] 76 | set_property IOSTANDARD LVCMOS33 [get_ports {led[14]}] 77 | set_property PACKAGE_PIN L1 [get_ports {led[15]}] 78 | set_property IOSTANDARD LVCMOS33 [get_ports {led[15]}] 79 | 80 | 81 | ##7 segment display 82 | set_property PACKAGE_PIN W7 [get_ports {seg[0]}] 83 | set_property IOSTANDARD LVCMOS33 [get_ports {seg[0]}] 84 | set_property PACKAGE_PIN W6 [get_ports {seg[1]}] 85 | set_property IOSTANDARD LVCMOS33 [get_ports {seg[1]}] 86 | set_property PACKAGE_PIN U8 [get_ports {seg[2]}] 87 | set_property IOSTANDARD LVCMOS33 [get_ports {seg[2]}] 88 | set_property PACKAGE_PIN V8 [get_ports {seg[3]}] 89 | set_property IOSTANDARD LVCMOS33 [get_ports {seg[3]}] 90 | set_property PACKAGE_PIN U5 [get_ports {seg[4]}] 91 | set_property IOSTANDARD LVCMOS33 [get_ports {seg[4]}] 92 | set_property PACKAGE_PIN V5 [get_ports {seg[5]}] 93 | set_property IOSTANDARD LVCMOS33 [get_ports {seg[5]}] 94 | set_property PACKAGE_PIN U7 [get_ports {seg[6]}] 95 | set_property IOSTANDARD LVCMOS33 [get_ports {seg[6]}] 96 | 97 | #set_property PACKAGE_PIN V7 [get_ports dp] 98 | #set_property IOSTANDARD LVCMOS33 [get_ports dp] 99 | 100 | set_property PACKAGE_PIN U2 [get_ports {an[0]}] 101 | set_property IOSTANDARD LVCMOS33 [get_ports {an[0]}] 102 | set_property PACKAGE_PIN U4 [get_ports {an[1]}] 103 | set_property IOSTANDARD LVCMOS33 [get_ports {an[1]}] 104 | set_property PACKAGE_PIN V4 [get_ports {an[2]}] 105 | set_property IOSTANDARD LVCMOS33 [get_ports {an[2]}] 106 | set_property PACKAGE_PIN W4 [get_ports {an[3]}] 107 | set_property IOSTANDARD LVCMOS33 [get_ports {an[3]}] 108 | 109 | 110 | ##Buttons 111 | #set_property PACKAGE_PIN U18 [get_ports btnC] 112 | #set_property IOSTANDARD LVCMOS33 [get_ports btnC] 113 | #set_property PACKAGE_PIN T18 [get_ports btnU] 114 | #set_property IOSTANDARD LVCMOS33 [get_ports btnU] 115 | #set_property PACKAGE_PIN W19 [get_ports btnL] 116 | #set_property IOSTANDARD LVCMOS33 [get_ports btnL] 117 | #set_property PACKAGE_PIN T17 [get_ports btnR] 118 | #set_property IOSTANDARD LVCMOS33 [get_ports btnR] 119 | #set_property PACKAGE_PIN U17 [get_ports btnD] 120 | #set_property IOSTANDARD LVCMOS33 [get_ports btnD] 121 | 122 | 123 | 124 | ##Pmod Header JA 125 | ##Sch name = JA1 126 | #set_property PACKAGE_PIN J1 [get_ports {JA[0]}] 127 | #set_property IOSTANDARD LVCMOS33 [get_ports {JA[0]}] 128 | ##Sch name = JA2 129 | #set_property PACKAGE_PIN L2 [get_ports {JA[1]}] 130 | #set_property IOSTANDARD LVCMOS33 [get_ports {JA[1]}] 131 | ##Sch name = JA3 132 | #set_property PACKAGE_PIN J2 [get_ports {JA[2]}] 133 | #set_property IOSTANDARD LVCMOS33 [get_ports {JA[2]}] 134 | ##Sch name = JA4 135 | #set_property PACKAGE_PIN G2 [get_ports {JA[3]}] 136 | #set_property IOSTANDARD LVCMOS33 [get_ports {JA[3]}] 137 | ##Sch name = JA7 138 | #set_property PACKAGE_PIN H1 [get_ports {JA[4]}] 139 | #set_property IOSTANDARD LVCMOS33 [get_ports {JA[4]}] 140 | ##Sch name = JA8 141 | #set_property PACKAGE_PIN K2 [get_ports {JA[5]}] 142 | #set_property IOSTANDARD LVCMOS33 [get_ports {JA[5]}] 143 | ##Sch name = JA9 144 | #set_property PACKAGE_PIN H2 [get_ports {JA[6]}] 145 | #set_property IOSTANDARD LVCMOS33 [get_ports {JA[6]}] 146 | ##Sch name = JA10 147 | #set_property PACKAGE_PIN G3 [get_ports {JA[7]}] 148 | #set_property IOSTANDARD LVCMOS33 [get_ports {JA[7]}] 149 | 150 | 151 | 152 | ##Pmod Header JB 153 | ##Sch name = JB1 154 | #set_property PACKAGE_PIN A14 [get_ports {JB[0]}] 155 | #set_property IOSTANDARD LVCMOS33 [get_ports {JB[0]}] 156 | ##Sch name = JB2 157 | #set_property PACKAGE_PIN A16 [get_ports {JB[1]}] 158 | #set_property IOSTANDARD LVCMOS33 [get_ports {JB[1]}] 159 | ##Sch name = JB3 160 | #set_property PACKAGE_PIN B15 [get_ports {JB[2]}] 161 | #set_property IOSTANDARD LVCMOS33 [get_ports {JB[2]}] 162 | ##Sch name = JB4 163 | #set_property PACKAGE_PIN B16 [get_ports {JB[3]}] 164 | #set_property IOSTANDARD LVCMOS33 [get_ports {JB[3]}] 165 | ##Sch name = JB7 166 | #set_property PACKAGE_PIN A15 [get_ports {JB[4]}] 167 | #set_property IOSTANDARD LVCMOS33 [get_ports {JB[4]}] 168 | ##Sch name = JB8 169 | #set_property PACKAGE_PIN A17 [get_ports {JB[5]}] 170 | #set_property IOSTANDARD LVCMOS33 [get_ports {JB[5]}] 171 | ##Sch name = JB9 172 | #set_property PACKAGE_PIN C15 [get_ports {JB[6]}] 173 | #set_property IOSTANDARD LVCMOS33 [get_ports {JB[6]}] 174 | ##Sch name = JB10 175 | #set_property PACKAGE_PIN C16 [get_ports {JB[7]}] 176 | #set_property IOSTANDARD LVCMOS33 [get_ports {JB[7]}] 177 | 178 | 179 | 180 | ##Pmod Header JC 181 | ##Sch name = JC1 182 | #set_property PACKAGE_PIN K17 [get_ports {JC[0]}] 183 | #set_property IOSTANDARD LVCMOS33 [get_ports {JC[0]}] 184 | ##Sch name = JC2 185 | #set_property PACKAGE_PIN M18 [get_ports {JC[1]}] 186 | #set_property IOSTANDARD LVCMOS33 [get_ports {JC[1]}] 187 | ##Sch name = JC3 188 | #set_property PACKAGE_PIN N17 [get_ports {JC[2]}] 189 | #set_property IOSTANDARD LVCMOS33 [get_ports {JC[2]}] 190 | ##Sch name = JC4 191 | #set_property PACKAGE_PIN P18 [get_ports {JC[3]}] 192 | #set_property IOSTANDARD LVCMOS33 [get_ports {JC[3]}] 193 | ##Sch name = JC7 194 | #set_property PACKAGE_PIN L17 [get_ports {JC[4]}] 195 | #set_property IOSTANDARD LVCMOS33 [get_ports {JC[4]}] 196 | ##Sch name = JC8 197 | #set_property PACKAGE_PIN M19 [get_ports {JC[5]}] 198 | #set_property IOSTANDARD LVCMOS33 [get_ports {JC[5]}] 199 | ##Sch name = JC9 200 | #set_property PACKAGE_PIN P17 [get_ports {JC[6]}] 201 | #set_property IOSTANDARD LVCMOS33 [get_ports {JC[6]}] 202 | ##Sch name = JC10 203 | #set_property PACKAGE_PIN R18 [get_ports {JC[7]}] 204 | #set_property IOSTANDARD LVCMOS33 [get_ports {JC[7]}] 205 | 206 | 207 | ##Pmod Header JXADC 208 | ##Sch name = XA1_P 209 | #set_property PACKAGE_PIN J3 [get_ports {JXADC[0]}] 210 | #set_property IOSTANDARD LVCMOS33 [get_ports {JXADC[0]}] 211 | ##Sch name = XA2_P 212 | #set_property PACKAGE_PIN L3 [get_ports {JXADC[1]}] 213 | #set_property IOSTANDARD LVCMOS33 [get_ports {JXADC[1]}] 214 | ##Sch name = XA3_P 215 | #set_property PACKAGE_PIN M2 [get_ports {JXADC[2]}] 216 | #set_property IOSTANDARD LVCMOS33 [get_ports {JXADC[2]}] 217 | ##Sch name = XA4_P 218 | #set_property PACKAGE_PIN N2 [get_ports {JXADC[3]}] 219 | #set_property IOSTANDARD LVCMOS33 [get_ports {JXADC[3]}] 220 | ##Sch name = XA1_N 221 | #set_property PACKAGE_PIN K3 [get_ports {JXADC[4]}] 222 | #set_property IOSTANDARD LVCMOS33 [get_ports {JXADC[4]}] 223 | ##Sch name = XA2_N 224 | #set_property PACKAGE_PIN M3 [get_ports {JXADC[5]}] 225 | #set_property IOSTANDARD LVCMOS33 [get_ports {JXADC[5]}] 226 | ##Sch name = XA3_N 227 | #set_property PACKAGE_PIN M1 [get_ports {JXADC[6]}] 228 | #set_property IOSTANDARD LVCMOS33 [get_ports {JXADC[6]}] 229 | ##Sch name = XA4_N 230 | #set_property PACKAGE_PIN N1 [get_ports {JXADC[7]}] 231 | #set_property IOSTANDARD LVCMOS33 [get_ports {JXADC[7]}] 232 | 233 | 234 | 235 | ##VGA Connector 236 | #set_property PACKAGE_PIN G19 [get_ports {vgaRed[0]}] 237 | #set_property IOSTANDARD LVCMOS33 [get_ports {vgaRed[0]}] 238 | #set_property PACKAGE_PIN H19 [get_ports {vgaRed[1]}] 239 | #set_property IOSTANDARD LVCMOS33 [get_ports {vgaRed[1]}] 240 | #set_property PACKAGE_PIN J19 [get_ports {vgaRed[2]}] 241 | #set_property IOSTANDARD LVCMOS33 [get_ports {vgaRed[2]}] 242 | #set_property PACKAGE_PIN N19 [get_ports {vgaRed[3]}] 243 | #set_property IOSTANDARD LVCMOS33 [get_ports {vgaRed[3]}] 244 | #set_property PACKAGE_PIN N18 [get_ports {vgaBlue[0]}] 245 | #set_property IOSTANDARD LVCMOS33 [get_ports {vgaBlue[0]}] 246 | #set_property PACKAGE_PIN L18 [get_ports {vgaBlue[1]}] 247 | #set_property IOSTANDARD LVCMOS33 [get_ports {vgaBlue[1]}] 248 | #set_property PACKAGE_PIN K18 [get_ports {vgaBlue[2]}] 249 | #set_property IOSTANDARD LVCMOS33 [get_ports {vgaBlue[2]}] 250 | #set_property PACKAGE_PIN J18 [get_ports {vgaBlue[3]}] 251 | #set_property IOSTANDARD LVCMOS33 [get_ports {vgaBlue[3]}] 252 | #set_property PACKAGE_PIN J17 [get_ports {vgaGreen[0]}] 253 | #set_property IOSTANDARD LVCMOS33 [get_ports {vgaGreen[0]}] 254 | #set_property PACKAGE_PIN H17 [get_ports {vgaGreen[1]}] 255 | #set_property IOSTANDARD LVCMOS33 [get_ports {vgaGreen[1]}] 256 | #set_property PACKAGE_PIN G17 [get_ports {vgaGreen[2]}] 257 | #set_property IOSTANDARD LVCMOS33 [get_ports {vgaGreen[2]}] 258 | #set_property PACKAGE_PIN D17 [get_ports {vgaGreen[3]}] 259 | #set_property IOSTANDARD LVCMOS33 [get_ports {vgaGreen[3]}] 260 | #set_property PACKAGE_PIN P19 [get_ports Hsync] 261 | #set_property IOSTANDARD LVCMOS33 [get_ports Hsync] 262 | #set_property PACKAGE_PIN R19 [get_ports Vsync] 263 | #set_property IOSTANDARD LVCMOS33 [get_ports Vsync] 264 | 265 | 266 | ##USB-RS232 Interface 267 | #set_property PACKAGE_PIN B18 [get_ports RsRx] 268 | #set_property IOSTANDARD LVCMOS33 [get_ports RsRx] 269 | #set_property PACKAGE_PIN A18 [get_ports RsTx] 270 | #set_property IOSTANDARD LVCMOS33 [get_ports RsTx] 271 | 272 | 273 | ##USB HID (PS/2) 274 | set_property PACKAGE_PIN C17 [get_ports PS2Clk] 275 | set_property IOSTANDARD LVCMOS33 [get_ports PS2Clk] 276 | set_property PULLUP true [get_ports PS2Clk] 277 | set_property PACKAGE_PIN B17 [get_ports PS2Data] 278 | set_property IOSTANDARD LVCMOS33 [get_ports PS2Data] 279 | set_property PULLUP true [get_ports PS2Data] 280 | 281 | 282 | ##Quad SPI Flash 283 | ##Note that CCLK_0 cannot be placed in 7 series devices. You can access it using the 284 | ##STARTUPE2 primitive. 285 | #set_property PACKAGE_PIN D18 [get_ports {QspiDB[0]}] 286 | #set_property IOSTANDARD LVCMOS33 [get_ports {QspiDB[0]}] 287 | #set_property PACKAGE_PIN D19 [get_ports {QspiDB[1]}] 288 | #set_property IOSTANDARD LVCMOS33 [get_ports {QspiDB[1]}] 289 | #set_property PACKAGE_PIN G18 [get_ports {QspiDB[2]}] 290 | #set_property IOSTANDARD LVCMOS33 [get_ports {QspiDB[2]}] 291 | #set_property PACKAGE_PIN F18 [get_ports {QspiDB[3]}] 292 | #set_property IOSTANDARD LVCMOS33 [get_ports {QspiDB[3]}] 293 | #set_property PACKAGE_PIN K19 [get_ports QspiCSn] 294 | #set_property IOSTANDARD LVCMOS33 [get_ports QspiCSn] 295 | 296 | 297 | ## Configuration options, can be used for all designs 298 | set_property CONFIG_VOLTAGE 3.3 [current_design] 299 | set_property CFGBVS VCCO [current_design] 300 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # FPGA Mouse Controller - Built on Basys3 2 | A simple interface for controlling the Basys3 FPGA via mouse using Verilog (created and tested in Vivado) 3 | 4 | ## How it works 5 | - Step 1) Take in the PS2 clock and data signals 6 | - Step 2) Synchronize the PS2 clock with our 100MHz base clock 7 | - Step 3) Use a double-buffered FIFO to de-serialize messages from the mouse 8 | - Step 4) Extract the 44-bit message into 4 11-bit words (assumes the "IntelliMouse" protocol is in use) 9 | - Step 5) Validate each word using start, stop, and parity bits (combinational) 10 | - Step 6) Map the output signals to bit patterns in the messages 11 | - Step 7) Output a `valid` signal when data is `ready` and `valid` 12 | ---- 13 | 14 | ## How to use it 15 | You should be able to import the four files into your project and instantiate a `ps2_mouse` module. 16 | 17 | Simply feed the `ps2_mouse` module the following signals: 18 | 19 | - 100MHz clock (`i_clk`) 20 | - Reset (`i_reset`) 21 | - PS2 Clock (`i_PS2Clk`) 22 | - PS2 Data (`i_PS2Data`) 23 | 24 | You will get the following signals in return: 25 | 26 | - x movement (`o_x`) 27 | - y movement (`o_y`) 28 | - x direction (`o_x_sign`) 29 | - y direction (`o_y_sign`) 30 | - x overflow (`o_x_ov`) 31 | - y overflow (`o_y_ov`) 32 | - left click (`o_l_click`) 33 | - right click (`o_r_click`) 34 | - valid signal (`o_valid`) 35 | ---- 36 | 37 | ## Notes 38 | The top level `o_valid` signal is a logical AND between the `valid` signal coming from the `ps2_validator` and the `ready` signal coming from the `ps2_signal`. This means you will only ever see a new *valid* signal when new data arrives and it is properly validated. 39 | 40 | According to the Basys3 reference manual, you can expect a full 4-packet message about once every 50ms. In my testing with a digital logic analyzer, however, messages were coming in with a period of about 10ms. Just something to keep in mind (YMMV). The output is magnitude of movement (velocity?) and the sign can be treated as direction (i.e. when `o_x_sign` is a 0, the mouse is moving in to the right. When `o_y_sign` is 1, it is moving downward). 41 | -------------------------------------------------------------------------------- /ps2_mouse.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | 3 | 4 | module ps2_mouse( 5 | input wire i_clk, 6 | input wire i_reset, 7 | input wire i_PS2Data, 8 | input wire i_PS2Clk, 9 | output wire [7:0] o_x, 10 | output wire o_x_ov, 11 | output wire o_x_sign, 12 | output wire [7:0] o_y, 13 | output wire o_y_ov, 14 | output wire o_y_sign, 15 | output wire o_r_click, 16 | output wire o_l_click, 17 | output wire o_valid 18 | ); 19 | // Top level module that takes in the raw PS2 signal (clock and data) and 20 | // transforms them into actionable signals. 21 | 22 | 23 | wire [10:0] word1, word2, word3, word4; 24 | wire [7:0] signal1, signal2, signal3, signal4; 25 | wire valid, ready; 26 | 27 | assign o_valid = ready && valid; 28 | 29 | // signal processing -> validation -> map to output 30 | //---------------------------------------------------------------------- 31 | ps2_signal ps2_signal( 32 | .i_clk(i_clk), 33 | .i_reset(i_reset), 34 | .i_PS2Clk(i_PS2Clk), 35 | .i_PS2Data(i_PS2Data), 36 | .o_word1(word1), 37 | .o_word2(word2), 38 | .o_word3(word3), 39 | .o_word4(word4), 40 | .o_ready(ready) 41 | ); 42 | //---------------------------------------------------------------------- 43 | ps2_validator ps2_validator( 44 | .i_word1(word1), 45 | .i_word2(word2), 46 | .i_word3(word3), 47 | .i_word4(word4), 48 | .o_signal1(signal1), 49 | .o_signal2(signal2), 50 | .o_signal3(signal3), 51 | .o_signal4(signal4), 52 | .o_valid(valid) 53 | ); 54 | 55 | //---------------------------------------------------------------------- 56 | ps2_mouse_map ps2_mouse_map( 57 | .i_clk(i_clk), 58 | .i_reset(i_reset), 59 | .i_signal1(signal1), 60 | .i_signal2(signal2), 61 | .i_signal3(signal3), 62 | .i_signal4(signal4), 63 | .o_x(o_x), 64 | .o_y(o_y), 65 | .o_x_overflow(o_x_ov), 66 | .o_y_overflow(o_y_ov), 67 | .o_x_sign(o_x_sign), 68 | .o_y_sign(o_y_sign), 69 | .o_l_click(o_l_click), 70 | .o_r_click(o_r_click) 71 | ); 72 | endmodule 73 | -------------------------------------------------------------------------------- /ps2_signal.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | 3 | module ps2_signal( 4 | input wire i_clk, 5 | input wire i_reset, 6 | input wire i_PS2Clk, 7 | input wire i_PS2Data, 8 | output wire [10:0] o_word1, 9 | output wire [10:0] o_word2, 10 | output wire [10:0] o_word3, 11 | output wire [10:0] o_word4, 12 | output wire o_ready 13 | ); 14 | // To avoid crossing clock domains, we detect the negative edge of the PS2Clk - 15 | // by keeping track of it in a 2-bit state variable. A negative edge has 16 | // occurred if and only if the state variable equals 2'b10. Interestingly 17 | // (perhaps), you can see in the digits themselves how this gives us the 18 | // negative edge. Consider the "wave form": 0/1\0/1\0/1\... 19 | 20 | 21 | reg [43:0] fifo; 22 | reg [43:0] buffer; 23 | reg [5:0] counter; 24 | reg [1:0] PS2Clk_sync; 25 | reg ready; 26 | reg PS2Data; 27 | wire PS2Clk_negedge; 28 | 29 | assign o_word1 = fifo[33 +: 11]; 30 | assign o_word2 = fifo[22 +: 11]; 31 | assign o_word3 = fifo[11 +: 11]; 32 | assign o_word4 = fifo[0 +: 11]; 33 | assign o_ready = ready; 34 | assign PS2Clk_negedge = (PS2Clk_sync == 2'b10); 35 | 36 | initial 37 | begin 38 | fifo <= 44'b0; 39 | buffer <= 44'b0; 40 | counter <= 6'b0; 41 | PS2Clk_sync <= 2'b1; 42 | ready <= 1'b0; 43 | PS2Data <= 1'b0; 44 | end // initial begin 45 | 46 | 47 | always @(posedge i_clk) 48 | // Enter Base Clock 49 | begin 50 | if(i_reset) 51 | // Provide a nice default start 52 | begin 53 | fifo <= 44'b0; 54 | buffer <= 44'b0; 55 | counter <= 6'b0; 56 | ready <= 1'b0; 57 | PS2Clk_sync <= 2'b1; 58 | PS2Data <= 1'b0; 59 | end 60 | else 61 | begin 62 | // Sync the PS2Clk with our Base Clock 63 | PS2Clk_sync <= {PS2Clk_sync[0], i_PS2Clk}; 64 | PS2Data <= i_PS2Data; 65 | 66 | if(PS2Clk_negedge) 67 | // Negative edge => Data is ready! 68 | begin 69 | buffer <= {buffer, PS2Data}; 70 | counter <= counter + 6'b1; 71 | end 72 | 73 | if(counter == 6'd44) 74 | // Counter==44 => Buffer is full! 75 | begin 76 | fifo <= buffer; 77 | buffer <= 44'b0; 78 | counter <= 6'b0; 79 | ready <= 1'b1; 80 | end 81 | else 82 | // Counter!=44 => (!ready && clear(FIFO)) 83 | begin 84 | ready <= 1'b0; 85 | fifo <= 44'b0; 86 | end 87 | end 88 | end 89 | endmodule 90 | -------------------------------------------------------------------------------- /ps2_signal_map.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | 3 | module ps2_mouse_map( 4 | input wire i_clk, 5 | input wire i_reset, 6 | input wire [7:0] i_signal1, 7 | input wire [7:0] i_signal2, 8 | input wire [7:0] i_signal3, 9 | input wire [7:0] i_signal4, 10 | output wire [7:0] o_x, 11 | output wire [7:0] o_y, 12 | output wire o_x_sign, 13 | output wire o_y_sign, 14 | output wire o_l_click, 15 | output wire o_r_click, 16 | output wire o_x_overflow, 17 | output wire o_y_overflow 18 | ); 19 | // This module takes the 8-bit words (after they have been validated) and 20 | // converts them into cohesive signals that can be operated on. Output names 21 | // are indicative of the mappings. Note that other signals of importance may 22 | // not be accounted for here. Namely, the Microsoft Intellimouse type 23 | // extension for supporting a scroll wheel mouse. This may be added in the 24 | // future (feel free to open a PR). 25 | 26 | assign o_x = i_signal2; 27 | assign o_y = i_signal3; 28 | assign {o_x_overflow, o_y_overflow} = i_signal1[1:0]; 29 | assign {o_x_sign, o_y_sign} = i_signal1[3:2]; 30 | assign {o_l_click, o_r_click} = i_signal1[7:6]; 31 | endmodule 32 | -------------------------------------------------------------------------------- /ps2_validator.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | 3 | module ps2_validator( 4 | input wire [10:0] i_word1, 5 | input wire [10:0] i_word2, 6 | input wire [10:0] i_word3, 7 | input wire [10:0] i_word4, 8 | output wire [7:0] o_signal1, 9 | output wire [7:0] o_signal2, 10 | output wire [7:0] o_signal3, 11 | output wire [7:0] o_signal4, 12 | output wire o_valid 13 | ); 14 | // Provides (imperfect) validation of the PS2 signal. This is done by 15 | // checking for parity and ensuring the start and stop bits are correct. If 16 | // either of these cases fail to occur, the 'valid' output will be 0. Note 17 | // that this is entirely combinational. 18 | 19 | 20 | wire parity1, parity2, parity3, parity4, parity; 21 | wire start1, start2, start3, start4, start; 22 | wire stop1, stop2, stop3, stop4, stop; 23 | wire valid1, valid2, valid3, valid4; 24 | 25 | // Separate packets into segments 26 | assign {start1, o_signal1, parity1, stop1} = i_word1; 27 | assign {start2, o_signal2, parity2, stop2} = i_word2; 28 | assign {start3, o_signal3, parity3, stop3} = i_word3; 29 | assign {start4, o_signal4, parity4, stop4} = i_word4; 30 | 31 | // XNOR words together and compare to parity bit 32 | assign valid1 = ~^o_signal1 == parity1; 33 | assign valid2 = ~^o_signal2 == parity2; 34 | assign valid3 = ~^o_signal3 == parity3; 35 | assign valid4 = ~^o_signal4 == parity4; 36 | 37 | assign parity = valid1 && valid2 && valid3 && valid4; 38 | assign start = (!start1 && !start2 && !start3 && !start4); 39 | assign stop = (stop1 && stop2 && stop3 && stop4); 40 | assign o_valid = (start && stop && parity); 41 | 42 | endmodule 43 | --------------------------------------------------------------------------------