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.

// SPDX-License-Identifier: Apache-2.0

`default_nettype none

module tt_um_lif_network_MR (
    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 for neuron inputs
    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
);
// >>> Module Implementation Begin

// <<< Module Implementation End
endmodule




`default_nettype none
module lif(
    input wire [3:0] current,
    input wire clk,
    input wire reset,
    output wire spike
);
    reg [3:0] state;

    wire [3:0] NS;
    reg [3:0] threshold;

    always @(posedge clk) begin
        if (!reset) begin
            state <= 0;
            threshold <= 8;
        end else if (spike) begin
            state <= 0;  // Reset state when spike occurs
        end else begin
            state <= NS;
        end    
    end

    // Leaky integration: add current and decay state
    assign NS = current + (state >> 1);

    // Generate spike when state reaches or exceeds the threshold
    assign spike = (state >= threshold); 

endmodule


`default_nettype none

module lif_neuron_network(
    input wire clk,                           // Clock signal
    input wire reset,                         // Active-low reset signal
    input wire [3:0] external_input_1,        // 5-bit input for Neuron 1
    input wire [3:0] external_input_2,        // 5-bit input for Neuron 2
    input wire [3:0] external_input_3,        // 5-bit input for Neuron 3
    output wire spike_1,                      // Spike output from Neuron 1
    output wire spike_2,                      // Spike output from Neuron 2
    output wire spike_3,                      // Spike output from Neuron 3
    output wire spike_output                  // Spike output from the output neuron
);

    // Internal signals for spikes and input current for the output neuron
    wire spike_out_1, spike_out_2, spike_out_3;
    reg [3:0] input_current_output;           // 5-bit input for the output neuron

    // Weights for synaptic connections from input neurons to the output neuron
    parameter [3:0] weight_1_to_output = 4'd5;  // Spike weight from Neuron 1 to Output Neuron
    parameter [3:0] weight_2_to_output = 4'd4;  // Spike weight from Neuron 2 to Output Neuron
    parameter [3:0] weight_3_to_output = 4'd3;  // Spike weight from Neuron 3 to Output Neuron

    // Instantiate the three input neurons with 5-bit width
    lif neuron1 (.current(external_input_1), .clk(clk), .reset(reset), .spike(spike_out_1));
    lif neuron2 (.current(external_input_2), .clk(clk), .reset(reset), .spike(spike_out_2));
    lif neuron3 (.current(external_input_3), .clk(clk), .reset(reset), .spike(spike_out_3));

    // Instantiate the output neuron with a 5-bit width
    lif output_neuron (.current(input_current_output), .clk(clk), .reset(reset), .spike(spike_output));

        // Generate the input current for the output neuron based on spikes from the input neurons
    always @(posedge clk) begin
        if (!reset) begin
            input_current_output <= 4'd0;  // Ensure full reset on reset
        end else if (spike_out_1 || spike_out_2 || spike_out_3) begin
            // Accumulate contributions only when there is a spike from any input neuron
            input_current_output <= ({4{spike_out_1}} & weight_1_to_output) +
                                    ({4{spike_out_2}} & weight_2_to_output) +
                                    ({4{spike_out_3}} & weight_3_to_output);
             
        end else begin
            input_current_output <= 4'd0;  // Set to zero when there are no spikes
            
        end
    end


    


    // Assign spike outputs for observation
    assign spike_1 = spike_out_1;
    assign spike_2 = spike_out_2;
    assign spike_3 = spike_out_3;

endmodule


Reference solution:
rtl/generated.v: 
    // Set `uio_oe` to 0 for inputs and 1 for outputs
    assign uio_oe = 8'b11110000;  // Lower 4 bits for inputs, upper 4 bits for outputs
    assign uio_out[3:0] = 0;
    // Prevent warnings by marking unused inputs
    wire _unused = &{ena, 1'b0, uio_in[7:4]};

    // Internal wires for spike outputs from neurons in the network
    wire spike_out_1, spike_out_2, spike_out_3, spike_out_final;

    // Instantiate the lif_neuron_network module with unique inputs for each neuron
    lif_neuron_network lif_net (
        .clk(clk),
        .reset(rst_n),                   
        .external_input_1(uio_in[3:0]),  // Unique input for Neuron 1
        .external_input_2(ui_in[7:4]),  // Unique input for Neuron 2
        .external_input_3(ui_in[3:0]),  // Unique input for Neuron 3
        .spike_1(spike_out_1),              
        .spike_2(spike_out_2),
        .spike_3(spike_out_3),
        .spike_output(spike_out_final)     
    );

    // Use the final spike output in uio_out[7] for observation
    assign uio_out[7] = spike_out_final;
    assign uio_out[6] = spike_out_3;
    assign uio_out[5] = spike_out_2;
    assign uio_out[4] = spike_out_1;

    // Combine individual neuron spike outputs into uo_out for monitoring
    assign uo_out = {4'b0, spike_out_3, spike_out_2, spike_out_1, spike_out_final};