module top_module(
    input clk,
    input areset,

    input predict_valid,
    input [6:0] predict_pc,
    output reg predict_taken,
    output reg [6:0] predict_history,

    input train_valid,
    input train_taken,
    input train_mispredicted,
    input [6:0] train_history,
    input [6:0] train_pc
);

    reg [1:0] PHT[127:0]; // Pattern History Table with 128 entries of 2-bit saturating counters
    reg [6:0] global_history; // 7-bit global history register

    wire [6:0] predict_index = predict_pc ^ global_history; // Hashing the PC and global history
    wire [6:0] train_index = train_pc ^ train_history; // Hashing for training

    always @(posedge clk or posedge areset) begin
        if (areset) begin
            global_history <= 7'b0;
            for (int i = 0; i < 128; i++) begin
                PHT[i] <= 2'b00; // Initialize PHT to 0 (strongly not taken)
            end
        end else begin
            if (train_valid) begin
                if (train_mispredicted) begin
                    // Recover history for misprediction
                    global_history <= train_history;
                end else begin
                    // Update history on correct prediction
                    global_history <= {global_history[5:0], train_taken};
                end

                // Update PHT based on training outcome
                case (PHT[train_index])
                    2'b00: PHT[train_index] <= train_taken ? 2'b01 : 2'b00;
                    2'b01: PHT[train_index] <= train_taken ? 2'b10 : 2'b00;
                    2'b10: PHT[train_index] <= train_taken ? 2'b11 : 2'b01;
                    2'b11: PHT[train_index] <= train_taken ? 2'b11 : 2'b10;
                endcase
            end

            // Predict
            if (predict_valid) begin
                predict_taken <= (PHT[predict_index] == 2'b10 || PHT[predict_index] == 2'b11);
                predict_history <= global_history;
            end
        end
    end
endmodule

