§ Описание и зависимости

Код контроллера требует наличия модуля kb.v.
Модуль принимает на вход данные от контроллера клавиатуры, так как использует тот же протокол передачи. При запуске, мыши отсылается код F4 через PS/2, активируя ее работу, и принимает пакеты по 3 байта, формируя (x,y) координаты. С помощью (xmax,ymax) можно задать правую и нижнюю границу, за которую указатель мыши выйти не может. Если их опустить, то по умолчанию будет принято значение (640,480) в качестве размера окна.

§ TOP-модуль

wire [11:0] x, y;
wire [ 2:0] btn;
wire        recv;

mouse M1
(
    .clock   (clock_25),
    .reset_n (reset_n),
    .xmax    (640),
    .ymax    (480),
    .x       (x),
    .y       (y),
    .ps_clk  (PS2_CLK2),
    .cmd     (kb_cmd),
    .dat     (kb_dat),
    .ready   (kb_ready),
    .hit     (kb_hit),
    .kbd     (kb_kbd),
    .btn     (btn),
    .recv    (recv)
);

§ Код

// https://wiki.osdev.org/PS/2_Mouse
// -----------------------------------------------------------------------------
module mouse
(
    input               clock,      // 25 MHZ
    input               reset_n,    // =0 Сброс
    // --------------------
    inout               ps_clk,     // Входящие данные от PS2_CLK
    output reg          cmd,        // Отправка команды на мышь
    output reg  [ 7:0]  dat,        // Что отправлять
    input               ready,      // Ждать готовности
    input               hit,        // Ответ от мыши
    input       [ 7:0]  kbd,        // Данные от мыши
    // --------------------
    output reg  [11:0]  x,          // Координата X
    output reg  [11:0]  y,          // Координата Y
    output reg  [ 2:0]  btn,        // Кнопки мыши
    output reg          recv,       // =1 Принятые данные
    // --------------------
    input       [11:0]  xmax,       // Если 0=639 (максимум X)
    input       [11:0]  ymax        // Если 0=479 (максимум Y)
);

// Регистры
reg [ 1:0] t;
reg [ 1:0] rc;
reg [23:0] sr;
reg [15:0] tm;

// Границы окна
wire [11:0] xm = xmax ? xmax - 1 : 639;
wire [11:0] ym = ymax ? ymax - 1 : 479;

// Следующие принятые данные
wire [23:0] isr   = {kbd, sr[23:8]};
wire [11:0] xnext = x + {{4{isr[4]}}, isr[15:8]};
wire [11:0] ynext = y - {{4{isr[5]}}, isr[23:16]};

always @(posedge clock)
if (reset_n) begin

    recv <= 0;

    // Код активации мыши в работу
    case (t)
    0: begin t <= ready ? 1 : 0; end
    1: begin cmd <= 1; t <= 2; dat <= 8'hF4; end
    2: begin cmd <= 0; end
    endcase

    // Отметить что ранее принятые данные невалидны
    if (tm == 16'hFFFE) rc <= 0;

    // Таймаут CLK=1 приема данных 2.6 мс
    tm <= ps_clk ? (&tm ? tm : tm + 1) : 0;

    // Прием данных
    if (hit) begin

        // Если были приняты все 3 байта из потока
        if (rc == 2) begin

            x    <= xnext[11] ? 0 : (xnext > xm ? xm : xnext);
            y    <= ynext[11] ? 0 : (ynext > ym ? ym : ynext);
            btn  <= isr[2:0];
            recv <= 1;

        end

        sr <= isr;
        rc <= rc == 2 ? 0 : rc + 1;

    end

end else begin

    t  <= 0;
    rc <= 0;
    x  <= (xmax >> 1);
    y  <= (ymax >> 1);

end

endmodule