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
//`timescale 1ns / 1ps

module vga_sync #(

  //SMELL: Instead of having lots of ternary operators (muxes based on mode),
  // it might be better to just use registers to store the parameters and load
  // those registers at the end of each frame. It seems there are only 8
  // actual registers we'd need to worry about (as their reset values are
  // derived from all the other constants). The ones that matter are:
  // - H_MAX, V_MAX
  // - H_VIEW, V_VIEW
  // - H_SYNC_START, V_SYNC_START
  // - H_SYNC_END, V_SYNC_END
  
  //SMELL: If we use these parameters in future, should they just be localparams instead?

  // Mode 0: 640x480@60Hz timing (http://tinyvga.com/vga-timing/640x480@60Hz).
  // Overall timing for true VGA 25.175MHz clock: 25,175,000 / 800 / 525 = 59.94Hz
  // or for 25.0MHz clock: 59.52Hz
  // 800 clocks wide:
  parameter M0_H_VIEW       = 640,  // Visible area comes first...
  parameter M0_H_FRONT      =  16,  // ...then HBLANK starts with M0_H_FRONT (RHS border)...
  parameter M0_H_SYNC       =  96,  // ...then sync pulse starts...
  parameter M0_H_BACK       =  48,  // ...then remainder of HBLANK (LHS border).
  parameter M0_H_MAX        = M0_H_VIEW + M0_H_FRONT + M0_H_SYNC + M0_H_BACK - 1,
  parameter M0_H_SYNC_START = M0_H_VIEW + M0_H_FRONT,
  parameter M0_H_SYNC_END   = M0_H_SYNC_START + M0_H_SYNC,
  // 525 lines tall:
  parameter M0_V_VIEW       = 480,
  parameter M0_V_FRONT      =  10,
  parameter M0_V_SYNC       =   2,
  parameter M0_V_BACK       =  33,
  parameter M0_V_MAX        = M0_V_VIEW + M0_V_FRONT + M0_V_SYNC + M0_V_BACK - 1,
  parameter M0_V_SYNC_START = M0_V_VIEW + M0_V_FRONT,
  parameter M0_V_SYNC_END   = M0_V_SYNC_START + M0_V_SYNC,

  // Mode 1: 1440x900@60 timing (http://tinyvga.com/vga-timing/1440x900@60Hz),
  // but with the clock divided by 4 (so 360x900) from 106.47MHz to 26.6175MHz.
  // 476 clocks wide (normally 1904 at full 1440x900 pixel clock):
  parameter M1_H_VIEW       = 360,  // 1440/4 // Visible area comes first...
  parameter M1_H_FRONT      =  20,  //   80/4 // ...then HBLANK starts with M1_H_FRONT (RHS border)...
  parameter M1_H_SYNC       =  38,  //  152/4 // ...then sync pulse starts...
  parameter M1_H_BACK       =  58,  //  232/4 // ...then remainder of HBLANK (LHS border).
  parameter M1_H_MAX        = M1_H_VIEW + M1_H_FRONT + M1_H_SYNC + M1_H_BACK - 1,
  parameter M1_H_SYNC_START = M1_H_VIEW + M1_H_FRONT,
  parameter M1_H_SYNC_END   = M1_H_SYNC_START + M1_H_SYNC,
  // 932 lines tall:
  parameter M1_V_VIEW       = 900,
  parameter M1_V_FRONT      =   1,
  parameter M1_V_SYNC       =   3,
  parameter M1_V_BACK       =  28,
  parameter M1_V_MAX        = M1_V_VIEW + M1_V_FRONT + M1_V_SYNC + M1_V_BACK - 1,
  parameter M1_V_SYNC_START = M1_V_VIEW + M1_V_FRONT,
  parameter M1_V_SYNC_END   = M1_V_SYNC_START + M1_V_SYNC

  //NOTE: If we were to use the 26.6175MHz clock for 640x480, this would be 63.375Hz.
  // Alternatively, 26.6175MHz for div-2 of this: http://tinyvga.com/vga-timing/800x600@85Hz
  // ...would mean 80.502Hz.
  // Or how about: http://tinyvga.com/vga-timing/640x400@70Hz
  // ...74.102Hz
  // On the flipside, 25.175MHz could give us 1440x900-div4 at 56.747Hz. Would my monitor sync to that?
  // It's also close mul-4 to 102.1MHz (1280x960@60), and 124.54MHz (1280x960@72).
) (
  // Inputs:
  input wire          clk,
  input wire          reset,
  input wire          mode,   // Selects between 640x480@60 timing (mode 0) and 1440x900@60 timing (mode 1).
  // Outputs:
  output wire         o_hsync,  // Polarity matches whatever the selected 'mode' needs.
  output wire         o_vsync,  // Polarity matches whatever the selected 'mode' needs.
  output wire [9:0]   o_hpos,
  output wire [9:0]   o_vpos,
  output wire         o_hmax,
  output wire         o_vmax,
  output wire         o_vblank, // High during vertical blanking.
  output wire         o_hblank, // High during horizontal blanking.
  output wire         o_visible
);

  // HSYNC and VSYNC:
  // These are the internal POSITIVE polarity sync signals.
  reg hsync, vsync;
  // Mode 0 and 1 both use negative polarity HSYNC:
  assign o_hsync = ~hsync;
  // Mode 0 VSYNC is neg polarity. For Mode 1 it is pos:
  assign o_vsync = (mode==0) ? ~vsync : vsync;
  
  // Pixel counters:
  reg [9:0] hpos, vpos;
  assign o_hpos = hpos;
  assign o_vpos = vpos;

  //TODO: Reduce equality checks to just test the bits that matter,
  // because we don't care about values ABOVE these.
  // Might also be able to do similar with comparisons.
  //TODO: Consider making 'visible' a reg insted of combo.

  assign o_hmax   = (mode==0) ? (hpos == M0_H_MAX)  : (hpos == M1_H_MAX);
  assign o_vmax   = (mode==0) ? (vpos == M0_V_MAX)  : (vpos == M1_V_MAX);
  assign o_hblank = (mode==0) ? (hpos >= M0_H_VIEW) : (hpos >= M1_H_VIEW);
  assign o_vblank = (mode==0) ? (vpos >= M0_V_VIEW) : (vpos >= M1_V_VIEW);
  assign o_visible = (~o_hblank) & (~o_vblank);

  // Horizontal tracing:
  always @(posedge clk) begin
          if (reset)                      hpos <= 0;
    else  if (o_hmax)                     hpos <= 0;
    else                                  hpos <= hpos + 1'b1;
  end

  // Vertical tracing:
  always @(posedge clk) begin
          if (reset)                      vpos <= 0;
    else  if (o_hmax)                     vpos <= (o_vmax) ? 10'b0 : vpos + 1'b1;
  end

  // HSYNC:
  always @(posedge clk) begin
    if (mode==0) begin
            if (hpos==M0_H_SYNC_END || reset)  hsync <= 0;
      else  if (hpos==M0_H_SYNC_START)         hsync <= 1;
    end else begin
            if (hpos==M1_H_SYNC_END || reset)  hsync <= 0;
      else  if (hpos==M1_H_SYNC_START)         hsync <= 1;
    end
  end

  // VSYNC:
  always @(posedge clk) begin
    if (mode==0) begin
            if (vpos==M0_V_SYNC_END || reset)  vsync <= 0;
      else  if (vpos==M0_V_SYNC_START)         vsync <= 1;
    end else begin
            if (vpos==M1_V_SYNC_END || reset)  vsync <= 0;
      else  if (vpos==M1_V_SYNC_START)         vsync <= 1;
    end
  end
