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 Aron Dennen 
 * SPDX-License-Identifier: Apache-2.0
 */

`define default_netname none

module tt_um_7seg_animated (
    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,      // will go high when the design is enabled
    input  wire       clk,      // clock
    input  wire       rst_n     // reset_n - low to reset
);

  reg reset;
  
  // *** Clock divider vars

  wire clkPwm;
  wire clk60;

  clock_divider clk_divider (
    .clk(clk),
    .reset(reset),
    .clkPwm(clkPwm),
    .clk60(clk60)
    );

  // *** PWM module vars

  reg pwmOut;

  pwm pwm (
    .enable(ena),
    .clk(clkPwm),
    .reset(reset),
    .pwmValue( { uio_in[6:0], 1'b0 } ),
    .pwmOut(pwmOut)
  );

  // *** Segment animator vars

  reg [6:0] charInput;
  wire [6:0] displayOut;

  segment_animator animator (
    .enable(ena),
    .clk(clk),
    .clk60(clk60),
    .reset(reset),
    .charAvailable(ui_in[7]),
    .charInput(charInput),
    .out(displayOut)
  );

  // *** Main program

  reg [7:0] out;
  assign uo_out = out;
  
  always @(posedge clk) begin
    reset <= ~rst_n;
    charInput <= ui_in[6:0];

    if (uio_in[7]) begin
      out[6:0] <= (pwmOut) ? displayOut : 7'b0000000;
    end
    else out[6:0] <= displayOut;

    out[7] <= ui_in[7];
  end

  // All output pins must be assigned. If not used, assign to 0.
  //assign uo_out  = ui_in + uio_in;  // Example: ou_out is the sum of ui_in and uio_in
  assign uio_out = 0;
  assign uio_oe  = 0;

endmodule


/*
 * Copyright (c) 2024 Aron Dennen 
 * SPDX-License-Identifier: Apache-2.0
 */

// Iterates over the bits of a 7-segment character, sets the output segments individually with a delay period

module segment_animator (

  // Inputs
  input wire reset,
  input wire enable,
  input wire clk,
  input wire clk60, // 60Hz clock input for timing
  input wire charAvailable, // A character is available to be read
  input wire [6:0] charInput, // The next character to read

  // Outputs
  output wire [6:0] out // 7-segment out
);
// >>> Module Implementation Begin

// <<< Module Implementation End
endmodule




/*
 * Copyright (c) 2024 Aron Dennen 
 * SPDX-License-Identifier: Apache-2.0
 */

// Inputs a 12.5 MHz signal and outputs a 122400 Hz (480Hz * 255 Pwm periods/clock) and 60 Hz clock signal
// Outputs toggle at twice the output frequency to maintin N rising edges per second

module clock_divider (
  // Inputs
  input wire clk,
  input wire reset,
  
  // Outputs
  output wire clkPwm,
  output wire clk60
);

  reg [5:0] count; // 6-bit counter for 12.5 MHz -> 122,400 Hz signal (51 counts per transition)
  reg [9:0] count2; // 10-bit counter for 122,400 Hz -> 60 Hz signal (1020 counts per transition)

  reg outPwm;
  reg out60;

  assign clkPwm = outPwm;
  assign clk60 = out60;

  always @(posedge clk) begin
    if (reset) begin
      count <= 0;
      outPwm <= 0;
    end
    else begin
      count <= count + 1;
      if (count == 51) begin
        // reset the main counter
        count <= 0; 
        outPwm <= ~outPwm;
      end
    end
  end

  always @(posedge outPwm) begin
    if (reset) begin
      count2 <= 0;
      out60 <= 0;
    end
    else begin
      count2 <= count2 + 1;

      if (count2 == 1020) begin
        count2 <= 0; 
        out60 <= ~out60;
      end
    end
  end

endmodule


/*
 * Copyright (c) 2024 Aron Dennen 
 * SPDX-License-Identifier: Apache-2.0
 */

// 8-bit pwm, pwmValue 0 = fully off, pwmValue 255 = fully on
// rolls the count over at 254 to prevent the off-by-one error
// which prevents 255 from being fully on

module pwm (
  // Inputs
  input wire enable,
  input wire clk,
  input wire reset,
  input wire [7:0] pwmValue,
 
  // Outputs
  output wire pwmOut
);

  reg [7:0] pwmCount;
  reg out;
  
  assign pwmOut = out;
  
  always @(posedge clk) begin
    if (enable) begin

      if (reset) begin
        pwmCount <= 0;
        out <= 0;
      end
      else if (enable) begin
        out <= (pwmCount < pwmValue) ? 1 : 0;
        pwmCount <= pwmCount + 1;
        if (pwmCount == 254) pwmCount <= 0; // Off-by-one error fix
      end

    end
  end

endmodule


Reference solution:
rtl/generated.v: 
  reg [6:0] segsOut;
  
  reg [6:0] currentChar; // Current 7-segment character to be displayed
  reg [6:0] segChecked; // Flags whether the segment has been evaluated for display
  reg [2:0] segIndex; // Debug for displaying segments sequentially

  reg [5:0] timerCount; // 6-bit segment animation timer (64 ticks)

  // Registers used for rising edge detection while avoiding multidriven errors 
  reg charAvailable_prev;
  reg clk60_prev;

  // States
  reg [1:0] state;
  localparam idle_state = 2'b00;
  localparam getChar_state = 2'b01;
  localparam getSeg_state = 2'b10;

  assign out = segsOut;

  always @(posedge clk) begin

    if (reset) begin
      segsOut <= 0;

      currentChar <= 0;
      segChecked <= 0;
      segIndex <= 0;

      timerCount <= 0;

      state <= idle_state;
      charAvailable_prev <= 0;
      clk60_prev <= 0;
    end
    else if (enable) begin

      // Check for rising edges 
      
      // Read the character from charInput on the rising edge of charAvailable
      if (charAvailable == 1 && charAvailable_prev == 0) begin
        state <= getChar_state;
      end

      // Update the timer on the rising edge of clk60
      else if (clk60 == 1 && clk60_prev == 0) begin

        if (timerCount > 0) begin
          timerCount <= timerCount - 1;
          if (timerCount == 1) state <= getSeg_state; // Get the next segment after the timer expires
        end
      end

      // If there are no rising edges then process the current state
      else begin

        case(state)
          getSeg_state: begin
            // Find the next valid segment, one clock at a time

            // If the current segment index is a valid segment,
            // display it and start the timer
            if (currentChar[segIndex] == 1) begin
              segsOut[segIndex] <= 1;

              // Start the timer and move to idle state
              timerCount <= 7; // delay for 7 timer ticks = 7/60 or 0.117 seconds
              state <= idle_state;
            end
            
            // Mark that the segment has been checked
            segChecked[segIndex] <= 1;
            
            // Move to the next segment to check (debug)
            segIndex <= segIndex + 1;
            
            // 3. If all the segments have been checked, idle
            if (segChecked == 7'b1111111) begin
              state <= idle_state;
            end
          end

          getChar_state: begin
            // *** Reset variables ***
            segsOut <= 0;  // Reset the display

            currentChar <= charInput; // Get the next input character here
            segChecked <= 0;
            segIndex <= 0;

            timerCount <= 0;

            // Done getting the new character
            // Start displaying the segments
            state <= getSeg_state;
          end
          
          default:;
        endcase

      end
      
      // Update the signal status registers used for edge detection
      charAvailable_prev <= charAvailable;
      clk60_prev <= clk60;
    end /* end else if (enable) */
    
  end /* end always block */