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_wokwi_413387065339458561 (
    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
);

  wire not_reset;
  assign not_reset = ~rst_n;

  // Easier to shuffle than if I'd made a single giant wire
  wire [8:0] pixel_0;
  wire [8:0] pixel_1;
  wire [8:0] pixel_2;
  wire [8:0] pixel_3;
  wire [8:0] pixel_4;
  wire [8:0] pixel_5;
  wire [8:0] pixel_6;

  apa102_in spi_in(
    .clk(clk),
    .rst_n(rst_n),
    .sck(ui_in[0]),
    .sda(ui_in[1]),
    .data_out({pixel_0, pixel_1, pixel_2, pixel_3, pixel_4, pixel_5, pixel_6})
  );
  // data_out is a pruned version of the SPI stream that loses the first 8 bits (intensity value)
  // of each 32-bit pixel value so we don't have to discard them via routing - this saves like 8%

  // APA102s are BGR; WS2812s expect GRB. So we have to shuffle the subpixel order.
  led #( .LED_CNT(7) ) ws2812_out (
    .clk(clk),
    .reset(not_reset),
    .led_o(uo_out[0]),
    .data({
      5'b0, pixel_0[5:3], 5'b0, pixel_0[2:0], 5'b0, pixel_0[8:6],
      5'b0, pixel_1[5:3], 5'b0, pixel_1[2:0], 5'b0, pixel_1[8:6],
      5'b0, pixel_2[5:3], 5'b0, pixel_2[2:0], 5'b0, pixel_2[8:6],
      5'b0, pixel_3[5:3], 5'b0, pixel_3[2:0], 5'b0, pixel_3[8:6],
      5'b0, pixel_4[5:3], 5'b0, pixel_4[2:0], 5'b0, pixel_4[8:6],
      5'b0, pixel_5[5:3], 5'b0, pixel_5[2:0], 5'b0, pixel_5[8:6],
      5'b0, pixel_6[5:3], 5'b0, pixel_6[2:0], 5'b0, pixel_6[8:6]
      })
  );

  uart_printer uart_output (
    .clk(clk),
    .rst_n(rst_n),
    .uart_out(uo_out[1])
  );

  // All output pins must be assigned. If not used, assign to 0.
  assign uio_out = 8'b0;
  assign uio_oe  = 0;
  assign uo_out[7:2]  = 6'b0;

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

endmodule


// A very basic SPI receiver; waits for a valid 32-bit '0' start packet for APA102s
// Then shifts the next 7 LEDs' 32-bit payloads into data_out (ignoring the leading 8 bits of "intensity")
// Stops shifting just prior to the 32-bit stop packet and then cycles back around for the next one

module apa102_in (
  input wire clk,
  input wire rst_n,
  input wire sck,
  input wire sda,
  output reg [62:0] data_out
);

  localparam START = 2'b00;
  localparam DATA = 2'b01;
  localparam STOP = 2'b10;
  
  reg [1:0] state;
  
  reg [5:0] index;
  
  reg [8:0] bit_count;

  reg last_sck;

  always @(posedge clk) begin
    if (!rst_n) begin
      state <= START;
      data_out <= 0;
      bit_count <= 0;
      last_sck <= 1;
      index <= 62;
    end else begin
      last_sck <= sck;

      //posedge sck
      if ((sck == 1) && !last_sck) begin 
        case(state)
          START: begin
            if (sda) begin // we need 32 0 bits for a valid start frame
              bit_count <= 0;
            end else begin
              if (bit_count == 31) begin
                state <= DATA;
              end
              bit_count <= bit_count + 1;
            end
          end // START
      
          DATA: begin
            if ( ((bit_count - 32)  % 32) >= 8 ) begin
              if ((bit_count % 8) < 3) begin
                data_out[index] <= sda;
                index <= index - 1;
              end
            end
            bit_count <= bit_count + 1;
            if (bit_count == 256) begin // 32*(start + 7 LEDs)
              state <= STOP;
            end
          end // DATA
       
          STOP: begin
            if (bit_count == 288) begin // 32*(start + 7 LEDs + stop)
              state <= START;
              index <= 62;
              bit_count <= 0;
            end else begin
              bit_count <= bit_count + 1;
            end
          end // STOP

          default: begin
            state <= START;
            data_out <= 0;
            bit_count <= 0;
            index <= 62;
          end
        endcase
      end
    end
  end    
endmodule


// Sourced from https://github.com/Gatsch/jku-tt06-ledcontroller/blob/main/src/led.v
// Modified to iterate through the data parameter in the opposite direction
//
// Copyright 2024 Mathias Garstenauer
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE−2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

`ifndef __led__
`define __led__