endmodule


// Adapted from Matt Venn's VGA clock:
// https://github.com/mattvenn/tt08-vga-clock/blob/main/src/vga_clock.v

`default_nettype none

module clock_logic #(
    parameter CORE_CLOCK = 25_000_000
) (
    input wire clk,
    input wire reset,
    input wire adj_hrs,
    input wire adj_min,
    input wire adj_sec,
    input wire but_clk_en,  // Pulses (e.g. on frame end) to throttle button update rate.
    output reg [3:0] sec_u,
    output reg [2:0] sec_d,
    output reg [3:0] min_u,
    output reg [2:0] min_d,
    output reg [3:0] hrs_u,
    output reg [1:0] hrs_d,
    output reg [2:0] color_offset // Used to cycle through colour ramp, as 'minutes' increments.
);
    reg [24:0] sec_counter; // Enough to hold CORE_CLOCK counts.

    wire adj_sec_pulse, adj_min_pulse, adj_hrs_pulse;

    always @(posedge clk) begin
        if(reset) begin
            sec_u <= 0;
            sec_d <= 0;
            min_u <= 0;
            min_d <= 0;
            hrs_u <= 0;
            hrs_d <= 0;
            sec_counter <= 0;
            color_offset <= 0;
        end else begin
            if(sec_u == 10) begin
                sec_u <= 0;
                sec_d <= sec_d + 1;
            end
            if(sec_d == 6) begin
                sec_d <= 0;
                min_u <= min_u + 1;
                color_offset <= color_offset + 1;
            end
            if(min_u == 10) begin
                min_u <= 0;
                min_d <= min_d + 1;
            end
            if(min_d == 6) begin
                min_d <= 0;
                hrs_u <= hrs_u + 1;
            end
            if(hrs_u == 10) begin
                hrs_u <= 0;
                hrs_d <= hrs_d + 1;
            end
            if(hrs_d == 2 && hrs_u == 4) begin
                hrs_u <= 0;
                hrs_d <= 0;
            end

            // second counter
            sec_counter <= sec_counter + 1;
            if(sec_counter + 1 == CORE_CLOCK) begin
                sec_u <= sec_u + 1;
                sec_counter <= 0;
            end

            // adjustment buttons
            if(adj_sec_pulse)
                sec_u <= sec_u + 1;
            if(adj_min_pulse) begin
                min_u <= min_u + 1;
                color_offset <= color_offset + 1;
            end
            if(adj_hrs_pulse)
                hrs_u <= hrs_u + 1;
        end
    end

    localparam MAX_BUT_RATE = 16;
    localparam DEC_COUNT = 1;
    localparam MIN_COUNT = 2;
    button_pulse #(.MIN_COUNT(MIN_COUNT), .DEC_COUNT(DEC_COUNT), .MAX_COUNT(MAX_BUT_RATE)) 
        pulse_sec (.clk(clk), .clk_en(but_clk_en), .button(adj_sec), .pulse(adj_sec_pulse), .reset(reset));
    button_pulse #(.MIN_COUNT(MIN_COUNT), .DEC_COUNT(DEC_COUNT), .MAX_COUNT(MAX_BUT_RATE)) 
        pulse_min (.clk(clk), .clk_en(but_clk_en), .button(adj_min), .pulse(adj_min_pulse), .reset(reset));
    button_pulse #(.MIN_COUNT(MIN_COUNT), .DEC_COUNT(DEC_COUNT), .MAX_COUNT(MAX_BUT_RATE)) 
        pulse_hrs (.clk(clk), .clk_en(but_clk_en), .button(adj_hrs), .pulse(adj_hrs_pulse), .reset(reset));


endmodule


module vga_clock_gen (
    input clk,
    input reset,
    input [9:0] x_px,   // X position for actual pixel.
    input [9:0] y_px,   // Y position for actual pixel.
    input activevideo,
    input [3:0] sec_u,
    input [2:0] sec_d,
    input [3:0] min_u,
    input [2:0] min_d,
    input [3:0] hrs_u,
    input [1:0] hrs_d,
    input [2:0] color_offset, // Used to cycle through colour ramp, as 'minutes' increments.
    output wire [5:0] rrggbb
);
    // these units are expressed in "blocks"
    localparam OFFSET_Y_BLK = 0;
    localparam OFFSET_X_BLK = 1;
    localparam NUM_CHARS = 8;
    localparam FONT_W = 4;
    localparam FONT_H = 5;
    localparam COLON = 10;
    localparam BLANK = 11;
    localparam COL_INDEX_W = $clog2(FONT_W);

    wire [FONT_W-1:0] font_out;
    wire [5:0] font_addr;
    wire [5:0] digit_index;
    wire [5:0] color;
    wire [3:0] number;
    wire [COL_INDEX_W-1:0] col_index;
    reg [COL_INDEX_W-1:0] col_index_q;

    wire px_clk = clk;

    // blocks are 16 x 16 px. total width = 8 * blocks of 4 =  512. 
    /* verilator lint_off WIDTH */
    wire [5:0] x_block = (x_px -64) >> 4;
    wire [5:0] y_block = (y_px -200) >> 4;
    /* verilator lint_on WIDTH */
    reg [5:0] x_block_q;
    reg [5:0] y_block_q;

    fontROM #(.data_width(FONT_W)) font_0 (.clk(px_clk), .addr(font_addr), .dout(font_out));

    digit #(.FONT_W(FONT_W), .FONT_H(FONT_H), .NUM_BLOCKS(NUM_CHARS*FONT_W)) digit_0 (.clk(px_clk), .x_block(x_block), .number(number), .digit_index(digit_index), .col_index(col_index), .color(color), .color_offset(color_offset));

    /* verilator lint_off WIDTH */
    assign number     = x_block < FONT_W * 1 ? hrs_d :
                        x_block < FONT_W * 2 ? hrs_u :
                        x_block < FONT_W * 3 ? COLON :
                        x_block < FONT_W * 4 ? min_d :
                        x_block < FONT_W * 5 ? min_u :
                        x_block < FONT_W * 6 ? COLON :
                        x_block < FONT_W * 7 ? sec_d :
                        x_block < FONT_W * 8 ? sec_u :
                        BLANK;
    /* verilator lint_on WIDTH */
   
    reg draw;
    assign rrggbb = activevideo && draw ? color : 6'b0;
    assign font_addr = digit_index + y_block;
    always @(posedge px_clk) begin
        if(reset) begin
            draw <= 0;
            x_block_q <= 0;
            y_block_q <= 0;
        end else begin
            x_block_q <= x_block;
            y_block_q <= y_block;
        end
        col_index_q <= col_index;
        if(x_block_q < FONT_W * NUM_CHARS && y_block_q < FONT_H)
            draw <= font_out[(FONT_W - 1) - col_index_q];
        else
            draw <= 0;
    
    end
endmodule


module button_pulse 
#(
    parameter MAX_COUNT = 8,    // max wait before issue next pulse
    parameter DEC_COUNT = 2,    // every pulse, decrement comparitor by this amount
    parameter MIN_COUNT = 1     // until reaches this wait time
)(
    input wire clk,
    input wire clk_en,
    input wire button,
    input wire reset,
    output wire pulse
);

    reg [$clog2(MAX_COUNT-1):0] comp;
    reg [$clog2(MAX_COUNT-1):0] count;

    assign pulse = (clk_en && button && count == 0);

    always @(posedge clk)
        if(reset) begin
            comp <= MAX_COUNT - 1;
            count <= 0;
        end else
        if(clk_en) begin
            if(button)
                count <= count + 1;

            // if button is held, increase pulse rate by reducing comp
            if(count == 0 && comp > (MIN_COUNT + DEC_COUNT)) begin
                comp <= comp - DEC_COUNT;
            end

            // reset counter
            if(count == comp)
                count <= 0;

            // if button is released, set count and comp to default
            if(!button) begin
                count <= 0;
                comp <= MAX_COUNT - 1;
            end
        end

endmodule


module digit #(
    parameter FONT_W = 3,
    parameter FONT_H = 5,
    parameter NUM_BLOCKS = 20
) (
    input wire clk,
    input wire [5:0] x_block,
    // input wire [5:0] y_block,
    input wire [3:0] number,      // the number to display: [0->9: ]
    input wire [2:0] color_offset, // shift through the colours
    output reg [5:0] digit_index,
    output reg [5:0] color,
    output reg [$clog2(FONT_W)-1:0] col_index
);

    localparam COL_INDEX_W = $clog2(FONT_W); 

    wire [3:0] char = x_block[5:2];
    wire [4:0] color_hash = char + {1'd0, color_offset};
    always @(posedge clk) begin
        /* verilator lint_off WIDTH */
        case (number) // This is number*5:
            4'd0    : digit_index <= 6'h00;
            4'd1    : digit_index <= 6'h05;
            4'd2    : digit_index <= 6'h0a;
            4'd3    : digit_index <= 6'h0f;
            4'd4    : digit_index <= 6'h14;
            4'd5    : digit_index <= 6'h19;
            4'd6    : digit_index <= 6'h1e;
            4'd7    : digit_index <= 6'h23;
            4'd8    : digit_index <= 6'h28;
            4'd9    : digit_index <= 6'h2d;
            4'd10   : digit_index <= 6'h32;
            4'd11   : digit_index <= 6'h37;
            default : digit_index <= 0;
        endcase
        col_index <= x_block < NUM_BLOCKS ? x_block[1:0] : 3;
        case (color_hash[2:0])
            3'd0    : color <= 6'b110000;
            3'd1    : color <= 6'b111000;
            3'd2    : color <= 6'b111100;
            3'd3    : color <= 6'b001000;
            3'd4    : color <= 6'b000011;
            3'd5    : color <= 6'b100010;
            3'd6    : color <= 6'b010010;
            3'd7    : color <= 6'b100001;
        endcase
        /* verilator lint_on WIDTH */
    end
   
endmodule


// Font ROM for numbers 0-9, 4x5 pixels, but really only 3x5.
module fontROM 
#(
    parameter addr_width = 6,
    parameter data_width = 4
)
(
    input wire                  clk,
    input wire [addr_width-1:0] addr,
    output reg [data_width-1:0] dout
);

    always @(posedge clk)
        begin
            case (addr)
                6'd0    : dout <= 4'b1110;
                6'd1    : dout <= 4'b1010;
                6'd2    : dout <= 4'b1010;
                6'd3    : dout <= 4'b1010;
                6'd4    : dout <= 4'b1110;
                6'd5    : dout <= 4'b1100;
                6'd6    : dout <= 4'b0100;
                6'd7    : dout <= 4'b0100;
                6'd8    : dout <= 4'b0100;
                6'd9    : dout <= 4'b1110;
                6'd10   : dout <= 4'b1110;
                6'd11   : dout <= 4'b0010;
                6'd12   : dout <= 4'b1110;
                6'd13   : dout <= 4'b1000;
                6'd14   : dout <= 4'b1110;
                6'd15   : dout <= 4'b1110;
                6'd16   : dout <= 4'b0010;
                6'd17   : dout <= 4'b1110;
                6'd18   : dout <= 4'b0010;
                6'd19   : dout <= 4'b1110;
                6'd20   : dout <= 4'b1010;
                6'd21   : dout <= 4'b1010;
                6'd22   : dout <= 4'b1110;
                6'd23   : dout <= 4'b0010;
                6'd24   : dout <= 4'b0010;
                6'd25   : dout <= 4'b1110;
                6'd26   : dout <= 4'b1000;
                6'd27   : dout <= 4'b1110;
                6'd28   : dout <= 4'b0010;
                6'd29   : dout <= 4'b1110;
                6'd30   : dout <= 4'b1000;
                6'd31   : dout <= 4'b1000;
                6'd32   : dout <= 4'b1110;
                6'd33   : dout <= 4'b1010;
                6'd34   : dout <= 4'b1110;
                6'd35   : dout <= 4'b1110;
                6'd36   : dout <= 4'b0010;
                6'd37   : dout <= 4'b0100;
                6'd38   : dout <= 4'b1000;
                6'd39   : dout <= 4'b1000;
                6'd40   : dout <= 4'b1110;
                6'd41   : dout <= 4'b1010;
                6'd42   : dout <= 4'b1110;
                6'd43   : dout <= 4'b1010;
                6'd44   : dout <= 4'b1110;
                6'd45   : dout <= 4'b1110;
                6'd46   : dout <= 4'b1010;
                6'd47   : dout <= 4'b1110;
                6'd48   : dout <= 4'b0010;
                6'd49   : dout <= 4'b0010;
                6'd50   : dout <= 4'b0000;
                6'd51   : dout <= 4'b0100;
                6'd52   : dout <= 4'b0000;
                6'd53   : dout <= 4'b0100;
                6'd54   : dout <= 4'b0000;
                6'd55   : dout <= 4'b0000;
                6'd56   : dout <= 4'b0000;
                6'd57   : dout <= 4'b0000;
                6'd58   : dout <= 4'b0000;
                6'd59   : dout <= 4'b0000;
                default : dout <= 4'b1110;
            endcase
        end

endmodule


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

`default_nettype none

