Mouse data packet format
Mouse Initialization
PS2 send data
The t r I-c and t r I-d signals are enable signals that control the tri-state buffers. when they are asserted, the corresponding ps2c-out and ps2d-out signals will be routed to the output ports.
Filter and descent Edge DetectionProgram:
// Body // ============================================ ==================/// filter and falling-edge tick generation for ps2c // ================ ========================================================== always @ (posedge CLK, posedge reset) if (reset) Begin filter_reg <= 0; f_ps2c_reg <= 0; end else begin filter_reg <= filter_next; else <= f_ps2c_next; end assign filter_next = {ps2c, filter_reg [7:1]}; assign f_ps2c_next = (filter_r Eg = 8 'b11111111 )? 1 'b1: (filter_reg = 8' b00000000 )? 1 'b0: f_ps2c_reg; assign fall_edge = f_ps2c_reg &~ F_ps2c_next;
Mouse transmission data module
CodeAs follows:
// Listing 10.1 module ps2_tx (input wire CLK, reset, input wire wr_ps2, input wire [] din, inout wire ps2d, ps2c, output Reg tx_idle, tx_done_tick ); // symbolic State declaration localparam [2: 0] idle = 3 'b000, RTS = 3 'b001, start = 3 'b010, Data = 3 'b011, stop = 3 'b100; // signal declaration Reg [2: 0] state_reg, state_next; Reg [7: 0] filter_reg; wire [7: 0] filter_next; Reg f_ps2c_reg; wire f_ps 2c_next; Reg [] n_reg, n_next; Reg [] B _reg, B _next; Reg [] c_reg, c_next; wire par, fall_edge; Reg ps2c_out, ps2d_out; Reg tri_c, tri_d; // body // ============================================ ==================/// filter and falling-edge tick generation for ps2c // ================ ========================================================== always @ (posedge CLK, posedge reset) if (reset) Begin filter_reg <= 0; f_ps2c_reg <= 0; End else begin filter_reg <= filter_next; begin <= f_ps2c_next; end assign filter_next = {ps2c, filter_reg [7]}; assign f_ps2c_next = (filter_reg = 8 'records )? 1 'b1: (filter_reg = 8' b00000000 )? 1 'b0: f_ps2c_reg; assign fall_edge = f_ps2c_reg &~ F_ps2c_next; // ================================================ ==============/// fsmd // ================================= ======================================/// fsmd State & Data Registers always @ (posedge CLK, posedge reset) if (reset) Begin state_reg <= idle; c_reg <= 0; n_reg <= 0; B _reg <= 0; end else begin state_reg <= state_next; c_reg <= c_next; n_reg <= n_next; B _reg <= B _next; end // odd parity bit assign par = ~ (^ Din); // fsmd next-state logic always @ * begin state_next = state_reg; c_next = c_reg; n_next = n_reg; B _next = B _reg; tx_done_tick = 1' B0; ps2c_out = 1' B1; ps2d_out = 1' B1; tri_c = 1' B0; tri_d = 1' B0; tx_idle = 1' B0; Case (state_reg) Idle: begin tx_idle = 1 'b1; If (wr_ps2) Begin B _next = {Par, DIN}; c_next = 13 'h1fff; // 2 ^ 13-1 to delay 164us state_next = RTS; end end RTS: // request to send beg In ps2c_out = 1' B0; tri_c = 1' B1; c_next = c_reg-1; if (c_reg = 0) // FPGA lowers ps2c 164us state_next = start; end start: // assert start bit PS2 clock line is disabled and the data line is set to 1 begin // The mouse now take over and generates a clock signal over the ps2c line ps2d_out = 1 'b0; tri_d = 1 'b1; If (fall_edge) Begin n_next = 4' H8; state_next = data; end data: // 8 Data + 1 parity begi N ps2d_out = B _reg [0]; tri_d = 1 'b1; If (fall_edge) Begin B _next = {1 'b0, B _reg [8:1]}; If (n_reg = 0) state_next = stop; else n_next = n_reg-1; end stop: // assume floating high for ps2d if (fall_edge) Begin state_next = idle; tx_done_tick = 1 'b1; end endcase end // tri-state buffers assign ps2c = (tri_c )? Ps2c_out: 1 'bz; assign ps2d = (tri_d )? Ps2d_out: 1 'bz; endmodule
PS2 reception
We use the TX-idle and RX-en signals to coordinate the transmitting and operating ing operations. priority is given to the transmitting operation. when the transmitting subsystem is in operation, the TX-idle signal is deasserted, which, in turn, disables the processing subsystem. the processing subsystem can process input only when the transmitting subsystem is idle.
PS2 three-state input and output module
Code:
// Listing 10.2 module ps2_rxtx (input wire CLK, reset, input wire wr_ps2, inout wire ps2d, ps2c, input wire [] din, output wire rx_done_tick, tx_done_tick, output wire [7:0] dout); // signal declaration wire tx_idle; // body // instantiate PS2 receiver ps2_rx ps2_rx_unit (. CLK (CLK ),. reset (reset ),. rx_en (tx_idle ),. ps2d (ps2d ),. ps2c (ps2c ),. rx_done_tick (rx_done_tick ),. dout (dout); // instantiate PS2 transmitter ps2_tx ps2_tx_unit (. CLK (CLK ),. reset (reset ),. wr_ps2 (wr_ps2 ),. din (DIN ),. ps2d (ps2d ),. ps2c (ps2c ),. tx_idle (tx_idle ),. tx_done_tick (tx_done_tick); endmodule
PS2 mouse Interface
Code:
// Listing 10.4 module mouse (input wire CLK, reset, inout wire ps2d, ps2c, output wire [] XM, ym, output wire [] btnm, output Reg m_done_tick ); // constant declaration localparam STRM = 8 'hf4; // stream command F4 // symbolic State declaration localparam [] init1 = 3 'b000, init2 = 3 'b001, init3 = 3 'b010, pack1 = 3' b011, pack2 = 3' B100, pack3 = 3' b101, done = 3' b110; // signal declaration Reg [] state_reg, state_next; wire [] rx_data; Reg wr_ps2; wire rx_done_tick, tx_done_tick; Reg [] x_reg, y_reg, x_next, y_next; Reg [] btn_reg, btn_next; // body // instantiation ps2_rxtx ps2_unit (. 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); // body // fsmd state and data registers always @ (posedge CLK, posedge reset) if (reset) Begin state_reg <= init1; x_reg <= 0; y_reg <= 0; btn_reg <= 0; end else begin state_reg <= state_next; x_reg <= x_next; y_reg <= y_next; btn_reg <= btn_next; end // fsmd next-state logic always @ * begin state_next = state_reg; wr_ps2 = 1' B0; m_done_tick = 1' B0; x_next = x_reg; y_next = y_reg; btn_next = btn_reg; case (state_reg) init1: Begin wr_ps2 = 1 'b1; state_next = init2; end init2: // wait for send to complete if (tx_done_tick) state_next = init3; init3: // wait for acknowledge packet if (rx_done_tick) state_next = pack1; pack1: // wait for 1st data packet if (rx_done_tick) Begin state_next = pack2; y_next [8] = rx_data [5]; x_next [8] = rx_data [4]; btn_next = rx_data [2: 0]; end pack2: // wait for 2nd data packet if (rx_done_tick) Begin state_next = pack3; x_next [7:0] = rx_data; end pack3: // wait for 3rd data packet if (rx_done_tick) begin state_next = done; y_next [7:0] = rx_data; end done: Begin m_done_tick = 1 'b1; state_next = pack1; end endcase end // output assign XM = x_reg; assign ym = y_reg; assign btnm = btn_reg; endmodule
Experiment: control the led with the mouse
Code:
// Listing 10.5 module mouse_led (input wire CLK, reset, inout wire ps2d, ps2c, output Reg [] led); // signal declaration Reg [] p_reg; wire [] p_next; wire [] XM; wire [] btnm; wire m_done_tick; // body // instantiation mouse mouse_unit (. CLK (CLK ),. reset (reset ),. ps2d (ps2d ),. ps2c (ps2c ),. XM (XM ),. ym (),. btnm (btnm ),. m_done_tick (m_done_tick); // counter always @ (posedge CLK, posed GE reset) if (reset) p_reg <= 0; else p_reg <= p_next; assign p_next = (~ M_done_tick )? P_reg: // No activity (btnm [0])? 10'b0: // left button (btnm [1])? 10 'h3ff: // right button p_reg + {XM [8], xm}; // X movement always @ * case (p_reg []) 3 'b000: led = 8 'b0000000; 3 'b001: LED = 8 'b0000000; 3 'b010: LED = 8 'b00100000; 3 'b011: LED = 8 'b00010000; 3 'b100: led = 8'b00001000; 3 'b101: LED = 8' b00000100; 3 'b110: LED = 8' b00000010; default: LED = 8' b00000001; endcaseendmodule