You are an expert Verilog hardware designer working on a complete FPGA or ASIC project. You are given the full source code of a Verilog project. One of the modules in the project is incomplete — its implementation is missing and marked with:

// >>> Module Implementation Begin

// <<< Module Implementation End

Your task is to complete the missing implementation so that the entire project functions correctly. You must infer what the missing module or logic is supposed to do by analyzing the rest of the codebase: module names, signal connections, instantiations, comments, and usage patterns.

Follow these rules:

1. Only generate Verilog code to go between the `// >>> Module Implementation Begin` and `// <<< Module Implementation End` comments.
2. Use Verilog-2001 syntax. Ensure the code is synthesizable.
3. Assume the goal is a working, integrated hardware design — your code must make the whole system function as intended.
4. Analyze the naming, I/O ports, and how the module is instantiated or used in other parts of the project.
5. Implement correct behavior based on design context. Do not guess randomly — reason it out.
6. Avoid vendor-specific features unless explicitly required.
7. Do not output comments, explanation, or anything outside the required code region unless explicitly asked.

Your output should contain **only the Verilog code** that fits inside the marked region.

/*
 * Copyright (c) 2024 Your Name
 * SPDX-License-Identifier: Apache-2.0
 */

`default_nettype none

module tt_um_benpayne_ps2_decoder (
    input  wire [7:0] ui_in,    // Dedicated inputs
    output wire [7:0] uo_out,   // Dedicated outputs
    input  wire [7:0] uio_in,   // IOs: Input path
    output wire [7:0] uio_out,  // IOs: Output path
    output wire [7:0] uio_oe,   // IOs: Enable path (active high: 0=input, 1=output)
    input  wire       ena,      // always 1 when the design is powered, so you can ignore it
    input  wire       clk,      // clock
    input  wire       rst_n     // reset_n - low to reset
);

  // All output pins must be assigned. If not used, assign to 0.
  assign uio_oe = cs ? 8'b11111111 : 8'b00000000; // [uio_out[7:0] are always outputs
  assign uo_out[7:3] = 5'b00000; // uo_out[7:3] set to always 0

  // List all unused inputs to prevent warnings
  wire _unused = &{ena, uio_in, ui_in[7:4], 1'b0};

  wire ps2_clk_internal;
  wire ps2_data_internal;
  wire [7:0] ps2_key_data;
  wire valid;
  wire interupt;
  wire int_clear;
  wire cs;
  wire data_rdy;

  reg cs_prev = 0;
  reg cs_trigger = 0;

  assign int_clear = ui_in[2];
  assign cs = ui_in[3];

  assign uo_out[0] = valid;
  //assign uo_out[1] = interupt;
  assign uo_out[2] = ~data_rdy;

  always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
      cs_prev <= 0;
      cs_trigger <= 0;
    end else begin
      cs_prev <= cs;
      if (cs_prev == 0 && cs) begin
        cs_trigger <= 1;
      end else begin
        cs_trigger <= 0;
      end 
    end
  end

  debounce ps2_clk_debounce(
    .clk(clk),
    .reset(~rst_n),
    .button(ui_in[0]),
    .debounced_button(ps2_clk_internal)
  );

  debounce ps2_data_debounce(
    .clk(clk),
    .reset(~rst_n),
    .button(ui_in[1]),
    .debounced_button(ps2_data_internal)
  );

  dual_port_fifo memory(
    .clk(clk),
    .rst(~rst_n),
    .wr_en(valid),
    .rd_en(cs_trigger),
    .empty(data_rdy),
    .data_in(ps2_key_data),
    .data_out(uio_out)
  );

  ps2_decoder ps2_decoder_inst (
    .clk(clk),
    .reset(~rst_n),
    .ps2_clk(ps2_clk_internal),
    .ps2_data(ps2_data_internal),
    .data(ps2_key_data),
    .valid(valid),
    .interupt(uo_out[1]),
    .int_clear(int_clear)
  );
endmodule




module ps2_decoder (
    input  wire       clk,      // clock
    input  wire       ps2_clk,  // PS2 Clock Input
    input  wire       ps2_data, // PS2 Data Input
    input  wire       reset,    // Reset signal
    input  wire       int_clear, // Clear Interupt
    output wire       valid,    // pulsed when the output data is valid
    output wire       interupt, // raised when the output data is valid, cleared by reset
    output wire [7:0] data      // Output data
);
// >>> Module Implementation Begin

// <<< Module Implementation End
endmodule





//
// This is a simple debouncer that will output the input signal after it has been stable for 128 clocks.
//

module debounce (
    input wire clk,
    input wire reset,
    input wire button,
    output wire debounced_button
);
    reg [7:0]  counter;  // use high bit to flag completion
    reg        debounced_button_reg;
    reg        last_button;

    assign debounced_button = debounced_button_reg;

    always @(posedge clk or posedge reset) begin
        if (reset) begin
            counter <= 0;
            debounced_button_reg <= 0;
            last_button <= 0;
        end else begin
            last_button <= button;
            if (button != last_button) begin
                counter <= 0;
            end else if (counter[7] == 1) begin
                debounced_button_reg <= last_button;
            end else begin
                counter <= counter + 1;
            end
        end
    end 

endmodule


module dual_port_fifo #(
    parameter DEPTH = 2,   // 2^Number of buffers
    parameter WIDTH = 8    // Data width
) (
    input wire clk,               // Clock signal
    input wire rst,               // Reset signal
    input wire wr_en,             // Write enable pulse signal
    input wire rd_en,             // Read enable pulse signal
    input wire [WIDTH-1:0] data_in, // Data input
    output reg [WIDTH-1:0] data_out, // Data output
    output wire empty,            // FIFO empty flag
    output wire full              // FIFO full flag
);

    // Internal signals
    reg [WIDTH-1:0] mem [0:(1<<DEPTH)-1]; // FIFO memory
    reg [DEPTH-1:0] wr_ptr;  // Write pointer
    reg [DEPTH-1:0] rd_ptr;  // Read pointer
    reg [DEPTH:0] count;     // Number of stored elements, upper bit means full

    // FIFO empty and full flags
    assign empty = (count == 0);
    assign full = (count[DEPTH]);

    // Synchronous write operation
    always @(posedge clk or posedge rst) begin
        if (rst) begin
            wr_ptr <= 0;
        end else if (wr_en && !full) begin
            mem[wr_ptr] <= data_in;
            wr_ptr <= wr_ptr + 1;
        end
    end

    // Synchronous read operation
    always @(posedge clk or posedge rst) begin
        if (rst) begin
            rd_ptr <= 0;
            data_out <= 0;
        end else if (rd_en && !empty) begin
            data_out <= mem[rd_ptr];
            rd_ptr <= rd_ptr + 1;
        end
    end

    // Counter for tracking the number of elements in the FIFO
    always @(posedge clk or posedge rst) begin
        if (rst) begin
            count <= 0;
        end else begin
            case ({wr_en && !full, rd_en && !empty})
                2'b01: count <= count - 1; // Read only
                2'b10: count <= count + 1; // Write only
                2'b11: count <= count;     // Simultaneous read and write
                default: count <= count;   // No operation
            endcase
        end
    end
endmodule

Reference solution:
rtl/generated.v: 
    localparam SYSTEM_CLOCK = 25_000_000;
    localparam PS2_CLOCK = 10_000;
    localparam PS2_BIT_TIME = SYSTEM_CLOCK / PS2_CLOCK;
    
    localparam IDLE = 0, SETUP = 1, CLEAR = 2;

    reg  [10:0]  shift_reg = 0;
    reg  [12:0]  clk_timeout = 0;
    reg  [2:0]   state_reg = IDLE;
    reg  [7:0]   ps2_value = 0;
    reg          valid_reg = 0;
    reg          int_reg = 0;
    reg          ps2_clk_prev = 0;
    reg          shift_reset = 0;

    assign data = ps2_value;
    assign valid = valid_reg;
    assign interupt = int_reg;

    always @(posedge clk or posedge reset) begin
        if (reset) begin 
            shift_reg <= 11'b11111111111;
            ps2_clk_prev <= 0;
        end else begin
            if (shift_reset) begin
                shift_reg <= 11'b11111111111;
            end else begin
                ps2_clk_prev <= ps2_clk;
                // detect the falling edge of ps2_clk
                if (!ps2_clk && ps2_clk_prev) begin
                    shift_reg <= {shift_reg[9:0], ps2_data};
                end
            end
        end
    end 

    always @(posedge clk or posedge reset) begin
        if (reset) begin
            clk_timeout <= 0;
            state_reg <= IDLE;
            valid_reg <= 0;
            shift_reset <= 0;
            ps2_value <= 8'b00000000;
        end else begin
            if (ps2_clk) begin
                if (clk_timeout == PS2_BIT_TIME[12:0]) begin
                    case(state_reg)
                        IDLE: begin
                            ps2_value <= {shift_reg[2], shift_reg[3], shift_reg[4], shift_reg[5], shift_reg[6], shift_reg[7], shift_reg[8], shift_reg[9]};
                            state_reg <= SETUP;
                        end
                        SETUP: begin
                            shift_reset <= 1;
                            valid_reg <= (shift_reg[2] ^ shift_reg[3] ^ shift_reg[4] ^ shift_reg[5] ^ shift_reg[6] ^ shift_reg[7] ^ shift_reg[8] ^ shift_reg[9] ^ shift_reg[1]) && shift_reg[0] == 1 && shift_reg[10] == 0;
                            state_reg <= CLEAR;
                        end
                        CLEAR: begin
                            shift_reset <= 0;
                            valid_reg <= 0;
                            ps2_value <= 0;
                            clk_timeout[12] <= 1;
                        end
                    endcase
                end else if (clk_timeout[12] == 0) begin
                    clk_timeout <= clk_timeout + 1;
                end
            end else begin
                clk_timeout <= 0;
                state_reg <= IDLE;
                valid_reg <= 0;
            end
        end
    end

    always @(posedge clk or posedge reset) begin
        if (reset) begin
            int_reg <= 0;
        end else if (valid_reg) begin
            int_reg <= 1;
        end else if (int_clear) begin
            int_reg <= 0;
        end
    end