`define RGB [5:0] // RrGgBb order

module tt_um_algofoogle_vga (
    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
);
// >>> Module Implementation Begin

// <<< Module Implementation End
endmodule





Reference solution:
rtl/generated.v: 
  localparam kClouds        = 64;
  localparam kGrassTop      = 384;
  localparam kDarkGrassTop  = 390;
  localparam kDirtShadow    = kGrassTop + 24;
  localparam kDirtTop       = kDirtShadow + 6;
  localparam kPlayerWidth   = 32;
  localparam kPlayerHeight  = 32;
  localparam kPlayerRadius1 = 16;
  localparam kPlayerRadius2 = 13;
  localparam kRangeX        = 640 - kPlayerWidth;
  localparam kRangeY        = kGrassTop - kPlayerHeight;
  localparam kSpeedX        = 9;
  localparam kInitialVelY   = 21;

  wire reset = ~rst_n;
  wire clock_adj_hrs        = ui_in[0];
  wire clock_adj_min        = ui_in[1];
  wire clock_adj_sec        = ui_in[2];
  wire pmod_select          = ui_in[3]; // 0=Tiny VGA, 1=Matt's VGA Clock.
  wire show_clock           = ui_in[4];
  wire video_timing_mode    = ui_in[7];
  wire hsync;
  wire vsync;
  wire [1:0] rr,gg,bb;
  wire [9:0] h,v;
  wire hmax,vmax, hblank,vblank;
  wire frame_end = hmax & vmax;
  wire visible; // Whether the display is in the visible region, or blanking region.

  // Tiny VGA PMOD wiring, with 'visible' used for blanking:
  assign uo_out =
    pmod_select ? {rr, gg, bb, vsync, hsync} :
                  {hsync, {3{visible}} & {bb[0], gg[0], rr[0]}, vsync, {3{visible}} & {bb[1], gg[1], rr[1]}};

  assign uio_out = {
    3'b000, // Unused.
    visible,
    vblank,
    hblank,
    vmax,
    hmax
  };
  assign uio_oe  = 8'b0001_1111; // Top 3 bidir pins are inputs, rest are outputs.

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

  vga_sync vga_sync(
    .clk      (clk),
    .reset    (reset),
    .mode     (video_timing_mode),
    .o_hsync  (hsync),
    .o_vsync  (vsync),
    .o_hpos   (h),
    .o_vpos   (v),
    .o_hmax   (hmax),
    .o_vmax   (vmax),
    .o_hblank (hblank),
    .o_vblank (vblank),
    .o_visible(visible)
  );

  reg signed [7:0] ydelta;
  reg ydir;
  reg signed [11:0] pxm, pym;
  // Player position:
  wire [9:0] px = pxm[11:2];//, py;
  wire [9:0] py = pym[9:0];
  reg dx; // 0=left, 1=right

  reg [10:0] product_comp;
  reg product_comp_dir;

  // X direction control:
  always @(posedge clk) begin
    if (reset) begin
      dx <= 1;
    end else if (px >= kRangeX) begin
      dx <= 0; // Move left.
    end else if (px <= 0) begin
      dx <= 1; // Move right.
    end
  end

  // X position control:
  always @(posedge clk) begin
    if (reset) begin
      pxm <= 0;
      pym <= 0;
      product_comp <= 9;
      product_comp_dir <= 1;
      ydelta <= kInitialVelY;
      ydir <= 0;
      pym <= 0;
    end else if (frame_end) begin
      // Update for next frame:

      if (dx) begin
        pxm <= pxm + kSpeedX;
      end else begin
        pxm <= pxm - kSpeedX;
      end

      if (ydelta < 0 && pym[11:8]==0 && pym[7:0] <= {-ydelta}) begin
        pym <= 0;//pym - {{4{ydelta[7]}}, ydelta};
        ydelta <= 17 + {5'd0,px[2:0]}; // Makes the next bounce height look a little random.
      end else begin
        pym <= pym + {{4{ydelta[7]}}, ydelta};
        ydelta <= ydelta - 1;
      end

      if (product_comp_dir) begin
        if (product_comp >= 200) begin
          product_comp_dir <= 0;
        end else begin
          product_comp <= product_comp + 10;
        end
      end else begin
        if (product_comp < 20) begin
          product_comp_dir <= 1;
        end else begin
          product_comp <= product_comp - 10;
        end
      end

    end
  end

  localparam `RGB zenith        = 6'b00_01_11; // Light blue.
  localparam `RGB sky           = 6'b01_10_11; // Bright blue.
  localparam `RGB grass         = 6'b01_10_00; // Lively green.
  localparam `RGB bright_grass  = 6'b01_11_00; // Bright green.
  localparam `RGB dark_grass1   = 6'b00_10_00; // Dark green.
  localparam `RGB dark_grass2   = 6'b00_01_00; // Darker green.
  localparam `RGB dirt_shadow   = 6'b01_00_00; // Dark brown.
  localparam `RGB dirt          = 6'b10_01_00; // Medium brown.
  localparam `RGB player_heart  = 6'b11_00_00; // Bright red.
  localparam `RGB player_ring   = 6'b10_00_00; // Red.
  localparam `RGB shadow        = 6'b00_00_00; // Black.


  wire signed [9:0] pxo = h-(kPlayerWidth/2)-px;
  wire signed [4:0] psubx = pxo[4:0];
  wire signed [9:0] pyo = v-(kPlayerHeight/2)+py-kGrassTop;
  wire signed [4:0] psuby = pyo[4:0];
  wire signed [10:0] product = psubx*psubx + psuby*psuby;

  wire in_player_box =
    (h >= px) && (h < px+kPlayerWidth) &&
    (v >= kGrassTop-py-kPlayerHeight) && (v < kGrassTop-py);

  wire in_player_ring  = in_player_box && (product < (kPlayerRadius1*kPlayerRadius1-15) );
  wire in_player_heart = in_player_box && (product < product_comp); //(kPlayerRadius2*kPlayerRadius2-15) );

  wire in_grass       = (v >= kGrassTop);
  wire in_dark_grass  = (v >= kDarkGrassTop);
  wire in_dirt        = (v >= kDirtTop);
  wire in_dirt_shadow = (v >= kDirtShadow);
  wire in_clouds      = (v <  kClouds);

  wire `RGB clock_rgb, clock_shadow_rgb;

  wire [3:0] clock_sec_u;
  wire [2:0] clock_sec_d;
  wire [3:0] clock_min_u;
  wire [2:0] clock_min_d;
  wire [3:0] clock_hrs_u;
  wire [1:0] clock_hrs_d;
  wire [2:0] clock_color_offset;

  clock_logic matt_venn_clock (
    .clk          (clk),
    .reset        (reset),
    .adj_hrs      (clock_adj_hrs),
    .adj_min      (clock_adj_min),
    .adj_sec      (clock_adj_sec),
    .but_clk_en   (frame_end),
    .sec_u        (clock_sec_u),
    .sec_d        (clock_sec_d),
    .min_u        (clock_min_u),
    .min_d        (clock_min_d),
    .hrs_u        (clock_hrs_u),
    .hrs_d        (clock_hrs_d),
    .color_offset (clock_color_offset)
  );

  vga_clock_gen matt_venn_vga (
    .clk          (clk),
    .reset        (reset),
    .x_px         (h),   // X position for actual pixel.
    .y_px         (v),   // Y position for actual pixel.
    .activevideo  (visible),
    .sec_u        (clock_sec_u),
    .sec_d        (clock_sec_d),
    .min_u        (clock_min_u),
    .min_d        (clock_min_d),
    .hrs_u        (clock_hrs_u),
    .hrs_d        (clock_hrs_d),
    .color_offset (clock_color_offset),
    .rrggbb       (clock_rgb)
  );

  // Used for creating a shadow under clock digits:
  vga_clock_gen matt_venn_vga_shadow (
    .clk          (clk),
    .reset        (reset),
    .x_px         (h-4),   // X position for actual pixel, offset by 16 for shadow.
    .y_px         (v-4),   // Y position for actual pixel, offset by 16 for shadow.
    .activevideo  (visible),
    .sec_u        (clock_sec_u),
    .sec_d        (clock_sec_d),
    .min_u        (clock_min_u),
    .min_d        (clock_min_d),
    .hrs_u        (clock_hrs_u),
    .hrs_d        (clock_hrs_d),
    .color_offset (clock_color_offset),
    .rrggbb       (clock_shadow_rgb)
  );

  wire in_clock       = show_clock && (clock_rgb != 0);
  wire in_clock_shade = show_clock && (clock_shadow_rgb != 0);
  wire frizz          = ((h[1:0]^v[1:0]) != v[3:2]);

  wire `RGB rgb =
    in_dirt         ? dirt :
    in_dirt_shadow  ? dirt_shadow :
    in_dark_grass   ? (frizz ? dark_grass1 : dark_grass2) :
    in_grass        ? (frizz ? grass : bright_grass) :
    in_player_heart ? player_heart :
    in_player_ring  ? player_ring :
    in_clock        ? clock_rgb :
    in_clock_shade  ? shadow :
    in_clouds       ? ( ( (!frizz) && (h[2]^v[2] || (v[5]==0)) || ((v[6:2]==0) && (h[0]^v[0]))) ? zenith : sky) :
                      sky;

  assign {rr,gg,bb} = rgb;