module led #(
	parameter CLK_SPEED = 25_000_000,		//clock speed of the chip
	parameter LED_CNT = 3,					//number of leds
	parameter CHANNELS = 3,					//number of channels per led
	parameter BITPERCHANNEL = 8,			//bits per channel
	parameter PERIOD = 0.00000125,			//period length of one bit
	parameter HIGH0 = 0.0000004,			//high time for a 0 bit
	parameter HIGH1 = 0.0000008,			//high time for a 1 bit
	parameter REFRESH_DURATION = 0.00005	//duration for reset
)(
	input wire [LED_CNT*CHANNELS*BITPERCHANNEL-1:0]data, //data
	output wire led_o,						//output for leds
	input wire clk,							//internal clock
	input wire reset						//chip reset
);
	
	
	//calculating multiple constants out of the parameters 
	localparam DATAWIDTH = LED_CNT*CHANNELS*BITPERCHANNEL;
	localparam DATACOUNTWIDTH = $clog2(DATAWIDTH);
	
	localparam REFRESH_PERIOD32 = $rtoi(CLK_SPEED*REFRESH_DURATION);
	localparam COUNT_PERIOD32 = $rtoi(CLK_SPEED*PERIOD);
	localparam COUNT_0H32 =  $rtoi(CLK_SPEED*HIGH0);
	localparam COUNT_1H32 =  $rtoi(CLK_SPEED*HIGH1);
	
	localparam COUNTWIDTH = $clog2(REFRESH_PERIOD32);
	//truncation to discard errors with operators later on
	localparam REFRESH_PERIOD = REFRESH_PERIOD32[COUNTWIDTH-1:0];
	localparam COUNT_PERIOD = COUNT_PERIOD32[COUNTWIDTH-1:0];
	localparam COUNT_0H = COUNT_0H32[COUNTWIDTH-1:0];
	localparam COUNT_1H = COUNT_1H32[COUNTWIDTH-1:0];
	
	localparam Refresh = 1'b0;
	localparam Write = 1'b1;
	
	reg [DATACOUNTWIDTH-1:0] datacounter, next_datacounter;
	reg [COUNTWIDTH-1:0] counter, next_counter;
	reg state, next_state;
	reg led_out;

	//the registers are updated each clock cylce with their new values
	always @(posedge clk) begin
		if (reset) begin
			state <= 0;
			counter <= 0;
			datacounter <= DATAWIDTH-1'b1;
		end else begin
			counter <= next_counter;
			datacounter <= next_datacounter;
			state <= next_state;
		end
		
	end
	
	//updates the leds constantly (includes a refresh period)
	always @(counter or datacounter) begin
		next_counter <= counter;
		next_datacounter <= datacounter;
		next_state <= state;
		led_out <= 1'b0;
		case (state) 
			//refresh for the leds the counter value is calculated from 
			//the internal clock as well as the needed duration
			Refresh: begin
				if (counter < REFRESH_PERIOD) begin
					next_counter <= counter + 1;
				end else begin
					next_counter <= 0;
					next_state <= Write;
				end
			end
			//writes the bits from data to the leds
			Write: begin
				if (counter < COUNT_PERIOD-1'b1) begin	//runs for one period
					next_counter <= counter + 1;
				end else begin
					next_counter <= 0;
					if (datacounter > 0) begin	//runs for all bits
						next_datacounter <= datacounter - 1;
					end else begin
						next_datacounter <= DATAWIDTH-1'b1;
						next_state <= Refresh;
					end
				end
				//set output to low at the right time according to the current bit
				if (counter < ((data[datacounter])?COUNT_1H:COUNT_0H)) begin
					led_out <= 1'b1;
				end else begin
					led_out <= 1'b0;
				end
			end
		endcase   
	end
	assign led_o = led_out;
endmodule

`endif


module uart_printer (
  input wire clk,
  input wire rst_n,
  output reg uart_out
);
// >>> Module Implementation Begin

// <<< Module Implementation End
endmodule




Reference solution:
rtl/generated.v:   localparam CLK_SPEED = 25000000;
  localparam UART_PERIOD = 0.000008681;
  localparam UART_COUNTS32 = $rtoi(CLK_SPEED*UART_PERIOD);
  localparam UART_COUNTS = UART_COUNTS32[7:0];
  localparam MSG_LEN = 180;

  // Generated in Python - but I had to flip it around backwards, gah:
  // for c in "Arglius Barglius\r\n"[::-1]:
  //     print("1'b1, {}, 1'b0, ".format(bin(ord(c))).replace("0b", "8'b"), end='')
  reg [MSG_LEN-1 : 0] msg = {1'b1, 8'b1010, 1'b0, 1'b1, 8'b1101, 1'b0, 1'b1, 8'b1110011, 1'b0, 1'b1, 8'b1110101, 1'b0, 1'b1, 8'b1101001, 1'b0, 1'b1, 8'b1101100, 1'b0, 1'b1, 8'b1100111, 1'b0, 1'b1, 8'b1110010, 1'b0, 1'b1, 8'b1100001, 1'b0, 1'b1, 8'b1000010, 1'b0, 1'b1, 8'b100000, 1'b0, 1'b1, 8'b1110011, 1'b0, 1'b1, 8'b1110101, 1'b0, 1'b1, 8'b1101001, 1'b0, 1'b1, 8'b1101100, 1'b0, 1'b1, 8'b1100111, 1'b0, 1'b1, 8'b1110010, 1'b0, 1'b1, 8'b1000001, 1'b0};

  reg [7:0] count;
  reg [7:0] index;

  always @(posedge clk) begin
    if (!rst_n) begin
       count <= 0;
       index <= 0;
       uart_out <= 1;
    end else begin
      if (count == UART_COUNTS) begin
        count <= 0;
        uart_out <= msg[index];
        if (index < MSG_LEN) begin
          index <= index + 1;
        end else begin
          index <= 0;
        end
      end else begin
        count <= count + 1;
      end
    end
  end