module top_module(
    input clk,
    input areset,

    input predict_valid,
    input [6:0] predict_pc,
    output predict_taken,
    output [6:0] predict_history,

    input train_valid,
    input train_taken,
    input train_mispredicted,
    input [6:0] train_history,
    input [6:0] train_pc
);

    // Parameters
    parameter PHT_SIZE = 128;
    parameter BHT_SIZE = 7;

    // PHT and BHT
    reg [1:0] PHT [0:PHT_SIZE-1];
    reg [BHT_SIZE-1:0] BHT;

    // Index and next state logic
    wire [6:0] index;
    wire [6:0] hashed_pc;
    assign hashed_pc = predict_pc ^ BHT; // XOR based hasher
    assign index = hashed_pc[6:0];

    // Prediction
    assign predict_taken = (PHT[index] > 1); // Taken if state > 1

    always @(posedge clk or posedge areset) begin
        if (areset) begin
            // Reset PHT and BHT
            integer i;
            for (i = 0; i < PHT_SIZE; i = i + 1) begin
                PHT[i] <= 2'b00; // Initialize to 'Strongly Not Taken'
            end
            BHT <= 7'b0;
        end
        else begin
            // Training
            if (train_valid) begin
                if (train_mispredicted) begin
                    BHT <= train_history; // Recover history on misprediction
                end
                // Update PHT on training result
                if (train_taken) begin
                    if (PHT[train_pc] < 2'b11) PHT[train_pc] <= PHT[train_pc] + 1; // +1 to state
                end else begin
                    if (PHT[train_pc] > 2'b00) PHT[train_pc] <= PHT[train_pc] - 1; // -1 to state
                end
            end

            // Prediction update
            if (predict_valid) begin
                // Update BHT based on prediction
                BHT <= (BHT << 1) | predict_taken; // Shift and update BHT
            end
        end
    end

    // Output current state of BHT
    assign predict_history = BHT;

endmodule

module top_module(
    input clk,
    input areset,

    input predict_valid,
    input [6:0] predict_pc,
    output reg predict_taken,
    output reg [6:0] predict_history,

    input train_valid,
    input train_taken,
    input train_mispredicted,
    input [6:0] train_history,
    input [6:0] train_pc
);

    reg [1:0] PHT [0:127]; // Pattern History Table
    reg [6:0] global_history; // Global Branch History Register

    wire [6:0] index;
    assign index = (predict_pc ^ global_history) % 128;

    always @(posedge clk or posedge areset) begin
        if (areset) begin
            global_history <= 7'b0;
            for (int i = 0; i < 128; i = i + 1) begin
                PHT[i] <= 2'b00; // Initialize PHT to "SNT"
            end
        end else begin
            // Prediction Logic
            if (predict_valid) begin
                predict_taken <= PHT[index][1]; // Taken if state is 2'b10 or 2'b11
                predict_history <= global_history;
            end

            // Training Logic
            if (train_valid) begin
                if (train_taken) begin
                    if (PHT[index] != 2'b11)
                        PHT[index] <= PHT[index] + 1; // Increment if not max
                end else begin
                    if (PHT[index] != 2'b00)
                        PHT[index] <= PHT[index] - 1; // Decrement if not min
                end

                // Update global history
                if (train_mispredicted) begin
                    global_history <= train_history; // Recover the global history
                end else begin
                    global_history <= {global_history[5:0], train_taken}; // Shift in new outcome
                end
            end
        end
    end

endmodule

module top_module(
    input clk,
    input areset,

    input predict_valid,
    input [6:0] predict_pc,
    output reg predict_taken,
    output reg [6:0] predict_history,

    input train_valid,
    input train_taken,
    input train_mispredicted,
    input [6:0] train_history,
    input [6:0] train_pc
);

    reg [1:0] PHT [127:0]; // Pattern History Table
    reg [6:0] global_history; // Global history register
    wire [6:0] index; // Index for PHT
    reg [1:0] predicted_state; // Predicted state for the branch

    assign index = predict_pc ^ global_history; // Calculate the index using XOR

    always @(posedge clk or posedge areset) begin
        if (areset) begin
            global_history <= 7'b0; // Reset global history
            predict_taken <= 1'b0; // Reset prediction
            predict_history <= 7'b0; // Reset predicted history
            // Reset PHT entries to weakly not taken (00)
            for (integer i = 0; i < 128; i = i + 1) begin
                PHT[i] <= 2'b00;
            end
        end else begin
            // Prediction Logic
            if (predict_valid) begin
                predicted_state <= PHT[index];
                predict_taken <= predicted_state[1]; // Most significant bit indicates taken
                predict_history <= global_history; // Output current history
            end

            // Training Logic
            if (train_valid) begin
                // Update PHT
                if (train_taken) begin
                    if (PHT[index] != 2'b11) PHT[index] <= PHT[index] + 1;
                end else begin
                    if (PHT[index] != 2'b00) PHT[index] <= PHT[index] - 1;
                end

                // Update global history
                if (train_mispredicted) begin
                    global_history <= train_history; // Recover history for misprediction
                end else begin
                    global_history <= {global_history[5:0], train_taken}; // Shift in the new prediction
                end
            end
        end
    end
endmodule

module top_module(
	input clk,
	input areset,

	input predict_valid,
	input [6:0] predict_pc,
	output reg predict_taken,
	output reg [6:0] predict_history,

	input train_valid,
	input train_taken,
	input train_mispredicted,
	input [6:0] train_history,
	input [6:0] train_pc
);

	// Parameters
	localparam TABLE_SIZE = 128;
	localparam COUNTER_WIDTH = 2;
	localparam MAX_COUNTER_VAL = (1 << COUNTER_WIDTH) - 1;

	// State variables
	reg [COUNTER_WIDTH-1:0] PHT [0:TABLE_SIZE-1];
	reg [6:0] global_history;
	reg [6:0] next_global_history;

	// Hashing the PC and global history to get the index
	wire [6:0] index = (predict_pc ^ global_history) % TABLE_SIZE;

	// Output prediction based on current PHT and global history
	always @(*) begin
		if (predict_valid) begin
			predict_taken = (PHT[index] >> 1); // Taken if the counter is 2 or 3
			predict_history = global_history;
		end
		else begin
			predict_taken = 0;
			predict_history = global_history;
		end
	end

	// Sequential block for updating the states
	always @(posedge clk or posedge areset) begin
		if (areset) begin
			// Resetting the PHT and history
			integer i;
			for (i = 0; i < TABLE_SIZE; i = i + 1) begin
				PHT[i] <= 0;
			end
			global_history <= 0;
		end else begin
			// Training logic
			if (train_valid) begin
				// Update the PHT
				if (train_mispredicted) begin
					PHT[index] <= (PHT[index] > 0) ? (PHT[index] - 1) : 0; // Decrease on mispredict
					global_history <= train_history; // Recover history on mispredicted
				end else begin
					PHT[index] <= (PHT[index] < MAX_COUNTER_VAL) ? (PHT[index] + 1) : MAX_COUNTER_VAL; // Increase on correct
				end
			end

			// Update global history based on the prediction at next clock edge
			if (predict_valid) begin
				global_history <= {global_history[5:0], predict_taken};
			end
		end
	end
endmodule

module top_module(
	input clk,
	input areset,

	input predict_valid,
	input [6:0] predict_pc,
	output reg predict_taken,
	output reg [6:0] predict_history,

	input train_valid,
	input train_taken,
	input train_mispredicted,
	input [6:0] train_history,
	input [6:0] train_pc
);

    reg [1:0] pht [127:0]; // Pattern History Table (PHT) with 128 entries
    reg [6:0] ghr; // Global History Register
    wire [6:0] hash_index;

    assign hash_index = predict_pc ^ ghr; // Hashing with XOR for index
    wire [6:0] train_hash_index = train_pc ^ train_history; // Hash index for training

    always @(posedge clk or posedge areset) begin
        if (areset) begin
            ghr <= 7'b0; // Reset GHR
            // Reset all PHT entries to 00 (strongly not taken)
            integer i;
            for (i = 0; i < 128; i = i + 1) begin
                pht[i] <= 2'b00;
            end
        end else begin
            // Training stage
            if (train_valid) begin
                if (train_mispredicted) begin
                    ghr <= train_history; // Recover GHR on misprediction
                end
                case (pht[train_hash_index])
                    2'b00: pht[train_hash_index] <= (train_taken ? 2'b01 : 2'b00);
                    2'b01: pht[train_hash_index] <= (train_taken ? 2'b10 : 2'b00);
                    2'b10: pht[train_hash_index] <= (train_taken ? 2'b11 : 2'b01);
                    2'b11: pht[train_hash_index] <= 2'b11; // Strongly taken
                endcase
            end

            // Prediction stage (after training updates)
            if (predict_valid) begin
                predict_taken <= (pht[hash_index] > 1) ? 1'b1 : 1'b0; // Predict taken if state is 2 or 3
                predict_history <= ghr; // Output current GHR
                ghr <= {ghr[5:0], predict_taken}; // Update GHR with predicted outcome
            end
        end
    end
endmodule

module top_module(
    input clk,
    input areset,

    input predict_valid,
    input [6:0] predict_pc,
    output reg predict_taken,
    output reg [6:0] predict_history,

    input train_valid,
    input train_taken,
    input train_mispredicted,
    input [6:0] train_history,
    input [6:0] train_pc
);

    reg [1:0] PHT [127:0]; // Pattern History Table with 128 entries
    reg [6:0] global_history; // 7-bit global branch history register
    wire [6:0] index; // Index for PHT

    assign index = (predict_pc ^ global_history) [6:0]; // XOR for 7-bit index

    always @(posedge clk or posedge areset) begin
        if (areset) begin
            global_history <= 7'b0;
            predict_taken <= 1'b0;
            predict_history <= 7'b0;
            for (integer i = 0; i < 128; i = i + 1) begin
                PHT[i] <= 2'b00; // Reset PHT
            end
        end else begin
            if (train_valid) begin
                // Update PHT based on training
                if (train_taken) begin
                    if (PHT[train_pc ^ train_history] < 2'b11)
                        PHT[train_pc ^ train_history] <= PHT[train_pc ^ train_history] + 1;
                end else begin
                    if (PHT[train_pc ^ train_history] > 2'b00)
                        PHT[train_pc ^ train_history] <= PHT[train_pc ^ train_history] - 1;
                end
                // Update global history
                if (train_mispredicted) begin
                    global_history <= train_history; // Recover to the state after misprediction
                end else begin
                    global_history <= {global_history[5:0], train_taken}; // Shift and update
                end
            end

            if (predict_valid) begin
                // Prediction logic
                predict_taken <= (PHT[index] >= 2'b10); // Predict taken if 2-bit counter indicates
                predict_history <= global_history; // Output current history
            end
        end
    end
endmodule

module top_module(
    input clk,
    input areset,

    input predict_valid,
    input [6:0] predict_pc,
    output reg predict_taken,
    output reg [6:0] predict_history,

    input train_valid,
    input train_taken,
    input train_mispredicted,
    input [6:0] train_history,
    input [6:0] train_pc
);
    reg [1:0] PHT[127:0]; // Pattern History Table
    reg [6:0] history_reg; // Global History Register
    wire [6:0] index; // Index for PHT

    assign index = predict_pc ^ history_reg; // XOR for hashing

    always @(posedge clk or posedge areset) begin
        if (areset) begin
            history_reg <= 7'b0;
            // Initialize PHT to weakly not taken (00)
            integer i;
            for (i = 0; i < 128; i = i + 1) begin
                PHT[i] <= 2'b00;
            end
        end else begin
            if (train_valid) begin
                if (train_mispredicted) begin
                    history_reg <= train_history; // recover on misprediction
                end else begin
                    history_reg <= {history_reg[5:0], train_taken}; // update history
                end

                // Update PHT based on training outcome
                case (PHT[train_pc ^ history_reg])
                    2'b00: PHT[train_pc ^ train_history] <= train_taken ? 2'b01 : 2'b00;
                    2'b01: PHT[train_pc ^ train_history] <= train_taken ? 2'b10 : 2'b00;
                    2'b10: PHT[train_pc ^ train_history] <= train_taken ? 2'b11 : 2'b01;
                    2'b11: PHT[train_pc ^ train_history] <= train_taken ? 2'b11 : 2'b10;
                endcase
            end

            if (predict_valid) begin
                predict_taken <= PHT[index][1]; // Predict based on current PHT state
                predict_history <= history_reg; // Output current history
                history_reg <= {history_reg[5:0], predict_taken}; // Update history with prediction
            end
        end
    end
endmodule

module top_module(
	input clk,
	input areset,

	input predict_valid,
	input [6:0] predict_pc,
	output reg predict_taken,
	output reg [6:0] predict_history,

	input train_valid,
	input train_taken,
	input train_mispredicted,
	input [6:0] train_history,
	input [6:0] train_pc
);

	reg [6:0] ghr; // Global History Register
	reg [1:0] pht [127:0]; // Pattern History Table with 128 entries
	wire [6:0] index; // Index for PHT

	assign index = (predict_pc ^ ghr) & 7'b0111111; // XOR to get index

	// Prediction Logic
	always @(*) begin
		if (predict_valid) begin
			predict_taken = (pht[index] > 1) ? 1 : 0; // Predict taken if counter > 1
			predict_history = ghr; // Output the current state of GHR
		end
	end

	// Training Logic
	always @(posedge clk or posedge areset) begin
		if (areset) begin
			ghr <= 7'b0; // Reset GHR
			// Reset all PHT entries to 2'b00
			for (integer i = 0; i < 128; i = i + 1) begin
				pht[i] <= 2'b00;
			end
		end else begin
			if (train_valid) begin
				// Update PHT based on training outcome
				if (train_taken && pht[index] < 2'b11)
					pht[index] <= pht[index] + 1;
				else if (!train_taken && pht[index] > 2'b00)
					pht[index] <= pht[index] - 1;

				// Update GHR
				if (train_mispredicted) begin
					ghr <= train_history; // Recover GHR state on misprediction
				end else begin
					ghr <= {ghr[5:0], train_taken}; // Shift in the actual outcome
				end
			end
		end
	end
endmodule

module top_module(
    input clk,
    input areset,

    input predict_valid,
    input [6:0] predict_pc,
    output reg predict_taken,
    output reg [6:0] predict_history,

    input train_valid,
    input train_taken,
    input train_mispredicted,
    input [6:0] train_history,
    input [6:0] train_pc
);

    reg [1:0] PHT [127:0]; // Pattern History Table
    reg [6:0] global_history; // Global history register

    wire [6:0] index;
    wire [1:0] pht_state;

    assign index = (predict_pc ^ global_history) [6:0];
    assign pht_state = PHT[index];

    always @(posedge clk or posedge areset) begin
        if (areset) begin
            global_history <= 7'b0;
            // Initialize PHT to weakly not taken state
            for (integer i = 0; i < 128; i = i + 1) begin
                PHT[i] <= 2'b01; // Weakly not taken
            end
        end else begin
            if (train_valid) begin
                if (train_mispredicted) begin
                    global_history <= train_history; // recover history on misprediction
                end else begin
                    global_history <= {global_history[5:0], train_taken}; // update history
                end

                // Update PHT based on training outcome
                case (PHT[train_pc ^ global_history])
                    2'b00: PHT[train_pc ^ global_history] <= train_taken ? 2'b01 : 2'b00; // Weakly not taken
                    2'b01: PHT[train_pc ^ global_history] <= train_taken ? 2'b10 : 2'b00; // Weakly taken
                    2'b10: PHT[train_pc ^ global_history] <= train_taken ? 2'b11 : 2'b01; // Strongly taken
                    2'b11: PHT[train_pc ^ global_history] <= train_taken ? 2'b11 : 2'b10; // Strongly not taken
                endcase
            end

            if (predict_valid) begin
                // Output the prediction based on PHT state
                predict_taken <= (pht_state[1] == 1'b1); // Taken if state is 2'b10 or 2'b11
                predict_history <= global_history; // Output current history
            end
        end
    end

endmodule

module top_module(
    input clk,
    input areset,

    input predict_valid,
    input [6:0] predict_pc,
    output reg predict_taken,
    output reg [6:0] predict_history,

    input train_valid,
    input train_taken,
    input train_mispredicted,
    input [6:0] train_history,
    input [6:0] train_pc
);

    reg [1:0] PHT [0:127]; // Pattern History Table with 128 entries of 2-bit saturating counters
    reg [6:0] ghr; // Global History Register

    wire [6:0] index = (predict_pc ^ ghr) & 7'b0111111; // Hashing PC and GHR into 7-bit index

    always @(posedge clk or posedge areset) begin
        if (areset) begin
            ghr <= 7'b0;
            // Initialize PHT entries
            integer i;
            for (i = 0; i < 128; i = i + 1) begin
                PHT[i] <= 2'b00;
            end
        end else begin
            // Prediction logic
            if (predict_valid) begin
                predict_taken <= (PHT[index] >= 2'b01);
                predict_history <= ghr;
            end

            // Training logic
            if (train_valid) begin
                // Update PHT based on training outcome
                if (train_taken) begin
                    if (PHT[train_pc ^ train_history] < 2'b11)
                        PHT[train_pc ^ train_history] <= PHT[train_pc ^ train_history] + 1;
                end else begin
                    if (PHT[train_pc ^ train_history] > 2'b00)
                        PHT[train_pc ^ train_history] <= PHT[train_pc ^ train_history] - 1;
                end

                // Update GHR for mispredicted branches
                if (train_mispredicted) begin
                    ghr <= train_history; // Reset GHR to history state after misprediction
                end else begin
                    ghr <= {ghr[5:0], train_taken}; // Shift in new outcome
                end
            end
        end
    end
endmodule

module top_module(
    input clk,
    input areset,

    input predict_valid,
    input [6:0] predict_pc,
    output reg predict_taken,
    output reg [6:0] predict_history,

    input train_valid,
    input train_taken,
    input train_mispredicted,
    input [6:0] train_history,
    input [6:0] train_pc
);

    reg [1:0] pht[127:0]; // Pattern History Table (PHT) with 128 entries
    reg [6:0] bhr; // Global Branch History Register

    wire [6:0] hashed_index;
    wire [1:0] pht_state;

    assign hashed_index = (predict_pc ^ bhr) % 128; // Hashing using XOR for the index
    assign pht_state = pht[hashed_index];

    // Prediction Logic
    always @(posedge clk or posedge areset) begin
        if (areset) begin
            bhr <= 7'b0;
            predict_taken <= 1'b0;
            predict_history <= 7'b0;
            integer i;
            for (i = 0; i < 128; i = i + 1) begin
                pht[i] <= 2'b00; // Initialize PHT entries
            end
        end else begin
            // Update prediction history
            if (predict_valid) begin
                predict_history <= bhr;
                case (pht_state)
                    2'b00: predict_taken <= 1'b0; // Strongly Not Taken
                    2'b01: predict_taken <= 1'b0; // Weakly Not Taken
                    2'b10: predict_taken <= 1'b1; // Weakly Taken
                    2'b11: predict_taken <= 1'b1; // Strongly Taken
                endcase
            end

            // Training Logic
            if (train_valid) begin
                if (train_mispredicted) begin
                    bhr <= train_history; // Restore BHR for misprediction
                end else begin
                    bhr <= {bhr[5:0], train_taken}; // Shift BHR and add new prediction
                end
                // Update PHT based on training
                case (pht[hashed_index])
                    2'b00: pht[hashed_index] <= train_taken ? 2'b01 : 2'b00;
                    2'b01: pht[hashed_index] <= train_taken ? 2'b10 : 2'b00;
                    2'b10: pht[hashed_index] <= train_taken ? 2'b11 : 2'b01;
                    2'b11: pht[hashed_index] <= train_taken ? 2'b11 : 2'b10;
                endcase
            end
        end
    end

endmodule

module top_module(
    input clk,
    input areset,

    input predict_valid,
    input [6:0] predict_pc,
    output reg predict_taken,
    output reg [6:0] predict_history,

    input train_valid,
    input train_taken,
    input train_mispredicted,
    input [6:0] train_history,
    input [6:0] train_pc
);

    // Define constants
    localparam PHT_SIZE = 128;
    localparam COUNTER_MAX = 3;

    // Saturating counter states
    reg [1:0] pht[PHT_SIZE-1:0]; // Pattern history table
    reg [6:0] ghr;               // Global history register
    wire [6:0] index;           // Hashed index
    wire [1:0] pred_counter;    // Predicted counter for the given PC and GHR

    // Hashing PC and GHR to get the index
    assign index = (predict_pc ^ ghr) % PHT_SIZE; // xor for hashing

    // Prediction logic
    always @(posedge clk or posedge areset) begin
        if (areset) begin
            ghr <= 7'b0;
            integer i;
            for (i = 0; i < PHT_SIZE; i = i + 1) begin
                pht[i] <= 2'b00; // Initialize PHT to weakly not taken
            end
        end else begin
            if (train_valid) begin
                // Training logic
                if (train_mispredicted) begin
                    ghr <= train_history; // Recover GHR on misprediction
                end else begin
                    ghr <= {ghr[5:0], train_taken}; // Update GHR
                end

                // Update PHT
                if (train_taken) begin
                    if (pht[train_pc ^ ghr] < COUNTER_MAX)
                        pht[train_pc ^ ghr] <= pht[train_pc ^ ghr] + 1;
                end else begin
                    if (pht[train_pc ^ ghr] > 0)
                        pht[train_pc ^ ghr] <= pht[train_pc ^ ghr] - 1;
                end
            end

            // Prediction logic
            if (predict_valid) begin
                predict_taken <= (pht[index] >= 2'b10); // Taken if counter is two or three
                predict_history <= ghr;
            end
        end
    end
endmodule

module top_module(
    input clk,
    input areset,

    input predict_valid,
    input [6:0] predict_pc,
    output reg predict_taken,
    output reg [6:0] predict_history,

    input train_valid,
    input train_taken,
    input train_mispredicted,
    input [6:0] train_history,
    input [6:0] train_pc
);

    reg [1:0] PHT[127:0]; // Pattern History Table
    reg [6:0] global_history; // Global History Register
    reg [6:0] index; // Index for PHT

    always @(posedge clk or posedge areset) begin
        if (areset) begin
            global_history <= 7'b0;
            for (int i = 0; i < 128; i = i + 1) begin
                PHT[i] <= 2'b00; // Initialize PHT entries to weakly not taken
            end
        end else begin
            // Training logic
            if (train_valid) begin
                index <= (train_pc ^ global_history) & 7'h7F; // Calculate index (7 bits)
                if (train_mispredicted) begin
                    // Recover global history on misprediction
                    global_history <= train_history;
                end

                // Update PHT
                if (train_taken) begin
                    if (PHT[index] < 2'b11) PHT[index] <= PHT[index] + 1; // Saturate to 2'b11
                end else begin
                    if (PHT[index] > 2'b00) PHT[index] <= PHT[index] - 1; // Saturate to 2'b00
                end
            end

            // Prediction logic
            if (predict_valid) begin
                index <= (predict_pc ^ global_history) & 7'h7F; // Calculate index (7 bits)
                predict_taken <= PHT[index][1]; // Output prediction
                predict_history <= global_history; // Output current global history
                // Update global history with the predicted value
                global_history <= {global_history[5:0], predict_taken};
            end
        end
    end
endmodule

module top_module(
    input clk,
    input areset,

    input predict_valid,
    input [6:0] predict_pc,
    output reg predict_taken,
    output reg [6:0] predict_history,

    input train_valid,
    input train_taken,
    input train_mispredicted,
    input [6:0] train_history,
    input [6:0] train_pc
);

    reg [1:0] PHT [127:0]; // Pattern History Table
    reg [6:0] GBR; // Global Branch Register
    wire [6:0] index; // Hashed index
    reg [1:0] prediction_state; // State of the counter

    // Hash function to get index
    assign index = (predict_pc ^ GBR) [6:0];

    always @(posedge clk or posedge areset) begin
        if (areset) begin
            GBR <= 7'b0;
            for (int i = 0; i < 128; i = i + 1) begin
                PHT[i] <= 2'b00; // Initialize all counters to 0
            end
            predict_taken <= 1'b0;
            predict_history <= 7'b0;
        end else begin
            if (train_valid) begin
                // Training phase: update PHT
                if (train_mispredicted) begin
                    // Recover GBR to state after misprediction
                    GBR <= train_history;
                end

                // Update the PHT entry based on actual outcome
                if (train_taken) begin
                    if (PHT[train_pc ^ GBR] < 2'b11)
                        PHT[train_pc ^ GBR] <= PHT[train_pc ^ GBR] + 1;
                end else begin
                    if (PHT[train_pc ^ GBR] > 2'b00)
                        PHT[train_pc ^ GBR] <= PHT[train_pc ^ GBR] - 1;
                end
            end

            if (predict_valid) begin
                // Prediction phase
                predict_taken <= (PHT[index] >= 2'b10); // Predict taken if counter is 2 or higher
                predict_history <= GBR; // Current state of GBR
            end

            // Update GBR for predicted branch
            if (predict_valid) begin
                GBR <= {GBR[5:0], predict_taken}; // Shift left and add predicted outcome
            end
        end
    end
endmodule

module top_module(
    input clk,
    input areset,

    input predict_valid,
    input [6:0] predict_pc,
    output reg predict_taken,
    output reg [6:0] predict_history,

    input train_valid,
    input train_taken,
    input train_mispredicted,
    input [6:0] train_history,
    input [6:0] train_pc
);

    reg [6:0] global_history;
    reg [1:0] pht [127:0]; // Pattern History Table
    reg [6:0] predicted_history;
    wire [6:0] index;

    assign index = (predict_pc ^ global_history) % 128;

    always @(posedge clk or posedge areset) begin
        if (areset) begin
            global_history <= 7'b0;
            predict_taken <= 1'b0;
            predict_history <= 7'b0;
            for (integer i = 0; i < 128; i = i + 1) begin
                pht[i] <= 2'b00;
            end
        end else begin
            if (train_valid) begin
                if (train_mispredicted) begin
                    global_history <= train_history;
                end else begin
                    global_history <= {global_history[5:0], train_taken};
                end

                // Update PHT
                case (train_taken)
                    1'b0: if (pht[train_pc ^ global_history] > 0) pht[train_pc ^ global_history] <= pht[train_pc ^ global_history] - 1;
                    1'b1: if (pht[train_pc ^ global_history] < 3) pht[train_pc ^ global_history] <= pht[train_pc ^ global_history] + 1;
                endcase
            end

            if (predict_valid) begin
                predict_taken <= (pht[index] > 1);
                predict_history <= global_history;
            end

            // Update global history with the predicted value
            if (predict_valid) begin
                global_history <= {global_history[5:0], predict_taken};
            end
        end
    end
endmodule

module top_module(
	input clk,
	input areset,

	input predict_valid,
	input [6:0] predict_pc,
	output reg predict_taken,
	output reg [6:0] predict_history,

	input train_valid,
	input train_taken,
	input train_mispredicted,
	input [6:0] train_history,
	input [6:0] train_pc
);

	// Define parameters
	parameter LOG2_ENTRIES = 7;
	parameter NUM_ENTRIES = 128;
	parameter COUNTER_BITS = 2;

	// Define the pattern history table (PHT) and history register
	reg [COUNTER_BITS-1:0] pht [0:NUM_ENTRIES-1];
	reg [6:0] global_history;

	// Function to get the index into the PHT
	function [LOG2_ENTRIES-1:0] get_index(input [6:0] pc, input [6:0] history);
		begin
			get_index = (pc ^ history) % NUM_ENTRIES;
		end
	endfunction

	// Prediction logic
	always @(*) begin
		if (predict_valid) begin
			predict_taken = (pht[get_index(predict_pc, global_history)] >= 2'b10);
			predict_history = global_history;
		end else begin
			predict_taken = 1'b0;
			predict_history = 7'b0;
		end
	end

	// Training logic
	always @(posedge clk or posedge areset) begin
		if (areset) begin
			// Reset PHT and history
			integer i;
			for (i = 0; i < NUM_ENTRIES; i = i + 1) begin
				pht[i] <= 2'b00;
			end
			global_history <= 7'b0;
		end else begin
			if (train_valid) begin
				// Update PHT based on training
				if (train_taken) begin
					if (pht[get_index(train_pc, train_history)] < 2'b11) begin
						pht[get_index(train_pc, train_history)] <= pht[get_index(train_pc, train_history)] + 1;
					end
				end else begin
					if (pht[get_index(train_pc, train_history)] > 2'b00) begin
						pht[get_index(train_pc, train_history)] <= pht[get_index(train_pc, train_history)] - 1;
					end
				end

				// Update global history
				if (train_mispredicted) begin
					global_history <= train_history;  // Recover history on misprediction
				end else begin
					global_history <= {global_history[5:0], train_taken}; // Shift in new direction
				end
			end
		end
	end

endmodule

module top_module(
    input clk,
    input areset,

    input predict_valid,
    input [6:0] predict_pc,
    output reg predict_taken,
    output reg [6:0] predict_history,

    input train_valid,
    input train_taken,
    input train_mispredicted,
    input [6:0] train_history,
    input [6:0] train_pc
);

    reg [1:0] PHT [0:127]; // Pattern History Table with 128 entries
    reg [6:0] global_history; // Global history register

    wire [6:0] index; // Hashed index
    assign index = (predict_pc ^ global_history) [6:0];

    always @(posedge clk or posedge areset) begin
        if (areset) begin
            global_history <= 7'b0;
            predict_taken <= 1'b0;
            predict_history <= 7'b0;
            for (int i = 0; i < 128; i = i + 1) begin
                PHT[i] <= 2'b00; // Reset all PHT entries
            end
        end else begin
            // Prediction Logic
            if (predict_valid) begin
                predict_taken <= (PHT[index] > 1); // Taken if counter is 2 or 3
                predict_history <= global_history; // Current history provided
            end

            // Training Logic
            if (train_valid) begin
                if (train_mispredicted) begin
                    global_history <= train_history; // Recover history on misprediction
                end
                // Update PHT based on the actual taken information
                if (train_taken) begin
                    if (PHT[train_pc[6:0]] < 2'b11)
                        PHT[train_pc[6:0]] <= PHT[train_pc[6:0]] + 1; // Increment
                end else begin
                    if (PHT[train_pc[6:0]] > 2'b00)
                        PHT[train_pc[6:0]] <= PHT[train_pc[6:0]] - 1; // Decrement
                end
                global_history <= {global_history[5:0], train_taken}; // Update global history
            end else if (predict_valid) begin
                global_history <= {global_history[5:0], predict_taken}; // Update if just predicting
            end
        end
    end

endmodule

module top_module(
    input clk,
    input areset,

    input predict_valid,
    input [6:0] predict_pc,
    output reg predict_taken,
    output reg [6:0] predict_history,

    input train_valid,
    input train_taken,
    input train_mispredicted,
    input [6:0] train_history,
    input [6:0] train_pc
);

    reg [1:0] PHT[0:127]; // Pattern History Table with 128 entries of 2-bit saturating counters
    reg [6:0] global_history; // 7-bit Global Branch History Register

    wire [6:0] index; // Hashed index
    wire [1:0] current_state;
    wire [1:0] next_state;

    assign index = predict_pc ^ global_history;

    always @(posedge clk or posedge areset) begin
        if (areset) begin
            global_history <= 7'b0;
            for (integer i = 0; i < 128; i = i + 1) begin
                PHT[i] <= 2'b00; // Initialize PHT to 00 (strongly not taken)
            end
        end else begin
            if (train_valid) begin
                if (train_mispredicted) begin
                    // Recover to previous history if there was a misprediction
                    global_history <= train_history;
                end else begin
                    // Update global history
                    global_history <= {global_history[5:0], train_taken};
                end
                // Update the PHT based on the train outcome
                case (PHT[train_pc ^ global_history])
                    2'b00: PHT[train_pc ^ global_history] <= (train_taken) ? 2'b01 : 2'b00;
                    2'b01: PHT[train_pc ^ global_history] <= (train_taken) ? 2'b10 : 2'b00;
                    2'b10: PHT[train_pc ^ global_history] <= (train_taken) ? 2'b11 : 2'b01;
                    2'b11: PHT[train_pc ^ global_history] <= (train_taken) ? 2'b11 : 2'b10;
                endcase
            end

            if (predict_valid) begin
                predict_history <= global_history;
                case (PHT[index])
                    2'b00: predict_taken <= 1'b0;
                    2'b01: predict_taken <= 1'b0;
                    2'b10: predict_taken <= 1'b1;
                    2'b11: predict_taken <= 1'b1;
                endcase

                // Update global history with the prediction
                global_history <= {global_history[5:0], predict_taken};
            end
        end
    end

endmodule

module top_module(
    input clk,
    input areset,

    input predict_valid,
    input [6:0] predict_pc,
    output reg predict_taken,
    output reg [6:0] predict_history,

    input train_valid,
    input train_taken,
    input train_mispredicted,
    input [6:0] train_history,
    input [6:0] train_pc
);

    reg [1:0] PHT[127:0]; // Pattern History Table
    reg [6:0] global_history; // Global History Register

    wire [6:0] hashed_index;
    wire [1:0] predicted_state;

    assign hashed_index = predict_pc ^ global_history; // Hashed index using XOR
    assign predicted_state = PHT[hashed_index]; // Access the PHT

    always @(posedge clk or posedge areset) begin
        if (areset) begin
            global_history <= 7'b0000000; // Reset global history
            integer i;
            for (i = 0; i < 128; i = i + 1) begin
                PHT[i] <= 2'b00; // Reset PHT
            end
        end else begin
            if (train_valid) begin
                // Update the PHT based on training data
                if (train_mispredicted) begin
                    PHT[train_pc ^ global_history] <= (train_taken) ?
                        ((PHT[train_pc ^ global_history] == 2'b00) ? 2'b00 : PHT[train_pc ^ global_history] - 1) :
                        ((PHT[train_pc ^ global_history] == 2'b11) ? 2'b11 : PHT[train_pc ^ global_history] + 1);
                    global_history <= train_history; // Update global history to train history on misprediction
                end else begin
                    PHT[train_pc ^ global_history] <= (train_taken) ?
                        ((PHT[train_pc ^ global_history] == 2'b11) ? 2'b11 : PHT[train_pc ^ global_history] + 1) :
                        ((PHT[train_pc ^ global_history] == 2'b00) ? 2'b00 : PHT[train_pc ^ global_history] - 1);
                    global_history <= train_history; // Update global history
                end
            end

            if (predict_valid) begin
                predict_history <= global_history; // Output current global history
                predict_taken <= (predicted_state[1] == 1) ? 1 : 0; // Predict taken if state is 2'b10 or 2'b11
            end
        end
    end
endmodule


module top_module (
	input clk,
	input areset,
	input bump_left,
	input bump_right,
	input ground,
	input dig,
	output reg walk_left,
	output reg walk_right,
	output reg aaah,
	output reg digging
);

  typedef enum logic [2:0] {
    S_WALK_LEFT,
    S_WALK_RIGHT,
    S_FALL,
    S_DIG,
    S_SPLAT
  } state_t;

  state_t current_state, next_state;
  logic [5:0] fall_counter;

  always_ff @(posedge clk or posedge areset) begin
    if (areset) begin
      current_state <= S_WALK_LEFT;
      fall_counter <= 6'b0;
    end else begin
      current_state <= next_state;
      if (current_state == S_FALL) begin
        fall_counter <= fall_counter + 1;
      end else begin
        fall_counter <= 6'b0;
      end
    end
  end

  always_comb begin
    // Default outputs
    walk_left = 0;
    walk_right = 0;
    aaah = 0;
    digging = 0;

    case (current_state)
      S_WALK_LEFT: begin
        walk_left = 1;
        if (!ground) begin
          next_state = S_FALL;
          aaah = 1;
        end else if (dig) begin
          next_state = S_DIG;
          digging = 1;
        end else if (bump_right) begin
          next_state = S_WALK_RIGHT;
        end else if (bump_left) begin
          next_state = S_WALK_LEFT;
        end else begin
          next_state = S_WALK_LEFT;
        end
      end

      S_WALK_RIGHT: begin
        walk_right = 1;
        if (!ground) begin
          next_state = S_FALL;
          aaah = 1;
        end else if (dig) begin
          next_state = S_DIG;
          digging = 1;
        end else if (bump_left) begin
          next_state = S_WALK_LEFT;
        end else if (bump_right) begin
          next_state = S_WALK_RIGHT;
        end else begin
          next_state = S_WALK_RIGHT;
        end
      end

      S_FALL: begin
        aaah = 1;
        if (ground) begin
          if (fall_counter > 20) begin
            next_state = S_SPLAT;
          end else begin
            next_state = (walk_left ? S_WALK_LEFT : S_WALK_RIGHT);
          end
        end else begin
          next_state = S_FALL;
        end
      end

      S_DIG: begin
        digging = 1;
        if (!ground) begin
          next_state = S_FALL;
          aaah = 1;
        end else if (ground) begin
          next_state = (walk_left ? S_WALK_LEFT : S_WALK_RIGHT);
        end else begin
          next_state = S_DIG;
        end
      end

      S_SPLAT: begin
        walk_left = 0;
        walk_right = 0;
        aaah = 0;
        digging = 0;
        next_state = S_SPLAT; // Remain in splat state
      end

      default: begin
        next_state = S_WALK_LEFT; // default state
      end
    endcase
  end

endmodule

module top_module (
    input clk,
    input areset,
    input bump_left,
    input bump_right,
    input ground,
    input dig,
    output reg walk_left,
    output reg walk_right,
    output reg aaah,
    output reg digging
);

    typedef enum reg [2:0] {
        WALK_LEFT,
        WALK_RIGHT,
        FALLING,
        DIGGING,
        SPLATTER
    } state_t;

    state_t current_state, next_state;
    reg [4:0] fall_counter;

    always_ff @(posedge clk or posedge areset) begin
        if (areset) begin
            current_state <= WALK_LEFT;
            fall_counter <= 0;
        end else begin
            current_state <= next_state;
            if (current_state == FALLING) begin
                fall_counter <= fall_counter + 1;
            end else begin
                fall_counter <= 0;
            end
        end
    end

    always_comb begin
        next_state = current_state;
        walk_left = 0;
        walk_right = 0;
        aaah = 0;
        digging = 0;

        case (current_state)
            WALK_LEFT: begin
                walk_left = 1;
                if (!ground) begin
                    next_state = FALLING;
                    aaah = 1;
                } else if (bump_right) begin
                    next_state = WALK_RIGHT;
                } else if (dig) begin
                    next_state = DIGGING;
                end
            end

            WALK_RIGHT: begin
                walk_right = 1;
                if (!ground) begin
                    next_state = FALLING;
                    aaah = 1;
                } else if (bump_left) begin
                    next_state = WALK_LEFT;
                } else if (dig) begin
                    next_state = DIGGING;
                end
            end

            FALLING: begin
                aaah = 1;
                if (ground) begin
                    if (fall_counter > 20) begin
                        next_state = SPLATTER;
                    end else begin
                        if (walk_left) begin
                            next_state = WALK_LEFT;
                        end else begin
                            next_state = WALK_RIGHT;
                        end
                    end
                end
            end

            DIGGING: begin
                digging = 1;
                if (!ground) begin
                    next_state = FALLING;
                    aaah = 1;
                end
            end

            SPLATTER: begin
                walk_left = 0;
                walk_right = 0;
                aaah = 0;
                digging = 0;
            end
        endcase
    end
endmodule

module top_module (
	input clk,
	input areset,
	input bump_left,
	input bump_right,
	input ground,
	input dig,
	output reg walk_left,
	output reg walk_right,
	output reg aaah,
	output reg digging
);

	// State encoding
	typedef enum reg [2:0] {
		WALK_LEFT = 3'b000,
		WALK_RIGHT = 3'b001,
		FALLING = 3'b010,
		DIGGING = 3'b011,
		SPLATTER = 3'b100
	} state_t;

	state_t current_state, next_state;
	reg [4:0] fall_counter;

	always @(posedge clk or posedge areset) begin
		if (areset) begin
			current_state <= WALK_LEFT;
			fall_counter <= 5'b0;
		end else begin
			current_state <= next_state;
		end
	end

	always @(*) begin
		// Default outputs
		walk_left = 0;
		walk_right = 0;
		aaah = 0;
		digging = 0;

		// Next state logic
		case (current_state)
			WALK_LEFT: begin
				if (!ground) begin
					next_state = FALLING;
					aaah = 1;
					fall_counter = 0;
				end else if (dig) begin
					next_state = DIGGING;
					digging = 1;
				end else if (bump_right) begin
					next_state = WALK_RIGHT;
					walk_right = 1;
				end else begin
					next_state = WALK_LEFT;
					walk_left = 1;
				end
			end

			WALK_RIGHT: begin
				if (!ground) begin
					next_state = FALLING;
					aaah = 1;
					fall_counter = 0;
				end else if (dig) begin
					next_state = DIGGING;
					digging = 1;
				end else if (bump_left) begin
					next_state = WALK_LEFT;
					walk_left = 1;
				end else begin
					next_state = WALK_RIGHT;
					walk_right = 1;
				end
			end

			FALLING: begin
				if (fall_counter >= 20 && ground) begin
					next_state = SPLATTER;
				end else if (ground) begin
					next_state = (bump_left) ? WALK_RIGHT :
					(bump_right) ? WALK_LEFT : (current_state == FALLING) ? current_state :
					(current_state == WALK_LEFT) ? WALK_LEFT : WALK_RIGHT;
					if (next_state == WALK_LEFT) walk_left = 1;
					else if (next_state == WALK_RIGHT) walk_right = 1;
				end else begin
					next_state = FALLING;
					fall_counter = fall_counter + 1;
				end
			end

			DIGGING: begin
				if (!ground) begin
					next_state = FALLING;
					aaah = 1;
					fall_counter = 0;
				end else begin
					next_state = DIGGING;
					digging = 1;
				end
			end

			SPLATTER: begin
				next_state = SPLATTER;
				walk_left = 0;
				walk_right = 0;
				aaah = 0;
				digging = 0;
			end

			default: next_state = WALK_LEFT;
		endcase
	end
endmodule

module top_module (
    input clk,
    input areset,
    input bump_left,
    input bump_right,
    input ground,
    input dig,
    output reg walk_left,
    output reg walk_right,
    output reg aaah,
    output reg digging
);

    typedef enum reg [2:0] {
        WALK_LEFT,
        WALK_RIGHT,
        FALL,
        DIG,
        SPLAT
    } state_t;

    state_t state, next_state;
    reg [4:0] fall_count; // 5 bits to count up to 20

    always @(posedge clk or posedge areset) begin
        if (areset) begin
            state <= WALK_LEFT;
            fall_count <= 0;
            walk_left <= 1;
            walk_right <= 0;
            aaah <= 0;
            digging <= 0;
        end else begin
            state <= next_state;
            if (state == FALL) begin
                fall_count <= fall_count + 1;
            end else begin
                fall_count <= 0;
            end
        end
    end

    always @(*) begin
        next_state = state;
        walk_left = 0;
        walk_right = 0;
        aaah = 0;
        digging = 0;

        case (state)
            WALK_LEFT: begin
                walk_left = 1;
                aaah = 0;
                if (!ground) begin
                    next_state = FALL;
                    aaah = 1;
                end else if (bump_right) begin
                    next_state = WALK_RIGHT;
                end else if (dig) begin
                    next_state = DIG;
                    digging = 1;
                end
            end

            WALK_RIGHT: begin
                walk_right = 1;
                aaah = 0;
                if (!ground) begin
                    next_state = FALL;
                    aaah = 1;
                end else if (bump_left) begin
                    next_state = WALK_LEFT;
                end else if (dig) begin
                    next_state = DIG;
                    digging = 1;
                end
            end

            FALL: begin
                aaah = 1;
                if (ground) begin
                    if (fall_count > 20) begin
                        next_state = SPLAT;
                    end else begin
                        if (walk_left) begin
                            next_state = WALK_LEFT;
                        end else begin
                            next_state = WALK_RIGHT;
                        end
                    end
                end
            end

            DIG: begin
                digging = 1;
                if (!ground) begin
                    next_state = FALL;
                    aaah = 1;
                end else if (bump_left || bump_right) begin
                    // Ignore bumps while digging
                    next_state = DIG;
                end else if (!ground) begin
                    next_state = FALL;
                    aaah = 1;
                end
            end

            SPLAT: begin
                walk_left = 0;
                walk_right = 0;
                aaah = 0;
                digging = 0;
            end
        endcase
    end
endmodule

module top_module (
    input clk,
    input areset,
    input bump_left,
    input bump_right,
    input ground,
    input dig,
    output reg walk_left,
    output reg walk_right,
    output reg aaah,
    output reg digging
);

    typedef enum logic [2:0] {
        WALK_LEFT,
        WALK_RIGHT,
        FALL,
        DIG,
        SPLAT
    } state_t;

    state_t current_state, next_state;
    logic [4:0] fall_counter;

    always_ff @(posedge clk or posedge areset) begin
        if (areset) begin
            current_state <= WALK_LEFT;
            fall_counter <= 0;
        end else begin
            current_state <= next_state;
        end
    end

    always_ff @(posedge clk) begin
        if (current_state == FALL) begin
            fall_counter <= fall_counter + 1;
        end else begin
            fall_counter <= 0;
        end
    end

    always_comb begin
        walk_left = 0;
        walk_right = 0;
        aaah = 0;
        digging = 0;
        next_state = current_state;

        case (current_state)
            WALK_LEFT: begin
                walk_left = 1;
                if (~ground) begin
                    next_state = FALL;
                    aaah = 1;
                end else if (dig) begin
                    next_state = DIG;
                    digging = 1;
                end else if (bump_right) begin
                    next_state = WALK_RIGHT;
                end
            end

            WALK_RIGHT: begin
                walk_right = 1;
                if (~ground) begin
                    next_state = FALL;
                    aaah = 1;
                end else if (dig) begin
                    next_state = DIG;
                    digging = 1;
                end else if (bump_left) begin
                    next_state = WALK_LEFT;
                end
            end

            FALL: begin
                aaah = 1;
                if (fall_counter >= 20 && ground) begin
                    next_state = SPLAT;
                end else if (ground) begin
                    if (current_state == WALK_LEFT) next_state = WALK_LEFT;
                    else if (current_state == WALK_RIGHT) next_state = WALK_RIGHT;
                end
            end

            DIG: begin
                digging = 1;
                if (~ground) begin
                    next_state = FALL;
                    aaah = 1;
                end else if (ground) begin
                    if (current_state == WALK_LEFT) next_state = WALK_LEFT;
                    else if (current_state == WALK_RIGHT) next_state = WALK_RIGHT;
                end
            end

            SPLAT: begin
                walk_left = 0;
                walk_right = 0;
                aaah = 0;
                digging = 0;
            end
        endcase
    end

endmodule

module top_module (
	input clk,
	input areset,
	input bump_left,
	input bump_right,
	input ground,
	input dig,
	output reg walk_left,
	output reg walk_right,
	output reg aaah,
	output reg digging
);

	typedef enum reg [2:0] {
		WALK_LEFT,
		WALK_RIGHT,
		FALLING,
		DIGGING,
		SPLATTER
	} state_t;

	state_t state, next_state;
	reg [4:0] fall_counter;

	always_ff @(posedge clk or posedge areset) begin
		if (areset) begin
			state <= WALK_LEFT;
			fall_counter <= 0;
		end else begin
			state <= next_state;
		end
	end

	always_ff @(posedge clk) begin
		if (state == FALLING) begin
			fall_counter <= fall_counter + 1;
		end else begin
			fall_counter <= 0;
		end
	end

	always_comb begin
		next_state = state;
		walk_left = 0;
		walk_right = 0;
		aaah = 0;
		digging = 0;

		case(state)
			WALK_LEFT: begin
				walk_left = 1;
				if (!ground) begin
					next_state = FALLING;
					aaah = 1;
				end else if (dig && ground) begin
					next_state = DIGGING;
					digging = 1;
				end else if (bump_right) begin
					next_state = WALK_RIGHT;
				end
			end
			WALK_RIGHT: begin
				walk_right = 1;
				if (!ground) begin
					next_state = FALLING;
					aaah = 1;
				end else if (dig && ground) begin
					next_state = DIGGING;
					digging = 1;
				end else if (bump_left) begin
					next_state = WALK_LEFT;
				end
			end
			FALLING: begin
				aaah = 1;
				if (ground) begin
					if (fall_counter > 20) begin
						next_state = SPLATTER;
					end else begin
						next_state = (walk_left) ? WALK_LEFT : WALK_RIGHT;
					end
				end
			end
			DIGGING: begin
				digging = 1;
				if (!ground) begin
					next_state = FALLING;
					aaah = 1;
				end else if (ground && !dig) begin
					next_state = (walk_left) ? WALK_LEFT : WALK_RIGHT;
				end
			end
			SPLATTER: begin
				walk_left = 0;
				walk_right = 0;
				aaah = 0;
				digging = 0;
			end
		endcase
	end
endmodule

module top_module (
    input clk,
    input areset,
    input bump_left,
    input bump_right,
    input ground,
    input dig,
    output reg walk_left,
    output reg walk_right,
    output reg aaah,
    output reg digging
);

    typedef enum reg [2:0] {
        STATE_WALKING_LEFT,
        STATE_WALKING_RIGHT,
        STATE_FALLING,
        STATE_DIGGING,
        STATE_SPLATTER
    } state_t;

    state_t current_state, next_state;
    reg [4:0] fall_counter; // Counter for fall duration

    always @(posedge clk or posedge areset) begin
        if (areset) begin
            current_state <= STATE_WALKING_LEFT;
            fall_counter <= 0;
        end else begin
            current_state <= next_state;
            if (current_state == STATE_FALLING) begin
                fall_counter <= fall_counter + 1;
            end else begin
                fall_counter <= 0;
            end
        end
    end

    always @(*) begin
        next_state = current_state; // Default next state
        walk_left = 0;
        walk_right = 0;
        aaah = 0;
        digging = 0;

        case (current_state)
            STATE_WALKING_LEFT: begin
                if (!ground) begin
                    next_state = STATE_FALLING;
                    aaah = 1; // Start falling
                end else if (dig) begin
                    next_state = STATE_DIGGING;
                    digging = 1;
                end else if (bump_left) begin
                    next_state = STATE_WALKING_RIGHT;
                    walk_right = 1;
                end else begin
                    walk_left = 1;
                end
            end

            STATE_WALKING_RIGHT: begin
                if (!ground) begin
                    next_state = STATE_FALLING;
                    aaah = 1; // Start falling
                end else if (dig) begin
                    next_state = STATE_DIGGING;
                    digging = 1;
                end else if (bump_right) begin
                    next_state = STATE_WALKING_LEFT;
                    walk_left = 1;
                end else begin
                    walk_right = 1;
                end
            end

            STATE_FALLING: begin
                aaah = 1; // Continue falling
                if (ground) begin
                    if (fall_counter > 20) begin
                        next_state = STATE_SPLATTER;
                    end else begin
                        if (walk_left) begin
                            next_state = STATE_WALKING_LEFT;
                        end else if (walk_right) begin
                            next_state = STATE_WALKING_RIGHT;
                        end
                    end
                end
            end

            STATE_DIGGING: begin
                digging = 1;
                if (!ground) begin
                    next_state = STATE_FALLING;
                    aaah = 1; // Start falling
                end else if (bump_left || bump_right) begin
                    // No effect while digging
                end else if (ground) begin
                    // Continue digging
                end
            end

            STATE_SPLATTER: begin
                walk_left = 0;
                walk_right = 0;
                aaah = 0;
                digging = 0;
            end
        endcase
    end
endmodule

module top_module (
    input clk,
    input areset,
    input bump_left,
    input bump_right,
    input ground,
    input dig,
    output reg walk_left,
    output reg walk_right,
    output reg aaah,
    output reg digging
);

    typedef enum logic [2:0] {
        WALK_LEFT,
        WALK_RIGHT,
        FALLING,
        DIGGING,
        SPLATTER
    } state_t;

    state_t state, next_state;
    logic [4:0] fall_duration;

    always_ff @(posedge clk or posedge areset) begin
        if (areset) begin
            state <= WALK_LEFT;
            fall_duration <= 0;
        end else begin
            state <= next_state;
            if (state == FALLING) begin
                fall_duration <= fall_duration + 1;
            end else begin
                fall_duration <= 0;
            end
        end
    end

    always_comb begin
        // Default output values
        walk_left = 0;
        walk_right = 0;
        aaah = 0;
        digging = 0;
        next_state = state;

        case (state)
            WALK_LEFT: begin
                walk_left = 1;
                if (!ground) begin
                    aaah = 1;
                    next_state = FALLING;
                end else if (bump_right) begin
                    next_state = WALK_RIGHT;
                end else if (dig) begin
                    next_state = DIGGING;
                end
            end

            WALK_RIGHT: begin
                walk_right = 1;
                if (!ground) begin
                    aaah = 1;
                    next_state = FALLING;
                end else if (bump_left) begin
                    next_state = WALK_LEFT;
                end else if (dig) begin
                    next_state = DIGGING;
                end
            end

            FALLING: begin
                aaah = 1;
                if (ground) begin
                    if (fall_duration > 20) begin
                        next_state = SPLATTER;
                    end else begin
                        next_state = (walk_left ? WALK_LEFT : WALK_RIGHT);
                    end
                end
            end

            DIGGING: begin
                digging = 1;
                if (!ground) begin
                    aaah = 1;
                    next_state = FALLING;
                end else if (bump_left || bump_right) begin
                    next_state = DIGGING; // Ignore bumps while digging
                end
            end

            SPLATTER: begin
                walk_left = 0;
                walk_right = 0;
                aaah = 0;
                digging = 0;
            end
        endcase
    end
endmodule

module top_module (
    input clk,
    input areset,
    input bump_left,
    input bump_right,
    input ground,
    input dig,
    output reg walk_left,
    output reg walk_right,
    output reg aaah,
    output reg digging
);

    typedef enum reg [2:0] {
        WALK_LEFT,
        WALK_RIGHT,
        FALLING,
        DIGGING,
        SPLATTER
    } state_t;

    state_t current_state, next_state;
    reg [4:0] fall_counter;

    always @(posedge clk or posedge areset) begin
        if (areset) begin
            current_state <= WALK_LEFT;
            fall_counter <= 0;
        end else if (current_state != SPLATTER) begin
            current_state <= next_state;
            if (current_state == FALLING) begin
                fall_counter <= fall_counter + 1;
            end else begin
                fall_counter <= 0;
            end
        end
    end

    always @(*) begin
        case (current_state)
            WALK_LEFT: begin
                walk_left = 1;
                walk_right = 0;
                aaah = 0;
                digging = 0;
                if (!ground) begin
                    next_state = FALLING;
                end else if (dig && ground) begin
                    next_state = DIGGING;
                end else if (bump_right) begin
                    next_state = WALK_RIGHT;
                end else begin
                    next_state = WALK_LEFT;
                end
            end

            WALK_RIGHT: begin
                walk_left = 0;
                walk_right = 1;
                aaah = 0;
                digging = 0;
                if (!ground) begin
                    next_state = FALLING;
                end else if (dig && ground) begin
                    next_state = DIGGING;
                end else if (bump_left) begin
                    next_state = WALK_LEFT;
                end else begin
                    next_state = WALK_RIGHT;
                end
            end

            FALLING: begin
                walk_left = 0;
                walk_right = 0;
                aaah = 1;
                digging = 0;
                if (ground) begin
                    if (fall_counter > 20) begin
                        next_state = SPLATTER;
                    end else begin
                        next_state = (walk_left) ? WALK_LEFT : WALK_RIGHT;
                    end
                end else begin
                    next_state = FALLING;
                end
            end

            DIGGING: begin
                walk_left = 0;
                walk_right = 0;
                aaah = 0;
                digging = 1;
                if (!ground) begin
                    next_state = FALLING;
                end else if (!dig && ground) begin
                    next_state = (walk_left) ? WALK_LEFT : WALK_RIGHT;
                end else begin
                    next_state = DIGGING;
                end
            end

            SPLATTER: begin
                walk_left = 0;
                walk_right = 0;
                aaah = 0;
                digging = 0;
                next_state = SPLATTER;
            end

            default: next_state = WALK_LEFT;
        endcase
    end

endmodule

module top_module (
    input clk,
    input areset,
    input bump_left,
    input bump_right,
    input ground,
    input dig,
    output reg walk_left,
    output reg walk_right,
    output reg aaah,
    output reg digging
);

// State Encoding
typedef enum logic [2:0] {
    STATE_WALK_LEFT,
    STATE_WALK_RIGHT,
    STATE_FALL,
    STATE_DIG,
    STATE_SPLAT
} state_t;

state_t current_state, next_state;
reg [4:0] fall_counter;

// State Transition
always_ff @(posedge clk or posedge areset) begin
    if (areset) begin
        current_state <= STATE_WALK_LEFT;
        fall_counter <= 0;
    end else begin
        current_state <= next_state;

        if (current_state == STATE_FALL) begin
            fall_counter <= fall_counter + 1;
        end else if (current_state == STATE_WALK_LEFT || current_state == STATE_WALK_RIGHT) begin
            fall_counter <= 0;
        end
    end
end

// Output Logic and Next State Logic
always_comb begin
    // Default outputs
    walk_left = 0;
    walk_right = 0;
    aaah = 0;
    digging = 0;

    next_state = current_state; // Default to stay in current state

    case (current_state)
        STATE_WALK_LEFT: begin
            walk_left = 1;
            if (!ground) begin
                next_state = STATE_FALL;
                aaah = 1;
            end else if (dig) begin
                next_state = STATE_DIG;
                digging = 1;
            end else if (bump_right) begin
                next_state = STATE_WALK_RIGHT;
            end
        end

        STATE_WALK_RIGHT: begin
            walk_right = 1;
            if (!ground) begin
                next_state = STATE_FALL;
                aaah = 1;
            end else if (dig) begin
                next_state = STATE_DIG;
                digging = 1;
            end else if (bump_left) begin
                next_state = STATE_WALK_LEFT;
            end
        end

        STATE_FALL: begin
            aaah = 1;
            if (ground) begin
                if (fall_counter > 20) begin
                    next_state = STATE_SPLAT;
                end else if (walk_left) begin
                    next_state = STATE_WALK_LEFT;
                end else if (walk_right) begin
                    next_state = STATE_WALK_RIGHT;
                end
            end
        end

        STATE_DIG: begin
            digging = 1;
            if (!ground) begin
                next_state = STATE_FALL;
                aaah = 1;
            end else if (ground && !dig) begin
                next_state = (walk_left) ? STATE_WALK_LEFT : STATE_WALK_RIGHT;
            end
        end

        STATE_SPLAT: begin
            // All outputs remain zero
        end

        default: next_state = STATE_WALK_LEFT; // Fallback
    endcase
end

endmodule

module top_module (
    input clk,
    input areset,
    input bump_left,
    input bump_right,
    input ground,
    input dig,
    output reg walk_left,
    output reg walk_right,
    output reg aaah,
    output reg digging
);

    typedef enum reg [2:0] {
        STATE_WALK_LEFT,
        STATE_WALK_RIGHT,
        STATE_FALL,
        STATE_DIG,
        STATE_SPLAT
    } state_t;

    state_t current_state, next_state;
    reg [4:0] fall_counter; // for counting the number of clock cycles falling

    always @(posedge clk or posedge areset) begin
        if (areset) begin
            current_state <= STATE_WALK_LEFT;
            fall_counter <= 0;
        end else begin
            current_state <= next_state;
        end
    end

    always @* begin
        // Default outputs
        walk_left = 0;
        walk_right = 0;
        aaah = 0;
        digging = 0;
        next_state = current_state;
        case (current_state)
            STATE_WALK_LEFT: begin
                walk_left = 1;
                if (!ground) begin
                    next_state = STATE_FALL;
                    aaah = 1;
                end else if (dig) begin
                    next_state = STATE_DIG;
                    digging = 1;
                end else if (bump_right) begin
                    next_state = STATE_WALK_RIGHT;
                end
            end

            STATE_WALK_RIGHT: begin
                walk_right = 1;
                if (!ground) begin
                    next_state = STATE_FALL;
                    aaah = 1;
                end else if (dig) begin
                    next_state = STATE_DIG;
                    digging = 1;
                end else if (bump_left) begin
                    next_state = STATE_WALK_LEFT;
                end
            end

            STATE_FALL: begin
                aaah = 1;
                fall_counter = fall_counter + 1;
                if (ground) begin
                    if (fall_counter > 20) begin
                        next_state = STATE_SPLAT;
                    end else begin
                        if (current_state == STATE_WALK_LEFT) begin
                            next_state = STATE_WALK_LEFT;
                        end else begin
                            next_state = STATE_WALK_RIGHT;
                        end
                    end
                    fall_counter = 0;
                end
            end

            STATE_DIG: begin
                digging = 1;
                if (!ground) begin
                    next_state = STATE_FALL;
                    aaah = 1;
                end
            end

            STATE_SPLAT: begin
                walk_left = 0;
                walk_right = 0;
                aaah = 0;
                digging = 0;
            end
        endcase
    end
endmodule

module top_module (
    input clk,
    input areset,
    input bump_left,
    input bump_right,
    input ground,
    input dig,
    output reg walk_left,
    output reg walk_right,
    output reg aaah,
    output reg digging
);

    typedef enum reg [2:0] {
        WALK_LEFT,
        WALK_RIGHT,
        FALL,
        DIG,
        SPLAT
    } state_t;

    state_t state, next_state;
    reg [4:0] fall_counter;

    always @(posedge clk or posedge areset) begin
        if (areset) begin
            state <= WALK_LEFT;
            fall_counter <= 0;
        end else begin
            state <= next_state;
        end
    end

    always @(*) begin
        // Default values
        next_state = state;
        walk_left = 0;
        walk_right = 0;
        aaah = 0;
        digging = 0;

        case (state)
            WALK_LEFT: begin
                walk_left = 1;
                if (!ground) begin
                    next_state = FALL;
                    aaah = 1;
                end else if (dig) begin
                    next_state = DIG;
                    digging = 1;
                end else if (bump_right) begin
                    next_state = WALK_RIGHT;
                end
            end

            WALK_RIGHT: begin
                walk_right = 1;
                if (!ground) begin
                    next_state = FALL;
                    aaah = 1;
                end else if (dig) begin
                    next_state = DIG;
                    digging = 1;
                end else if (bump_left) begin
                    next_state = WALK_LEFT;
                end
            end

            FALL: begin
                aaah = 1;
                fall_counter = fall_counter + 1;
                if (ground) begin
                    if (fall_counter > 20) begin
                        next_state = SPLAT;
                    end else begin
                        next_state = (walk_left) ? WALK_LEFT : WALK_RIGHT;
                        fall_counter = 0;
                    end
                end
            end

            DIG: begin
                digging = 1;
                if (!ground) begin
                    next_state = FALL;
                    aaah = 1;
                end
            end

            SPLAT: begin
                walk_left = 0;
                walk_right = 0;
                aaah = 0;
                digging = 0;
            end
        endcase
    end
endmodule

module top_module (
    input clk,
    input areset,
    input bump_left,
    input bump_right,
    input ground,
    input dig,
    output reg walk_left,
    output reg walk_right,
    output reg aaah,
    output reg digging
);

    typedef enum logic [2:0] {
        STATE_WALK_LEFT,
        STATE_WALK_RIGHT,
        STATE_FALL,
        STATE_DIG,
        STATE_SPLAT
    } state_t;

    state_t current_state, next_state;
    logic [4:0] fall_counter;

    always_ff @(posedge clk or posedge areset) begin
        if (areset) begin
            current_state <= STATE_WALK_LEFT;
            fall_counter <= 0;
        end else begin
            current_state <= next_state;
            if (current_state == STATE_FALL) begin
                fall_counter <= fall_counter + 1;
            end else begin
                fall_counter <= 0;
            end
        end
    end

    always_comb begin
        // Default outputs
        walk_left = 0;
        walk_right = 0;
        aaah = 0;
        digging = 0;
        next_state = current_state;

        case (current_state)
            STATE_WALK_LEFT: begin
                walk_left = 1;
                if (!ground) begin
                    aaah = 1;
                    next_state = STATE_FALL;
                } else if (bump_right) begin
                    next_state = STATE_WALK_RIGHT;
                } else if (dig) begin
                    if (ground) begin
                        digging = 1;
                        next_state = STATE_DIG;
                    }
                end
            end

            STATE_WALK_RIGHT: begin
                walk_right = 1;
                if (!ground) begin
                    aaah = 1;
                    next_state = STATE_FALL;
                } else if (bump_left) begin
                    next_state = STATE_WALK_LEFT;
                } else if (dig) begin
                    if (ground) begin
                        digging = 1;
                        next_state = STATE_DIG;
                    }
                end
            end

            STATE_FALL: begin
                aaah = 1;
                if (ground) begin
                    if (fall_counter > 20) begin
                        next_state = STATE_SPLAT;
                    end else begin
                        if (current_state == STATE_WALK_LEFT) begin
                            next_state = STATE_WALK_LEFT;
                        end else if (current_state == STATE_WALK_RIGHT) begin
                            next_state = STATE_WALK_RIGHT;
                        end
                    end
                end
            end

            STATE_DIG: begin
                digging = 1;
                if (!ground) begin
                    aaah = 1;
                    next_state = STATE_FALL;
                end else begin
                    if (bump_left || bump_right) begin
                        // Ignore bump while digging
                    end else if (ground) begin
                        // Continue digging
                        next_state = STATE_DIG;
                    end
                end
            end

            STATE_SPLAT: begin
                walk_left = 0;
                walk_right = 0;
                aaah = 0;
                digging = 0;
            end
        endcase
    end

endmodule

module top_module (
    input clk,
    input areset,
    input bump_left,
    input bump_right,
    input ground,
    input dig,
    output reg walk_left,
    output reg walk_right,
    output reg aaah,
    output reg digging
);

    typedef enum reg [2:0] {
        WALK_LEFT,
        WALK_RIGHT,
        FALLING,
        DIGGING,
        SPLATTER
    } state_t;

    state_t state, next_state;
    reg [4:0] fall_counter;

    always @(posedge clk or posedge areset) begin
        if (areset) begin
            state <= WALK_LEFT;
            fall_counter <= 0;
            walk_left <= 1;
            walk_right <= 0;
            aaah <= 0;
            digging <= 0;
        end else begin
            state <= next_state;
            if (state == FALLING) begin
                fall_counter <= fall_counter + 1;
            end else begin
                fall_counter <= 0;
            end
        end
    end

    always @(*) begin
        next_state = state;
        walk_left = 0;
        walk_right = 0;
        aaah = 0;
        digging = 0;

        case (state)
            WALK_LEFT: begin
                walk_left = 1;
                aaah = 0;
                digging = 0;
                if (!ground) begin
                    next_state = FALLING;
                    aaah = 1;
                end else if (dig) begin
                    next_state = DIGGING;
                    digging = 1;
                end else if (bump_right) begin
                    next_state = WALK_RIGHT;
                end
            end

            WALK_RIGHT: begin
                walk_right = 1;
                aaah = 0;
                digging = 0;
                if (!ground) begin
                    next_state = FALLING;
                    aaah = 1;
                end else if (dig) begin
                    next_state = DIGGING;
                    digging = 1;
                end else if (bump_left) begin
                    next_state = WALK_LEFT;
                end
            end

            FALLING: begin
                aaah = 1;
                if (ground) begin
                    if (fall_counter > 20) begin
                        next_state = SPLATTER;
                    end else begin
                        next_state = (walk_left) ? WALK_LEFT : WALK_RIGHT;
                    end
                end
            end

            DIGGING: begin
                digging = 1;
                if (!ground) begin
                    next_state = FALLING;
                    aaah = 1;
                end else if (!dig) begin
                    next_state = (walk_left) ? WALK_LEFT : WALK_RIGHT;
                end
            end

            SPLATTER: begin
                walk_left = 0;
                walk_right = 0;
                aaah = 0;
                digging = 0;
            end
        endcase
    end

endmodule

module top_module (
    input clk,
    input areset,
    input bump_left,
    input bump_right,
    input ground,
    input dig,
    output reg walk_left,
    output reg walk_right,
    output reg aaah,
    output reg digging
);

    typedef enum reg [2:0] {
        STATE_WALK_LEFT,
        STATE_WALK_RIGHT,
        STATE_FALLING,
        STATE_DIGGING,
        STATE_SPLATTER
    } state_t;

    state_t current_state, next_state;
    reg [4:0] fall_counter; // 5 bits to count up to 20

    always @(posedge clk or posedge areset) begin
        if (areset) begin
            current_state <= STATE_WALK_LEFT;
            fall_counter <= 0;
        end else begin
            current_state <= next_state;
            if (current_state == STATE_FALLING) begin
                if (fall_counter < 20)
                    fall_counter <= fall_counter + 1;
            end else begin
                fall_counter <= 0;
            end
        end
    end

    always @(*) begin
        next_state = current_state;
        walk_left = 0;
        walk_right = 0;
        aaah = 0;
        digging = 0;

        case (current_state)
            STATE_WALK_LEFT: begin
                walk_left = 1;
                if (!ground) begin
                    next_state = STATE_FALLING;
                    aaah = 1;
                end else if (bump_right) begin
                    next_state = STATE_WALK_RIGHT;
                end else if (dig) begin
                    next_state = STATE_DIGGING;
                    digging = 1;
                end
            end

            STATE_WALK_RIGHT: begin
                walk_right = 1;
                if (!ground) begin
                    next_state = STATE_FALLING;
                    aaah = 1;
                end else if (bump_left) begin
                    next_state = STATE_WALK_LEFT;
                end else if (dig) begin
                    next_state = STATE_DIGGING;
                    digging = 1;
                end
            end

            STATE_FALLING: begin
                aaah = 1;
                if (ground) begin
                    if (fall_counter > 20) begin
                        next_state = STATE_SPLATTER;
                    end else begin
                        if (walk_left) next_state = STATE_WALK_LEFT;
                        else if (walk_right) next_state = STATE_WALK_RIGHT;
                    end
                end
            end

            STATE_DIGGING: begin
                digging = 1;
                if (!ground) begin
                    next_state = STATE_FALLING;
                    aaah = 1;
                end else if (ground) begin
                    if (bump_left) next_state = STATE_WALK_LEFT;
                    else if (bump_right) next_state = STATE_WALK_RIGHT;
                end
            end

            STATE_SPLATTER: begin
                walk_left = 0;
                walk_right = 0;
                aaah = 0;
                digging = 0;
            end
        endcase
    end
endmodule

module top_module (
    input clk,
    input areset,
    input bump_left,
    input bump_right,
    input ground,
    input dig,
    output reg walk_left,
    output reg walk_right,
    output reg aaah,
    output reg digging
);

    typedef enum reg [3:0] {
        STATE_WALK_LEFT,
        STATE_WALK_RIGHT,
        STATE_FALL,
        STATE_DIGGING,
        STATE_SPLAT
    } state_t;

    state_t current_state, next_state;
    reg [4:0] fall_counter;

    always @(posedge clk or posedge areset) begin
        if (areset) begin
            current_state <= STATE_WALK_LEFT;
            fall_counter <= 0;
        end else begin
            current_state <= next_state;
        end
    end

    always @(*) begin
        next_state = current_state;
        aaah = 0;
        walk_left = 0;
        walk_right = 0;
        digging = 0;

        case (current_state)
            STATE_WALK_LEFT: begin
                if (!ground) begin
                    aaah = 1;
                    next_state = STATE_FALL;
                end else if (dig) begin
                    next_state = STATE_DIGGING;
                    digging = 1;
                end else begin
                    walk_left = 1;
                    if (bump_right) next_state = STATE_WALK_RIGHT;
                end
            end

            STATE_WALK_RIGHT: begin
                if (!ground) begin
                    aaah = 1;
                    next_state = STATE_FALL;
                end else if (dig) begin
                    next_state = STATE_DIGGING;
                    digging = 1;
                end else begin
                    walk_right = 1;
                    if (bump_left) next_state = STATE_WALK_LEFT;
                end
            end

            STATE_FALL: begin
                aaah = 1;
                if (ground) begin
                    if (fall_counter > 20) begin
                        next_state = STATE_SPLAT;
                    end else begin
                        if (bump_right) next_state = STATE_WALK_LEFT;
                        else if (bump_left) next_state = STATE_WALK_RIGHT;
                        else if (current_state == STATE_WALK_LEFT) next_state = STATE_WALK_LEFT;
                        else next_state = STATE_WALK_RIGHT;
                    end
                    fall_counter <= 0;
                end else begin
                    fall_counter <= fall_counter + 1;
                end
            end

            STATE_DIGGING: begin
                digging = 1;
                if (!ground) begin
                    aaah = 1;
                    next_state = STATE_FALL;
                end else if (!dig) begin
                    next_state = current_state;
                end
            end

            STATE_SPLAT: begin
                walk_left = 0;
                walk_right = 0;
                aaah = 0;
                digging = 0;
            end
        endcase
    end
endmodule

module top_module (
    input clk,
    input areset,
    input bump_left,
    input bump_right,
    input ground,
    input dig,
    output reg walk_left,
    output reg walk_right,
    output reg aaah,
    output reg digging
);

    typedef enum reg [2:0] {
        STATE_WALK_LEFT,
        STATE_WALK_RIGHT,
        STATE_FALL,
        STATE_DIG,
        STATE_SPLAT
    } state_t;

    state_t current_state, next_state;
    reg [4:0] fall_counter; // Count the number of clock cycles falling

    always @(posedge clk or posedge areset) begin
        if (areset) begin
            current_state <= STATE_WALK_LEFT;
            fall_counter <= 0;
        end else begin
            current_state <= next_state;
            if (current_state == STATE_FALL) begin
                fall_counter <= fall_counter + 1;
            end else begin
                fall_counter <= 0;
            end
        end
    end

    always @(*) begin
        walk_left = 0;
        walk_right = 0;
        aaah = 0;
        digging = 0;
        next_state = current_state;

        case (current_state)
            STATE_WALK_LEFT: begin
                walk_left = 1;
                if (!ground) begin
                    next_state = STATE_FALL;
                    aaah = 1;
                end else if (dig) begin
                    next_state = STATE_DIG;
                end else if (bump_right) begin
                    next_state = STATE_WALK_RIGHT;
                end
            end

            STATE_WALK_RIGHT: begin
                walk_right = 1;
                if (!ground) begin
                    next_state = STATE_FALL;
                    aaah = 1;
                end else if (dig) begin
                    next_state = STATE_DIG;
                end else if (bump_left) begin
                    next_state = STATE_WALK_LEFT;
                end
            end

            STATE_FALL: begin
                aaah = 1;
                if (ground) begin
                    if (fall_counter > 20) begin
                        next_state = STATE_SPLAT;
                    end else begin
                        next_state = (bump_left) ? STATE_WALK_RIGHT : (bump_right) ? STATE_WALK_LEFT : current_state;
                    end
                end
            end

            STATE_DIG: begin
                digging = 1;
                if (!ground) begin
                    next_state = STATE_FALL;
                    aaah = 1;
                end else if (!dig) begin
                    next_state = (walk_left) ? STATE_WALK_LEFT : STATE_WALK_RIGHT;
                end
            end

            STATE_SPLAT: begin
                // All outputs are 0 in the splat state
                // Remain in this state forever
            end
        endcase
    end
endmodule

module top_module (
    input clk,
    input areset,
    input bump_left,
    input bump_right,
    input ground,
    input dig,
    output reg walk_left,
    output reg walk_right,
    output reg aaah,
    output reg digging
);

    typedef enum logic [2:0] {
        WALK_LEFT,
        WALK_RIGHT,
        FALLING,
        DIGGING,
        SPLATTER
    } state_t;

    state_t current_state, next_state;
    reg [4:0] fall_counter; // Counter to track falling duration

    always_ff @(posedge clk or posedge areset) begin
        if (areset) begin
            current_state <= WALK_LEFT;
            fall_counter <= 0;
        end else begin
            current_state <= next_state;
            if (current_state == FALLING) begin
                if (fall_counter < 20)
                    fall_counter <= fall_counter + 1;
            end else begin
                fall_counter <= 0; // Reset counter when not falling
            end
        end
    end

    always_comb begin
        next_state = current_state;
        walk_left = 0;
        walk_right = 0;
        aaah = 0;
        digging = 0;

        case (current_state)
            WALK_LEFT: begin
                walk_left = 1;
                if (ground == 0) begin
                    next_state = FALLING;
                    aaah = 1;
                end else if (bump_right) begin
                    next_state = WALK_RIGHT;
                } else if (dig) begin
                    next_state = DIGGING;
                end
            end

            WALK_RIGHT: begin
                walk_right = 1;
                if (ground == 0) begin
                    next_state = FALLING;
                    aaah = 1;
                end else if (bump_left) begin
                    next_state = WALK_LEFT;
                end else if (dig) begin
                    next_state = DIGGING;
                end
            end

            FALLING: begin
                aaah = 1;
                if (ground) begin
                    if (fall_counter > 20) begin
                        next_state = SPLATTER;
                    end else begin
                        next_state = (walk_left) ? WALK_LEFT : WALK_RIGHT;
                    end
                end
            end

            DIGGING: begin
                digging = 1;
                if (ground == 0) begin
                    next_state = FALLING;
                    aaah = 1;
                end else if (bump_left || bump_right) begin
                    // Stay in DIGGING state
                end else if (ground) begin
                    next_state = (walk_left) ? WALK_LEFT : WALK_RIGHT;
                end
            end

            SPLATTER: begin
                walk_left = 0;
                walk_right = 0;
                aaah = 0;
                digging = 0;
                // Remain in this state forever until reset
            end
        endcase
    end
endmodule

module top_module (
    input clk,
    input areset,
    input bump_left,
    input bump_right,
    input ground,
    input dig,
    output reg walk_left,
    output reg walk_right,
    output reg aaah,
    output reg digging
);

    typedef enum reg [2:0] {
        WALK_LEFT,
        WALK_RIGHT,
        FALL,
        DIG,
        SPLAT
    } state_t;

    state_t current_state, next_state;
    reg [4:0] fall_count; // 5 bits to count up to 20

    always @(posedge clk or posedge areset) begin
        if (areset) begin
            current_state <= WALK_LEFT;
            fall_count <= 0;
        end else begin
            current_state <= next_state;
            if (current_state == FALL) begin
                fall_count <= fall_count + 1;
            end else begin
                fall_count <= 0;
            end
        end
    end

    always @(*) begin
        next_state = current_state;
        walk_left = 0;
        walk_right = 0;
        aaah = 0;
        digging = 0;

        case (current_state)
            WALK_LEFT: begin
                walk_left = 1;
                if (ground == 0) begin
                    next_state = FALL;
                    aaah = 1;
                end else if (bump_right) begin
                    next_state = WALK_RIGHT;
                end else if (dig) begin
                    next_state = DIG;
                end
            end

            WALK_RIGHT: begin
                walk_right = 1;
                if (ground == 0) begin
                    next_state = FALL;
                    aaah = 1;
                end else if (bump_left) begin
                    next_state = WALK_LEFT;
                end else if (dig) begin
                    next_state = DIG;
                end
            end

            FALL: begin
                aaah = 1;
                if (fall_count >= 20 && ground) begin
                    next_state = SPLAT;
                end else if (ground) begin
                    next_state = (walk_left) ? WALK_LEFT : WALK_RIGHT;
                end
            end

            DIG: begin
                digging = 1;
                if (ground == 0) begin
                    next_state = FALL;
                    aaah = 1;
                end else if (!ground) begin
                    next_state = FALL;
                end else if (ground && fall_count == 0) begin
                    next_state = (walk_left) ? WALK_LEFT : WALK_RIGHT;
                end
            end

            SPLAT: begin
                walk_left = 0;
                walk_right = 0;
                aaah = 0;
                digging = 0;
            end

        endcase
    end

endmodule

module top_module (
	input clk,
	input areset,
	input bump_left,
	input bump_right,
	input ground,
	input dig,
	output reg walk_left,
	output reg walk_right,
	output reg aaah,
	output reg digging
);

    typedef enum reg [2:0] {
        STATE_WALK_LEFT,
        STATE_WALK_RIGHT,
        STATE_FALL,
        STATE_DIG,
        STATE_SPLAT
    } state_t;

    state_t current_state, next_state;
    reg [4:0] fall_counter; // To count the clock cycles fallen

    always @(posedge clk or posedge areset) begin
        if (areset) begin
            current_state <= STATE_WALK_LEFT;
            fall_counter <= 0;
        end else begin
            current_state <= next_state;
            if (current_state == STATE_FALL) begin
                fall_counter <= fall_counter + 1;
            end else begin
                fall_counter <= 0;
            end
        end
    end

    always @(*) begin
        // Default assignments
        walk_left = 0;
        walk_right = 0;
        aaah = 0;
        digging = 0;

        case (current_state)
            STATE_WALK_LEFT: begin
                walk_left = 1;
                if (!ground) begin
                    next_state = STATE_FALL;
                    aaah = 1;
                end else if (dig) begin
                    next_state = STATE_DIG;
                end else if (bump_right) begin
                    next_state = STATE_WALK_RIGHT;
                end else begin
                    next_state = STATE_WALK_LEFT;
                end
            end

            STATE_WALK_RIGHT: begin
                walk_right = 1;
                if (!ground) begin
                    next_state = STATE_FALL;
                    aaah = 1;
                end else if (dig) begin
                    next_state = STATE_DIG;
                end else if (bump_left) begin
                    next_state = STATE_WALK_LEFT;
                end else begin
                    next_state = STATE_WALK_RIGHT;
                end
            end

            STATE_FALL: begin
                aaah = 1;
                if (ground) begin
                    if (fall_counter > 20) begin
                        next_state = STATE_SPLAT;
                    end else begin
                        if (walk_left) next_state = STATE_WALK_LEFT;
                        else next_state = STATE_WALK_RIGHT;
                    end
                end else begin
                    next_state = STATE_FALL;
                end
            end

            STATE_DIG: begin
                digging = 1;
                if (ground) begin
                    next_state = STATE_DIG;
                end else begin
                    next_state = STATE_FALL;
                    aaah = 1;
                end
            end

            STATE_SPLAT: begin
                walk_left = 0;
                walk_right = 0;
                aaah = 0;
                digging = 0;
                next_state = STATE_SPLAT; // Remain in splat state
            end

            default: begin
                next_state = STATE_WALK_LEFT; // Default state
            end
        endcase
    end
endmodule