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.

`default_nettype none

module tt_um_mini_aie_2x2 (
    input  wire [7:0] ui_in,    // Dedicated inputs - connected to the input switches
    output wire [7:0] uo_out,   // Dedicated outputs - connected to the 7 segment display
    /* verilator lint_off UNUSEDSIGNAL */
    input  wire [7:0] uio_in,   // IOs: Bidirectional Input path
    /* verilator lint_on UNUSEDSIGNAL */
    output wire [7:0] uio_out,  // IOs: Bidirectional Output path
    output wire [7:0] uio_oe,   // IOs: Bidirectional Enable path (active high: 0=input, 1=output)
    input  wire       ena,      // will go high when the design is enabled
    input  wire       clk,      // clock
    input  wire       rst_n     // reset_n - low to reset
);

  wire reset = !rst_n & ena;
  assign uio_oe = 8'b11111111;

  // intermediate regs between FIFOs and switches
  reg [7:0] switch_fifo_in[4];
  reg [7:0] switch_fifo_out[4];

  // intermediate regs between switches and PEs
  reg [7:0] switch_pe_out[4];
  reg [7:0] switch_pe_in[4];

  // intermediate regs between PEs
  reg [7:0] prev_pe_in[4];
  reg [7:0] next_pe_in[4];

  // control signals
  wire switch_fifo_rd_en[4];
  wire switch_fifo_wr_en[4];
  
  // generate noc and pe array
  generate
    genvar i;
    for (i = 0; i < 4; i = i + 1) begin : gen
      if (i == 0) begin
        synchronous_fifo #(
            .DEPTH(2),
            .DATA_WIDTH(8)
        ) fifo (
            .clk(clk),
            .rst_n(rst_n),
            .w_en(ena),
            .r_en(switch_fifo_rd_en[i]),
            .data_in(ui_in),
            .data_out(switch_fifo_in[i]),
            .full(),
            .empty()
        );
      end else begin
        synchronous_fifo #(
            .DEPTH(2),
            .DATA_WIDTH(8)
        ) fifo (
            .clk(clk),
            .rst_n(rst_n),
            .w_en(switch_fifo_wr_en[i-1]),
            .r_en(switch_fifo_rd_en[i]),
            .data_in(switch_fifo_out[i-1]),
            .data_out(switch_fifo_in[i]),
            .full(),
            .empty()
        );
      end

      switch #(
          .rank(i)
      ) switch (
          .clk(clk),
          .rst_n(rst_n),
          .switch_fifo_in(switch_fifo_in[i]),
          .switch_fifo_out(switch_fifo_out[i]),
          .pe_fifo_in(switch_pe_out[i]),
          .pe_fifo_out(switch_pe_in[i]),
          .rd_en(switch_fifo_rd_en[i]),
          .wr_en(switch_fifo_wr_en[i])
      );

      integer last = i == 3 ? 0 : i + 1;
      compute_tile pe (
          .clk(clk),
          .rst_n(rst_n),
          .switch_data_in(switch_pe_in[i]),
          .switch_data_out(switch_pe_out[i]),
          .prev_pe_data_in(next_pe_in[last]),
          .next_pe_data_out(next_pe_in[i]),
          .next_pe_data_in(prev_pe_in[last]),
          .prev_pe_data_out(prev_pe_in[i])
      );
    end

  endgenerate
  assign uo_out = switch_fifo_out[2];
  assign uio_out = 8'b00000000;

  always @(posedge clk or negedge rst_n) begin
    $display("------------");
    $display("uo_out: %d, uio_in[7]: %d", uo_out, uio_in[7]);
    $display("switch_fifo_out[0]: %b, switch_fifo_in[0]: %b", switch_fifo_out[0], switch_fifo_in[0]);
    $display("switch_fifo_out[1]: %b, switch_fifo_in[1]: %b", switch_fifo_out[1], switch_fifo_in[1]);
    $display("switch_fifo_out[2]: %b, switch_fifo_in[2]: %b", switch_fifo_out[2], switch_fifo_in[2]);
    $display("switch_fifo_out[3]: %b, switch_fifo_in[3]: %b", switch_fifo_out[3], switch_fifo_in[3]);
  end
  

endmodule




module synchronous_fifo #(parameter DEPTH=2, DATA_WIDTH=8) (
  input wire clk, 
  input wire rst_n,
  input wire w_en, 
  input wire r_en,
  input [DATA_WIDTH-1:0] data_in,
  output reg [DATA_WIDTH-1:0] data_out,
  output wire full, empty
);
  
  reg [$clog2(DEPTH)-1:0] w_ptr, r_ptr;
  reg [DATA_WIDTH-1:0] fifo[DEPTH];
  
  // Set Default values on reset.
  always@(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
      w_ptr <= 0; r_ptr <= 0;
      data_out <= 0;
      
    end else begin
      if (w_en & !full) begin
        fifo[w_ptr] <= data_in;
        w_ptr <= w_ptr + 1;
      end
      
      if (r_en & !empty) begin
        data_out <= fifo[r_ptr];
        r_ptr <= r_ptr + 1;
      end
    end
  end

  assign full = ((w_ptr+1'b1) == r_ptr);
  assign empty = (w_ptr == r_ptr);


endmodule

// data_in[7:6] -> state
//   state = 00: CONFIG(WEIGHT)
//   state = 01: CONFIG(NEXT_PE, OP)
//   state = 10: START(OPERAND)
//   state = 11: END(OUTPUT)

module compute_tile
(
    input wire clk, 
    input wire rst_n,
    input [7:0] switch_data_in,
    output reg [7:0] switch_data_out,
    output reg [7:0] next_pe_data_out,
    input [7:0] next_pe_data_in,
    input [7:0] prev_pe_data_in,
    output reg [7:0] prev_pe_data_out
);
// >>> Module Implementation Begin

// <<< Module Implementation End
endmodule







module switch 
#(parameter rank = 0)
(
    input wire clk, rst_n,
    input [7:0] switch_fifo_in, 
    output reg [7:0] switch_fifo_out,
    input [7:0] pe_fifo_in,
    output reg [7:0] pe_fifo_out,
    output wire rd_en,
    output wire wr_en
);

reg [7:0] prev_switch_fifo_in;
reg [7:0] prev_pe_fifo_in;

wire pe_rd, fifo_rd;
assign pe_rd = pe_fifo_in != prev_pe_fifo_in;
assign fifo_rd = switch_fifo_in != prev_switch_fifo_in;

always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        switch_fifo_out <= 8'b00000000;
        pe_fifo_out <= 8'b00000000;
        prev_pe_fifo_in <= 8'b00000000;
        prev_switch_fifo_in <= 8'b00000001;

    end else begin
        if (pe_rd) begin
            prev_pe_fifo_in <= pe_fifo_in;
            switch_fifo_out <= {4'b1111, pe_fifo_in[3:0]};
            
        end else if (fifo_rd) begin
            prev_switch_fifo_in <= switch_fifo_in;
            if (switch_fifo_in[5:4] == rank) begin
                pe_fifo_out <= switch_fifo_in;
            end else begin
                switch_fifo_out <= switch_fifo_in;
            end
        end 
    end
end

assign rd_en = 1'b1;
assign wr_en = 1'b1;

endmodule


Reference solution:
rtl/generated.v: 
    reg op_type;
    reg [3:0] weight;

    reg has_next_core;
    reg next_core_offset;

    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            op_type <= 1'b0;
            weight <= 4'b0000;
            next_pe_data_out <= 8'b00000000;
            prev_pe_data_out <= 8'b00000000;

            has_next_core <= 1'b0;
            next_core_offset <= 1'b0;
            switch_data_out <= 8'b00000000;
        
        end else if (switch_data_in[7:6] == 2'b00) begin
            // $display("compute_tile config weight: %d", switch_data_in);
            weight <= switch_data_in[3:0];
        
        end else if (switch_data_in[7:6] == 2'b01) begin
            has_next_core <= 1'b1;
            next_core_offset <= switch_data_in[4];
            op_type <= switch_data_in[0];
        
        end else begin
            if (has_next_core) begin
                next_pe_data_out <= switch_data_in;
                // case (next_core_offset)
                //     1'b0: next_pe_data_out <= switch_data_in;
                //     1'b1: prev_pe_data_out <= switch_data_in;
                // endcase
            end else begin
                switch_data_out <= weight + prev_pe_data_in + next_pe_data_in;
                // case (op_type) 
                //     1'b0: switch_data_out <= weight + prev_pe_data_in + next_pe_data_in;
                //     1'b1: switch_data_out <= weight & prev_pe_data_in & next_pe_data_in;
                // endcase    
            end
        end
    end