module top_module (
    input clk,
    input in,
    input reset,
    output reg [7:0] out_byte,
    output reg done
);

    typedef enum logic [2:0] {
        IDLE = 3'b000,
        START = 3'b001,
        DATA = 3'b010,
        STOP = 3'b011,
        WAIT_STOP = 3'b100
    } state_t;

    state_t state, next_state;
    reg [7:0] data_reg;
    reg [2:0] bit_count;

    always @(posedge clk or posedge reset) begin
        if (reset) begin
            state <= IDLE;
            out_byte <= 8'b0;
            done <= 1'b0;
            data_reg <= 8'b0;
            bit_count <= 3'b0;
        end else begin
            state <= next_state;
        end
    end

    always @(*) begin
        next_state = state;
        done = 1'b0;
        case (state)
            IDLE: begin
                if (in == 1'b0) // Detect start bit
                    next_state = START;
            end
            START: begin
                if (in == 1'b0) // Confirm start bit
                    next_state = DATA;
            end
            DATA: begin
                if (bit_count == 3'b111) // Last bit of data
                    next_state = STOP;
            end
            STOP: begin
                if (in == 1'b1) begin // Check stop bit
                    next_state = IDLE;
                    done = 1'b1;
                end else begin
                    next_state = WAIT_STOP;
                end
            end
            WAIT_STOP: begin
                if (in == 1'b1) // Wait for stop bit
                    next_state = IDLE;
            end
        endcase
    end

    always @(posedge clk or posedge reset) begin
        if (reset) begin
            data_reg <= 8'b0;
            bit_count <= 3'b0;
            out_byte <= 8'b0;
        end else begin
            case (state)
                IDLE: begin
                    bit_count <= 3'b0;
                end
                START: begin
                    if (in == 1'b0) // Confirm start bit
                        bit_count <= 3'b0;
                end
                DATA: begin
                    data_reg[bit_count] <= in;
                    bit_count <= bit_count + 1;
                end
                STOP: begin
                    if (in == 1'b1) // Valid stop bit, store data
                        out_byte <= data_reg;
                end
                WAIT_STOP: begin
                    // Do nothing, wait for stop bit
                end
            endcase
        end
    end

endmodule

module top_module (
    input clk,
    input in,
    input reset,
    output reg [7:0] out_byte,
    output reg done
);
    // States of the FSM
    typedef enum reg [2:0] {
        IDLE = 3'b000,
        START = 3'b001,
        RECEIVE = 3'b010,
        STOP = 3'b011,
        WAIT_STOP = 3'b100
    } state_t;

    reg [2:0] state, next_state;
    reg [2:0] bit_counter;
    reg [7:0] shift_reg;

    // State transition logic
    always @(*) begin
        case (state)
            IDLE: begin
                if (in == 1'b0) // Detect start bit
                    next_state = START;
                else
                    next_state = IDLE;
            end
            START: next_state = RECEIVE;

            RECEIVE: begin
                if (bit_counter == 3'b111)
                    next_state = STOP;
                else
                    next_state = RECEIVE;
            end

            STOP: begin
                if (in == 1'b1) // Detect stop bit
                    next_state = IDLE;
                else
                    next_state = WAIT_STOP;
            end

            WAIT_STOP: begin
                if (in == 1'b1)
                    next_state = IDLE;
                else
                    next_state = WAIT_STOP;
            end

            default: next_state = IDLE;
        endcase
    end

    // State flip-flops
    always @(posedge clk or posedge reset) begin
        if (reset)
            state <= IDLE;
        else
            state <= next_state;
    end

    // Output logic and shift register
    always @(posedge clk or posedge reset) begin
        if (reset) begin
            shift_reg <= 8'b0;
            out_byte <= 8'b0;
            done <= 1'b0;
            bit_counter <= 3'b0;
        end
        else begin
            case (state)
                IDLE: begin
                    done <= 1'b0;
                end

                START: begin
                    bit_counter <= 3'b0;
                end

                RECEIVE: begin
                    shift_reg <= {in, shift_reg[7:1]};
                    bit_counter <= bit_counter + 3'b1;
                end

                STOP: begin
                    if (in == 1'b1) begin
                        out_byte <= shift_reg;
                        done <= 1'b1;
                    end
                end

                WAIT_STOP: begin
                    done <= 1'b0;
                end
            endcase
        end
    end
endmodule

module top_module (
    input clk,
    input in,
    input reset,
    output reg [7:0] out_byte,
    output reg done
);

    // State encoding
    typedef enum reg [2:0] {
        IDLE = 3'b000,
        START = 3'b001,
        DATA = 3'b010,
        STOP = 3'b011,
        DONE = 3'b100
    } state_t;

    state_t current_state, next_state;
    reg [2:0] bit_counter; // For counting up to 8 data bits
    reg [7:0] data_buffer; // Buffer to store received data bits

    // State transition logic
    always @(posedge clk or posedge reset) begin
        if (reset) begin
            current_state <= IDLE;
            bit_counter <= 3'b000;
            out_byte <= 8'b0;
            done <= 1'b0;
            data_buffer <= 8'b0;
        end else begin
            current_state <= next_state;
            if (current_state == DATA) begin
                data_buffer <= {in, data_buffer[7:1]}; // Shift data in LSB-first
            end
        end
    end

    // Next state logic and output logic
    always @(*) begin
        next_state = current_state;
        done = 1'b0;

        case (current_state)
            IDLE: begin
                if (in == 1'b0) begin // Detect start bit
                    next_state = START;
                end
            end

            START: begin
                next_state = DATA;
                bit_counter = 3'b000;
            end

            DATA: begin
                if (bit_counter == 3'b111) begin
                    next_state = STOP;
                end else begin
                    bit_counter = bit_counter + 1'b1;
                end
            end

            STOP: begin
                if (in == 1'b1) begin // Check stop bit
                    next_state = DONE;
                end else begin
                    next_state = IDLE; // Wait for stop bit correctly
                end
            end

            DONE: begin
                done = 1'b1;
                out_byte = data_buffer;
                next_state = IDLE; // Go back to idle to receive next byte
            end

            default: next_state = IDLE;
        endcase
    end

endmodule

module top_module (
    input clk,
    input in,
    input reset,
    output reg [7:0] out_byte,
    output reg done
);

    typedef enum reg [2:0] {
        IDLE        = 3'b000,
        START       = 3'b001,
        DATA        = 3'b010,
        STOP        = 3'b011,
        ERROR       = 3'b100
    } state_t;

    reg [2:0] state, next_state;
    reg [2:0] bit_count;
    reg [7:0] data_byte;

    always @(posedge clk or posedge reset) begin
        if (reset) begin
            state <= IDLE;
            bit_count <= 3'b0;
            out_byte <= 8'b0;
            done <= 1'b0;
        end else begin
            state <= next_state;
            if (state == DATA)
                data_byte[bit_count] <= in;
        end
    end

    always @(*) begin
        next_state = state;
        done = 1'b0;

        case (state)
            IDLE: begin
                if (in == 1'b0) // Start bit detected
                    next_state = START;
            end

            START: begin
                next_state = DATA;
            end

            DATA: begin
                if (bit_count == 3'b111) begin
                    next_state = STOP;
                end else begin
                    bit_count = bit_count + 1'b1;
                end
            end

            STOP: begin
                if (in == 1'b1) begin // Stop bit detected
                    out_byte = data_byte;
                    done = 1'b1;
                    next_state = IDLE;
                end else begin
                    next_state = ERROR;
                end
                bit_count = 3'b0;
            end

            ERROR: begin
                if (in == 1'b1) // Wait for stop bit to transition to IDLE
                    next_state = IDLE;
            end

            default: begin
                next_state = IDLE;
            end
        endcase
    end

endmodule

module top_module (
    input clk,
    input in,
    input reset,
    output reg [7:0] out_byte,
    output reg done
);

    typedef enum reg [2:0] {
        IDLE   = 3'b000,
        START  = 3'b001,
        DATA   = 3'b010,
        STOP   = 3'b011,
        ERROR  = 3'b100
    } state_t;

    reg [2:0] state, next_state;
    reg [2:0] bit_count;
    reg [7:0] data_reg;

    always @(posedge clk or posedge reset) begin
        if (reset) begin
            state <= IDLE;
            bit_count <= 3'b000;
            data_reg <= 8'b0;
            out_byte <= 8'b0;
            done <= 1'b0;
        end
        else begin
            state <= next_state;

            if (state == DATA) begin
                data_reg[bit_count] <= in;
                bit_count <= bit_count + 1;
            end
        end
    end

    always @(*) begin
        next_state = state; // Default state is to remain in the current state
        done = 1'b0;        // Default output for done
        case (state)
            IDLE: begin
                if (in == 1'b0) begin   // Detect start bit
                    next_state = START;
                    bit_count = 3'b000;
                end
            end

            START: begin
                next_state = DATA;
            end

            DATA: begin
                if (bit_count == 3'b111) begin
                    next_state = STOP;
                end
            end

            STOP: begin
                if (in == 1'b1) begin   // Check stop bit
                    out_byte = data_reg;
                    done = 1'b1;
                    next_state = IDLE;
                end
                else begin
                    next_state = ERROR;
                end
            end

            ERROR: begin
                if (in == 1'b1) begin
                    next_state = IDLE; // Wait for stop bit to return to IDLE
                end
            end
        endcase
    end

endmodule

module top_module (
    input clk,
    input in,
    input reset,
    output reg [7:0] out_byte,
    output reg done
);

    typedef enum reg [2:0] {
        IDLE = 3'b000,
        START = 3'b001,
        DATA = 3'b010,
        STOP = 3'b011,
        WAIT_STOP = 3'b100
    } state_t;

    state_t state, next_state;
    reg [2:0] bit_cnt;
    reg [7:0] data_reg;

    always @(posedge clk or posedge reset) begin
        if (reset) begin
            state <= IDLE;
            bit_cnt <= 3'b000;
            data_reg <= 8'b00000000;
            out_byte <= 8'bxxxxxxxx;
            done <= 0;
        end else begin
            state <= next_state;
            if (state == DATA) begin
                data_reg[bit_cnt] <= in;
                bit_cnt <= bit_cnt + 1;
            end else if (state == IDLE) begin
                bit_cnt <= 3'b000;
            end
        end
    end

    always @* begin
        next_state = state;
        done = 0;
        out_byte = 8'bxxxxxxxx;
        case (state)
            IDLE: begin
                if (in == 0) begin
                    next_state = START;
                end
            end
            START: begin
                if (in == 0) begin
                    next_state = DATA;
                end else begin
                    next_state = IDLE;
                end
            end
            DATA: begin
                if (bit_cnt == 3'b111) begin
                    next_state = STOP;
                end
            end
            STOP: begin
                if (in == 1) begin
                    done = 1;
                    out_byte = data_reg;
                    next_state = IDLE;
                end else begin
                    next_state = WAIT_STOP;
                end
            end
            WAIT_STOP: begin
                if (in == 1) begin
                    next_state = IDLE;
                end
            end
        endcase
    end

endmodule

module top_module (
    input clk,
    input in,
    input reset,
    output reg [7:0] out_byte,
    output reg done
);

    typedef enum logic [2:0] {
        IDLE = 3'b000,
        START = 3'b001,
        DATA = 3'b010,
        STOP = 3'b011,
        DONE = 3'b100
    } state_t;

    state_t state, next_state;

    reg [2:0] bit_count;
    reg [7:0] data;

    always_ff @(posedge clk or posedge reset) begin
        if (reset) begin
            state <= IDLE;
            out_byte <= 8'b0;
            done <= 1'b0;
            bit_count <= 3'b0;
            data <= 8'b0;
        end else begin
            state <= next_state;
            if (state == DATA) begin
                data[bit_count] <= in;
                bit_count <= bit_count + 1;
            end
            if (state == DONE) begin
                out_byte <= data;
                done <= 1'b1;
            end else begin
                done <= 1'b0;
            end
        end
    end

    always_comb begin
        next_state = state;
        case (state)
            IDLE: begin
                if (in == 1'b0) begin
                    next_state = START;
                end
            end
            START: begin
                if (in == 1'b0) begin
                    next_state = DATA;
                end else begin
                    next_state = IDLE;
                end
            end
            DATA: begin
                if (bit_count == 3'b111) begin
                    next_state = STOP;
                end
            end
            STOP: begin
                if (in == 1'b1) begin
                    next_state = DONE;
                end else begin
                    next_state = IDLE;
                end
            end
            DONE: begin
                next_state = IDLE;
            end
        endcase
    end

endmodule

module top_module (
    input clk,
    input in,
    input reset,
    output reg [7:0] out_byte,
    output reg done
);

    typedef enum logic [2:0] {
        IDLE,
        START,
        DATA,
        STOP,
        ERROR
    } state_type;

    state_type current_state, next_state;
    reg [2:0] bit_idx;
    reg [7:0] data_register;

    always_ff @(posedge clk or posedge reset) begin
        if (reset) begin
            current_state <= IDLE;
            bit_idx <= 3'd0;
            out_byte <= 8'b0;
            done <= 1'b0;
        end else begin
            current_state <= next_state;
            if (current_state == DATA && bit_idx < 3'd8)
                data_register[bit_idx] <= in;
            if (current_state == DATA)
                bit_idx <= bit_idx + 1;
            else if (current_state != DATA)
                bit_idx <= 3'd0;
        end
    end

    always_comb begin
        next_state = current_state;
        done = 1'b0;
        case (current_state)
            IDLE: begin
                if (in == 1'b0)
                    next_state = START;
            end
            START: begin
                if (in == 1'b0)
                    next_state = DATA;
                else
                    next_state = IDLE;
            end
            DATA: begin
                if (bit_idx == 3'd7)
                    next_state = STOP;
            end
            STOP: begin
                if (in == 1'b1) begin
                    next_state = IDLE;
                    done = 1'b1;
                    out_byte = data_register;
                end else
                    next_state = ERROR;
            end
            ERROR: begin
                if (in == 1'b1)
                    next_state = IDLE;
            end
        endcase
    end

endmodule

module top_module (
    input clk,
    input in,
    input reset,
    output reg [7:0] out_byte,
    output reg done
);

    typedef enum reg [2:0] {
        IDLE = 3'b000,
        START = 3'b001,
        DATA = 3'b010,
        STOP = 3'b011,
        WAIT_STOP = 3'b100
    } state_t;

    reg [2:0] state, next_state;
    reg [2:0] bit_count;
    reg [7:0] data_reg;

    // State transition
    always @(posedge clk or posedge reset) begin
        if (reset) begin
            state <= IDLE;
            bit_count <= 0;
            out_byte <= 8'b0;
            done <= 0;
            data_reg <= 8'b0;
        end else begin
            state <= next_state;

            if (state == DATA) begin
                data_reg[bit_count] <= in;
                bit_count <= bit_count + 1;
            end else if (state == STOP) begin
                out_byte <= data_reg;
                done <= 1;
            end else begin
                done <= 0;
                bit_count <= 0;
            end
        end
    end

    // Next state logic
    always @(*) begin
        case (state)
            IDLE: next_state = (in == 0) ? START : IDLE;
            START: next_state = DATA;
            DATA: next_state = (bit_count == 3'd7) ? STOP : DATA;
            STOP: next_state = (in == 1) ? IDLE : WAIT_STOP;
            WAIT_STOP: next_state = (in == 1) ? IDLE : WAIT_STOP;
            default: next_state = IDLE;
        endcase
    end

endmodule

module top_module (
    input clk,
    input in,
    input reset,
    output reg [7:0] out_byte,
    output reg done
);

    typedef enum logic [2:0] {
        IDLE  = 3'd0,
        START = 3'd1,
        DATA  = 3'd2,
        STOP  = 3'd3
    } state_t;

    state_t state, next_state;
    reg [2:0] bit_count;
    reg [7:0] data_byte;

    always_ff @(posedge clk or posedge reset) begin
        if (reset) begin
            state <= IDLE;
        end else begin
            state <= next_state;
        end
    end

    always_ff @(posedge clk) begin
        if (reset) begin
            bit_count <= 3'd0;
            data_byte <= 8'd0;
            out_byte <= 8'd0;
            done <= 1'b0;
        end else begin
            case (state)
                IDLE: begin
                    done <= 1'b0;
                    if (in == 1'b0) begin // Detect start bit
                        next_state <= START;
                    end
                end
                START: begin
                    if (in == 1'b0) begin // Valid start bit detected
                        next_state <= DATA;
                        bit_count <= 3'd0;
                    end else begin
                        next_state <= IDLE; // False start, go back to IDLE
                    end
                end
                DATA: begin
                    data_byte[bit_count] <= in;
                    bit_count <= bit_count + 3'd1;
                    if (bit_count == 3'd7) begin
                        next_state <= STOP;
                    end
                end
                STOP: begin
                    if (in == 1'b1) begin // Stop bit detected
                        done <= 1'b1;
                        out_byte <= data_byte;
                        next_state <= IDLE;
                    end else begin
                        next_state <= IDLE; // Stay in IDLE waiting for the next start bit
                    end
                end
                default: begin
                    next_state <= IDLE;
                end
            endcase
        end
    end

endmodule

module top_module (
    input clk,
    input in,
    input reset,
    output reg [7:0] out_byte,
    output reg done
);

    // State declaration
    typedef enum reg [2:0] {
        IDLE        = 3'b000,
        START_BIT   = 3'b001,
        DATA_BIT    = 3'b010,
        STOP_BIT    = 3'b011
    } state_t;

    state_t current_state, next_state;
    reg [2:0] bit_count;
    reg [7:0] data_reg;

    always @(posedge clk or posedge reset) begin
        if (reset) begin
            current_state <= IDLE;
            bit_count <= 3'd0;
            data_reg <= 8'd0;
            out_byte <= 8'd0;
            done <= 1'b0;
        end else begin
            current_state <= next_state;
            if (current_state == DATA_BIT) begin
                data_reg[bit_count] <= in;
                bit_count <= bit_count + 1;
            end
        end
    end

    always @(*) begin
        next_state = current_state;
        done = 1'b0;

        case (current_state)
            IDLE: begin
                if (in == 1'b0) // Detected start bit
                    next_state = START_BIT;
            end
            START_BIT: begin
                next_state = DATA_BIT;
                bit_count = 3'd0;
            end
            DATA_BIT: begin
                if (bit_count == 3'd7)
                    next_state = STOP_BIT;
            end
            STOP_BIT: begin
                if (in == 1'b1) begin // Check for stop bit
                    out_byte = data_reg;
                    done = 1'b1;
                    next_state = IDLE;
                end
            end
        endcase
    end

endmodule

module top_module (
    input clk,
    input in,
    input reset,
    output reg [7:0] out_byte,
    output reg done
);

    typedef enum reg [2:0] {
        IDLE  = 3'd0,
        START = 3'd1,
        DATA  = 3'd2,
        STOP  = 3'd3
    } state_t;

    reg [2:0] state, next_state;
    reg [2:0] bit_count;
    reg [7:0] data_shift_reg;

    always @(posedge clk or posedge reset) begin
        if (reset) begin
            state <= IDLE;
            done <= 0;
            bit_count <= 0;
            out_byte <= 8'b0;
        end else begin
            state <= next_state;
            if (next_state == DATA && state == START) begin
                bit_count <= 0;
            end else if (next_state == DATA) begin
                bit_count <= bit_count + 1;
            end
            if (state == DATA) begin
                data_shift_reg <= {in, data_shift_reg[7:1]};
            end
            if (state == STOP) begin
                out_byte <= data_shift_reg;
            end
        end
    end

    always @(*) begin
        done = 0;
        next_state = state;
        case (state)
            IDLE: begin
                if (in == 0)  // Detect start bit
                    next_state = START;
            end
            START: begin
                next_state = DATA;  // Move to DATA state
            end
            DATA: begin
                if (bit_count == 7)
                    next_state = (in == 1) ? STOP : IDLE;  // Expecting stop bit next
            end
            STOP: begin
                done = 1;
                if (in == 1)
                    next_state = IDLE;
            end
        endcase
    end
endmodule

module top_module (
	input clk,
	input in,
	input reset,
	output reg [7:0] out_byte,
	output reg done
);

    // FSM States
    typedef enum reg [3:0] {
        IDLE    = 4'd0,
        START   = 4'd1,
        BIT0    = 4'd2,
        BIT1    = 4'd3,
        BIT2    = 4'd4,
        BIT3    = 4'd5,
        BIT4    = 4'd6,
        BIT5    = 4'd7,
        BIT6    = 4'd8,
        BIT7    = 4'd9,
        STOP    = 4'd10
    } state_t;

    state_t current_state, next_state;
    reg [2:0] bit_count;
    reg [7:0] data_byte;

    always @(posedge clk or posedge reset) begin
        if (reset) begin
            current_state <= IDLE;
            done <= 1'b0;
            out_byte <= 8'b0;
            bit_count <= 3'b0;
            data_byte <= 8'b0;
        end else begin
            current_state <= next_state;
        end
    end

    always @(posedge clk) begin
        if (current_state == BIT0 ||
            current_state == BIT1 ||
            current_state == BIT2 ||
            current_state == BIT3 ||
            current_state == BIT4 ||
            current_state == BIT5 ||
            current_state == BIT6 ||
            current_state == BIT7) begin
            data_byte[bit_count] <= in;
        end
    end

    always @(*) begin
        // Default values
        next_state = current_state;
        done = 1'b0;

        case (current_state)
            IDLE: begin
                if (!in) // Wait for start bit
                    next_state = START;
            end

            START: begin
                next_state = BIT0;
                bit_count = 3'd0;
            end

            BIT0: begin
                next_state = BIT1;
                bit_count = 3'd1;
            end

            BIT1: begin
                next_state = BIT2;
                bit_count = 3'd2;
            end

            BIT2: begin
                next_state = BIT3;
                bit_count = 3'd3;
            end

            BIT3: begin
                next_state = BIT4;
                bit_count = 3'd4;
            end

            BIT4: begin
                next_state = BIT5;
                bit_count = 3'd5;
            end

            BIT5: begin
                next_state = BIT6;
                bit_count = 3'd6;
            end

            BIT6: begin
                next_state = BIT7;
                bit_count = 3'd7;
            end

            BIT7: begin
                next_state = STOP;
            end

            STOP: begin
                if (in) begin // Verify stop bit
                    done = 1'b1;
                    out_byte = data_byte;
                    next_state = IDLE;
                end else begin
                    next_state = IDLE; // Stay here until valid stop bit
                end
            end

            default: begin
                next_state = IDLE;
            end
        endcase
    end
endmodule

module top_module (
    input clk,
    input in,
    input reset,
    output reg [7:0] out_byte,
    output reg done
);

    typedef enum reg [2:0] {
        IDLE,   // Waiting for start bit
        START,  // Start bit detected
        DATA,   // Receiving data bits
        STOP,   // Checking stop bit
        VALID   // Stop bit validated
    } state_t;

    state_t state, next_state;
    reg [2:0] bit_count;
    reg [7:0] data_temp;

    always @(posedge clk or posedge reset) begin
        if (reset) begin
            state <= IDLE;
            out_byte <= 8'd0;
            done <= 1'b0;
            bit_count <= 3'd0;
            data_temp <= 8'd0;
        end else begin
            state <= next_state;
        end
    end

    always @(posedge clk) begin
        if (state == DATA && !reset) begin
            data_temp[bit_count] <= in;
            bit_count <= bit_count + 3'd1;
        end
    end

    always @(*) begin
        next_state = state;
        done = 1'b0;

        case (state)
            IDLE: begin
                if (in == 1'b0) begin  // Start bit detected
                    next_state = START;
                end
            end

            START: begin
                if (in == 1'b0) begin // Still in start bit
                    next_state = DATA;
                    bit_count = 3'd0;
                end else begin
                    next_state = IDLE; // False start bit detected, return to idle
                end
            end

            DATA: begin
                if (bit_count == 3'd7) begin
                    next_state = STOP;
                end
            end

            STOP: begin
                if (in == 1'b1) begin // Correct stop bit
                    out_byte = data_temp;
                    done = 1'b1;
                    next_state = VALID;
                end else begin
                    next_state = IDLE; // Stop bit error, return to idle and search for new start
                end
            end

            VALID: begin
                if (in == 1'b1) begin // Wait for stop bit to end
                    next_state = IDLE;
                end
            end
        endcase
    end

endmodule

module top_module (
    input clk,
    input in,
    input reset,
    output reg [7:0] out_byte,
    output reg done
);

    // Define states
    typedef enum logic [3:0] {
        IDLE       = 4'b0000,
        START_BIT  = 4'b0001,
        BIT_0      = 4'b0010,
        BIT_1      = 4'b0011,
        BIT_2      = 4'b0100,
        BIT_3      = 4'b0101,
        BIT_4      = 4'b0110,
        BIT_5      = 4'b0111,
        BIT_6      = 4'b1000,
        BIT_7      = 4'b1001,
        STOP_BIT   = 4'b1010
    } state_type;

    state_type current_state, next_state;
    reg [2:0] bit_count;   // To count the number of bits

    // State transition logic
    always @(posedge clk or posedge reset) begin
        if (reset) begin
            current_state <= IDLE;
            bit_count <= 3'd0;
            out_byte <= 8'd0;
            done <= 1'b0;
        end else begin
            current_state <= next_state;
        end
    end

    // Next state logic and output logic
    always @(*) begin
        next_state = current_state;
        done = 1'b0;

        case (current_state)
            IDLE: begin
                if (in == 1'b0) // Detected start bit (0)
                    next_state = START_BIT;
            end

            START_BIT: begin
                next_state = BIT_0;
                bit_count = 3'd0;
            end

            BIT_0: begin
                out_byte[0] = in;
                next_state = BIT_1;
            end

            BIT_1: begin
                out_byte[1] = in;
                next_state = BIT_2;
            end

            BIT_2: begin
                out_byte[2] = in;
                next_state = BIT_3;
            end

            BIT_3: begin
                out_byte[3] = in;
                next_state = BIT_4;
            end

            BIT_4: begin
                out_byte[4] = in;
                next_state = BIT_5;
            end

            BIT_5: begin
                out_byte[5] = in;
                next_state = BIT_6;
            end

            BIT_6: begin
                out_byte[6] = in;
                next_state = BIT_7;
            end

            BIT_7: begin
                out_byte[7] = in;
                next_state = STOP_BIT;
            end

            STOP_BIT: begin
                if (in == 1'b1) begin
                    done = 1'b1; // Valid stop bit detected
                    next_state = IDLE;
                end else begin
                    next_state = STOP_BIT; // Wait for a '1' stop bit
                end
            end

            default: next_state = IDLE;
        endcase
    end

endmodule

module top_module (
    input clk,
    input in,
    input reset,
    output reg [7:0] out_byte,
    output reg done
);

    reg [3:0] state, next_state;
    reg [7:0] data_buffer;
    reg [3:0] bit_counter;

    localparam IDLE       = 4'd0,
               START      = 4'd1,
               BIT0       = 4'd2,
               BIT1       = 4'd3,
               BIT2       = 4'd4,
               BIT3       = 4'd5,
               BIT4       = 4'd6,
               BIT5       = 4'd7,
               BIT6       = 4'd8,
               BIT7       = 4'd9,
               STOP       = 4'd10,
               ERROR      = 4'd11;

    // State transition
    always @(posedge clk or posedge reset) begin
        if (reset) begin
            state <= IDLE;
        end else begin
            state <= next_state;
        end
    end

    // Next state logic
    always @(*) begin
        next_state = state; // Default to current state
        done = 0;           // Default done to 0
        case (state)
            IDLE: begin
                if (in == 0)
                    next_state = START;
            end
            START: begin
                next_state = BIT0;
            end
            BIT0: begin
                next_state = BIT1;
            end
            BIT1: begin
                next_state = BIT2;
            end
            BIT2: begin
                next_state = BIT3;
            end
            BIT3: begin
                next_state = BIT4;
            end
            BIT4: begin
                next_state = BIT5;
            end
            BIT5: begin
                next_state = BIT6;
            end
            BIT6: begin
                next_state = BIT7;
            end
            BIT7: begin
                next_state = STOP;
            end
            STOP: begin
                if (in == 1) begin
                    next_state = IDLE;
                    done = 1;
                end else begin
                    next_state = ERROR;
                end
            end
            ERROR: begin
                if (in == 1)
                    next_state = IDLE;
            end
            default: next_state = IDLE;
        endcase
    end

    // Output logic and data capture
    always @(posedge clk or posedge reset) begin
        if (reset) begin
            out_byte <= 8'd0;
            data_buffer <= 8'd0;
            bit_counter <= 4'd0;
        end else begin
            case (state)
                START: begin
                    bit_counter <= 4'd0;
                end
                BIT0: begin
                    data_buffer[bit_counter] <= in;
                    bit_counter <= bit_counter + 1;
                end
                BIT1: begin
                    data_buffer[bit_counter] <= in;
                    bit_counter <= bit_counter + 1;
                end
                BIT2: begin
                    data_buffer[bit_counter] <= in;
                    bit_counter <= bit_counter + 1;
                end
                BIT3: begin
                    data_buffer[bit_counter] <= in;
                    bit_counter <= bit_counter + 1;
                end
                BIT4: begin
                    data_buffer[bit_counter] <= in;
                    bit_counter <= bit_counter + 1;
                end
                BIT5: begin
                    data_buffer[bit_counter] <= in;
                    bit_counter <= bit_counter + 1;
                end
                BIT6: begin
                    data_buffer[bit_counter] <= in;
                    bit_counter <= bit_counter + 1;
                end
                BIT7: begin
                    data_buffer[bit_counter] <= in;
                    bit_counter <= bit_counter + 1;
                end
                STOP: begin
                    if (in == 1) begin
                        out_byte <= data_buffer;
                    end
                end
            endcase
        end
    end

endmodule

module top_module (
    input clk,
    input in,
    input reset,
    output reg [7:0] out_byte,
    output reg done
);

    // State Encoding
    typedef enum reg [2:0] {
        IDLE = 3'b000,
        START_BIT = 3'b001,
        DATA_BITS = 3'b010,
        STOP_BIT = 3'b011,
        DONE = 3'b100
    } state_t;

    state_t state, next_state;
    reg [2:0] bit_count;
    reg [7:0] data_byte;

    // State Transition
    always @(posedge clk or posedge reset) begin
        if (reset) begin
            state <= IDLE;
            bit_count <= 3'b000;
            data_byte <= 8'b0;
            out_byte <= 8'b0;
            done <= 1'b0;
        end else begin
            state <= next_state;
            if (state == DATA_BITS) begin
                data_byte[bit_count] <= in;
                bit_count <= bit_count + 1'b1;
            end else if (state == IDLE || state == DONE) begin
                bit_count <= 3'b000;
            end
        end
    end

    // Next State Logic
    always @* begin
        next_state = state;  // Default: Remain in current state
        done = 1'b0;         // Default: done is 0
        case (state)
            IDLE: begin
                if (in == 1'b0)           // Detect start bit (0)
                    next_state = START_BIT;
            end
            START_BIT: begin
                next_state = DATA_BITS;  // Move to DATA_BITS state immediately
            end
            DATA_BITS: begin
                if (bit_count == 3'b111) // Check if 8 data bits are received
                    next_state = STOP_BIT;
            end
            STOP_BIT: begin
                if (in == 1'b1) begin    // Check for stop bit (1)
                    out_byte = data_byte;
                    done = 1'b1;
                    next_state = DONE;
                end else begin
                    next_state = IDLE;   // Go back to IDLE state if stop bit is incorrect
                end
            end
            DONE: begin
                next_state = IDLE;       // Go back to IDLE after asserting done
            end
        endcase
    end

endmodule

module top_module (
    input clk,
    input in,
    input reset,
    output reg [7:0] out_byte,
    output reg done
);

    typedef enum logic [2:0] {
        IDLE = 3'd0,
        START = 3'd1,
        DATA = 3'd2,
        STOP = 3'd3
    } state_t;

    state_t state, next_state;
    logic [2:0] bit_count;
    logic [7:0] data_shift_reg;

    always_ff @(posedge clk or posedge reset) begin
        if (reset) begin
            state <= IDLE;
            bit_count <= 3'd0;
            data_shift_reg <= 8'd0;
            done <= 1'b0;
            out_byte <= 8'd0;
        end else begin
            state <= next_state;
            if (state == DATA) begin
                bit_count <= bit_count + 3'd1;
                data_shift_reg <= {in, data_shift_reg[7:1]};
            end else begin
                bit_count <= 3'd0;
            end

            if (state == STOP && in == 1'b1) begin
                done <= 1'b1;
                out_byte <= data_shift_reg;
            end else begin
                done <= 1'b0;
            end
        end
    end

    always_comb begin
        case (state)
            IDLE: begin
                if (in == 1'b0)
                    next_state = START;
                else
                    next_state = IDLE;
            end
            START: begin
                next_state = DATA;
            end
            DATA: begin
                if (bit_count == 3'd7)
                    next_state = STOP;
                else
                    next_state = DATA;
            end
            STOP: begin
                if (in == 1'b1)
                    next_state = IDLE;
                else
                    next_state = STOP;
            end
            default: begin
                next_state = IDLE;
            end
        endcase
    end

endmodule

module top_module (
    input clk,
    input in,
    input reset,
    output reg [7:0] out_byte,
    output reg done
);

    // State encodings
    typedef enum reg [2:0] {
        IDLE = 3'b000,
        START = 3'b001,
        DATA = 3'b010,
        STOP = 3'b011,
        DONE = 3'b100
    } state_t;

    state_t current_state, next_state;
    reg [2:0] bit_count;

    always @(posedge clk or posedge reset) begin
        if (reset) begin
            current_state <= IDLE;
            bit_count <= 3'b000;
            done <= 1'b0;
            out_byte <= 8'b0;
        end else begin
            current_state <= next_state;
            if (current_state == DATA) begin
                out_byte[bit_count] <= in;
                bit_count <= bit_count + 1;
            end else if (current_state == DONE) begin
                done <= 1'b1;
            end else begin
                done <= 1'b0;
                bit_count <= 3'b000;
            end
        end
    end

    always @(*) begin
        next_state = current_state; // Default: stay in the current state
        case (current_state)
            IDLE: begin
                if (in == 1'b0) // Detected start bit
                    next_state = START;
            end
            START: begin
                next_state = DATA;
            end
            DATA: begin
                if (bit_count == 3'b111) // Once 8 data bits are received
                    next_state = STOP;
            end
            STOP: begin
                if (in == 1'b1) // Detected stop bit
                    next_state = DONE;
                else
                    next_state = IDLE; // Return to IDLE if stop bit is wrong
            end
            DONE: begin
                next_state = IDLE;
            end
        endcase
    end

endmodule

module top_module (
    input clk,
    input in,
    input reset,
    output reg [7:0] out_byte,
    output reg done
);

    // State encoding
    typedef enum logic [2:0] {
        IDLE      = 3'b000,
        START_BIT = 3'b001,
        DATA_BITS = 3'b010,
        STOP_BIT  = 3'b011,
        DONE      = 3'b100
    } state_t;

    state_t current_state, next_state;
    reg [2:0] bit_count;         // Counter for tracking data bits (3 bits is sufficient for counting to 8)
    reg [7:0] byte_buffer;       // Temporary storage for received byte

    always @(posedge clk or posedge reset) begin
        if (reset) begin
            current_state <= IDLE;
            bit_count <= 3'd0;
            byte_buffer <= 8'd0;
            out_byte <= 8'd0;
            done <= 0;
        end else begin
            current_state <= next_state;

            if (current_state == DATA_BITS) begin
                // Shift in data bits
                byte_buffer <= {in, byte_buffer[7:1]};
                bit_count <= bit_count + 1;
            end

            if (current_state == DONE) begin
                // Capture the valid byte and signal done
                out_byte <= byte_buffer;
                done <= 1;
            end else begin
                done <= 0;
            end
        end
    end

    always @(*) begin
        next_state = current_state; // Default: stay in the current state
        case (current_state)
            IDLE: begin
                if (in == 0)  // Look for start bit (0)
                    next_state = START_BIT;
            end

            START_BIT: begin
                // Move to data bits collection
                next_state = DATA_BITS;
                bit_count = 3'd0; // Initialize bit counter
            end

            DATA_BITS: begin
                if (bit_count == 3'd7) // Last bit received
                    next_state = STOP_BIT;
            end

            STOP_BIT: begin
                if (in == 1)  // Verify stop bit (1)
                    next_state = DONE;
                else
                    next_state = IDLE; // Stop bit was incorrect, wait for a new stop bit
            end

            DONE: begin
                next_state = IDLE; // Return to idle after processing complete
            end

            default: next_state = IDLE;
        endcase
    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 [0:127]; // 128-entry table of two-bit saturating counters

    wire [6:0] predict_index = predict_pc ^ global_history;
    wire [6:0] train_index = train_pc ^ train_history;

    // Asynchronous reset
    always @(posedge clk or posedge areset) begin
        if (areset) begin
            global_history <= 7'b0;
            integer i;
            for (i = 0; i < 128; i = i + 1)
                PHT[i] <= 2'b01; // Initialize PHT to weakly not taken
        end else begin
            if (train_valid) begin
                // Perform training updates
                if (train_mispredicted) begin
                    global_history <= train_history;
                end

                // Update counter in PHT
                if (train_taken) begin
                    if (PHT[train_index] < 2'b11)
                        PHT[train_index] <= PHT[train_index] + 1;
                end else begin
                    if (PHT[train_index] > 2'b00)
                        PHT[train_index] <= PHT[train_index] - 1;
                end
            end

            if (predict_valid && !train_valid) begin
                // Update global history with the latest prediction
                global_history <= {global_history[5:0], predict_taken};
            end
        end
    end

    always @(*) begin
        if (predict_valid) begin
            predict_history = global_history;
            case (PHT[predict_index])
                2'b00, 2'b01: predict_taken = 1'b0; // Weakly or strongly not taken
                2'b10, 2'b11: predict_taken = 1'b1; // Weakly or strongly taken
                default: predict_taken = 1'b0;
            endcase
        end else begin
            predict_taken = 1'b0;
            predict_history = 7'b0;
        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];  // 128-entry table of 2-bit saturating counters
    reg [6:0] global_history;

    // XOR-based hashing
    wire [6:0] predict_index = predict_pc ^ global_history;
    wire [6:0] train_index = train_pc ^ train_history;

    integer i;
    initial begin
        // Initialize the PHT and global history
        for (i = 0; i < 128; i = i + 1)
            PHT[i] = 2'b01; // Weakly not taken by default
        global_history = 7'b0;
    end

    // Prediction logic
    always @(*) begin
        if (predict_valid) begin
            predict_taken = PHT[predict_index] >= 2'b10;  // Predict taken if counter is 2 or 3
            predict_history = global_history;
        end
    end

    // Training and prediction update
    always @(posedge clk or posedge areset) begin
        if (areset) begin
            // Reset state
            for (i = 0; i < 128; i = i + 1)
                PHT[i] <= 2'b01; // Weakly not taken by default
            global_history <= 7'b0;
        end else begin
            if (train_valid) begin
                // Train the PHT using the true outcome
                if (train_taken) begin
                    // Increment the saturating counter
                    if (PHT[train_index] < 2'b11)
                        PHT[train_index] <= PHT[train_index] + 1;
                end else begin
                    // Decrement the saturating counter
                    if (PHT[train_index] > 2'b00)
                        PHT[train_index] <= PHT[train_index] - 1;
                end

                // Handle misprediction recovery
                if (train_mispredicted)
                    global_history <= {train_history[5:0], train_taken};
                else
                    global_history <= {global_history[5:0], predict_taken};
            end else if (predict_valid) begin
                // No training, update history with last prediction outcome
                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 [6:0] global_history;
	reg [1:0] pht [0:127]; // 128-entry table of 2-bit saturating counters
	integer i;

	always @(posedge clk or posedge areset) begin
		if (areset) begin
			global_history <= 7'b0;
			for (i = 0; i < 128; i = i + 1) begin
				pht[i] <= 2'b01; // Weakly not-taken (initializing the PHT)
			end
		end else begin
			if (train_valid) begin
				// Calculate the index for training
				integer train_index = train_pc ^ train_history;
				// Update PHT
				if (train_taken) begin
					// Increment saturating counter if taken
					if (pht[train_index] != 2'b11) begin
						pht[train_index] <= pht[train_index] + 1;
					end
				end else begin
					// Decrement saturating counter if not taken
					if (pht[train_index] != 2'b00) begin
						pht[train_index] <= pht[train_index] - 1;
					end
				end
				// Update global history after misprediction recovery
				if (train_mispredicted) begin
					global_history <= {train_history[5:0], train_taken};
				end
			end
			// Update global history with predicted outcome
			if (!train_valid && predict_valid) begin
				global_history <= {global_history[5:0], predict_taken};
			end
		end
	end

	always @(*) begin
		// Default values
		predict_taken = 1'b0;
		predict_history = global_history;

		if (predict_valid) begin
			// Calculate the index for prediction
			integer predict_index = predict_pc ^ global_history;
			// Access PHT to get prediction
			predict_taken = pht[predict_index][1];
			predict_history = global_history;
		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 [0:127]; // 128-entry table of two-bit saturating counters

    wire [6:0] predict_index, train_index;
    assign predict_index = predict_pc ^ global_history;
    assign train_index = train_pc ^ train_history;

    // Asynchronous reset and updating the global history register
    always @(posedge clk or posedge areset) begin
        if (areset) begin
            global_history <= 0;
        end
        else begin
            if (predict_valid && !(train_valid && train_mispredicted)) begin
                // Update global history with the predicted outcome
                global_history <= {global_history[5:0], predict_taken};
            end
            else if (train_valid && train_mispredicted) begin
                // Recover global history on misprediction
                global_history <= {train_history[5:0], train_taken};
            end
        end
    end

    // Prediction logic
    always @(*) begin
        if (predict_valid) begin
            predict_taken = PHT[predict_index][1];
            predict_history = global_history;
        end
        else begin
            predict_taken = 0;
            predict_history = 7'b0;
        end
    end

    // Training logic
    always @(posedge clk) begin
        if (train_valid) begin
            case ({train_taken, PHT[train_index]})
                3'b00: PHT[train_index] <= 2'b00;
                3'b01: PHT[train_index] <= 2'b00;
                3'b10: PHT[train_index] <= 2'b01;
                3'b11: PHT[train_index] <= 2'b10;
                3'b01: PHT[train_index] <= 2'b01;
                3'b11: PHT[train_index] <= 2'b11;
                3'b00: PHT[train_index] <= 2'b10;
                3'b10: PHT[train_index] <= 2'b11;
            endcase
        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
);

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

	wire [6:0] predict_index;
	wire [6:0] train_index;

	assign predict_index = predict_pc ^ GHR;
	assign train_index = train_pc ^ train_history;

	// Predict logic
	assign predict_taken = PHT[predict_index][1];
	assign predict_history = GHR;

	// Update logic for PHT during training
	always @(posedge clk or posedge areset) begin
		if (areset) begin
			// Asynchronously reset GHR and PHT
			GHR <= 7'b0;
			integer i;
			for (i = 0; i < 128; i = i + 1) begin
				PHT[i] <= 2'b01;
			end
		end else begin
			// Update predict history register
			if (predict_valid && !(train_valid && train_mispredicted)) begin
				GHR <= {GHR[5:0], predict_taken};
			end

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

				if (train_mispredicted) begin
					GHR <= {train_history[6:1], train_taken};
				end else if (!predict_valid) begin
					GHR <= {GHR[5:0], predict_taken};
				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
);

    // Two-bit saturating counter states
    localparam ST = 2'b11; // Strongly taken
    localparam WT = 2'b10; // Weakly taken
    localparam WN = 2'b01; // Weakly not taken
    localparam SN = 2'b00; // Strongly not taken

    reg [1:0] pht [0:127];       // Pattern history table with 128 entries of 2-bit counters
    reg [6:0] bhr;               // Global branch history register

    wire [6:0] predict_index;
    wire [6:0] train_index;

    // XOR hash: PC ^ Global History
    assign predict_index = predict_pc ^ bhr;
    assign train_index = train_pc ^ train_history;

    integer i;
    always @(posedge clk or posedge areset) begin
        if (areset) begin
            // Reset all PHT counters and branch history register
            for (i = 0; i < 128; i = i + 1) begin
                pht[i] <= WN; // Initialize to weakly not taken (neutral start)
            end
            bhr <= 7'b0;
        end else begin
            if (train_valid) begin
                // Update PHT based on actual outcome
                case(pht[train_index])
                    ST: pht[train_index] <= train_taken ? ST : WT;
                    WT: pht[train_index] <= train_taken ? ST : WN;
                    WN: pht[train_index] <= train_taken ? WT : SN;
                    SN: pht[train_index] <= train_taken ? WN : SN;
                endcase

                // Update the branch history register in case of misprediction
                if (train_mispredicted) begin
                    bhr <= {train_history[5:0], train_taken};
                end
            end

            // Update branch history register for predictions not being trained
            if (predict_valid && !(train_valid && train_mispredicted)) begin
                bhr <= {bhr[5:0], predict_taken};
            end
        end
    end

    // Combinational logic for prediction
    always @(*) begin
        if (predict_valid) begin
            // Predict based on the current state of PHT
            case(pht[predict_index])
                ST, WT: predict_taken = 1'b1;
                WN, SN: predict_taken = 1'b0;
            endcase

            // Output the state of branch history register used for prediction
            predict_history = bhr;
        end else begin
            predict_taken = 1'b0;
            predict_history = 7'b0;
        end
    end

endmodule

module top_module(
    input clk,
    input areset,

    input predict_valid,
    input [6:0] predict_pc,
    output 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]; // 128-entry table of two-bit saturating counters
    reg [6:0] global_history; // 7-bit global branch history register

    integer i;

    wire [6:0] predict_index = predict_pc ^ global_history; // Hash pc and history
    wire [6:0] train_index = train_pc ^ train_history;

    always @(posedge clk or posedge areset) begin
        if (areset) begin
            global_history <= 7'b0;
            predict_history <= 7'b0;
            for (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_taken) begin
                    if (PHT[train_index] < 2'b11) begin
                        PHT[train_index] <= PHT[train_index] + 1;
                    end
                end else begin
                    if (PHT[train_index] > 2'b00) begin
                        PHT[train_index] <= PHT[train_index] - 1;
                    end
                end
                if (train_mispredicted) begin
                    global_history <= train_history;
                end
            end

            if (predict_valid && !train_valid) begin
                global_history <= {global_history[5:0], predict_taken};
            end

            predict_history <= global_history;
        end
    end

    assign predict_taken = (PHT[predict_index] >= 2'b10);

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

    // Global branch history register
    reg [6:0] global_bhr;

    // Pattern history table (PHT) with 128 entries of 2-bit saturating counters
    reg [1:0] PHT [0:127];

    wire [6:0] predict_index = predict_pc ^ global_bhr; // Predict index using XOR
    wire [6:0] train_index = train_pc ^ train_history; // Train index using XOR

    reg [1:0] predict_counter;
    reg [1:0] train_counter;

    // Predict taken based on the most significant bit of the counter (strong = 1, weak = 0)
    assign predict_taken = predict_counter[1];
    assign predict_history = global_bhr;

    // Update logic for saturating counter
    always @* begin
        // Read the counter value for prediction
        if (predict_valid) begin
            predict_counter = PHT[predict_index];
        end else begin
            predict_counter = 2'b00;
        end

        // Read the counter value for training
        if (train_valid) begin
            train_counter = PHT[train_index];
        end else begin
            train_counter = 2'b00;
        end
    end

    // Sequential logic
    always @(posedge clk or posedge areset) begin
        if (areset) begin
            global_bhr <= 7'b0; // Reset the global branch history register
            // Reset all PHT entries to weakly taken (10)
            integer i;
            for (i = 0; i < 128; i = i + 1) begin
                PHT[i] <= 2'b10;
            end
        end else begin
            // Update the branch history register for prediction
            if (predict_valid && (!train_valid || !train_mispredicted)) begin
                global_bhr <= {global_bhr[5:0], predict_taken}; // Shift in the predicted outcome
            end

            // Update the PHT based on training
            if (train_valid) begin
                if (train_taken) begin
                    if (train_counter != 2'b11) begin
                        PHT[train_index] <= train_counter + 2'b01;
                    end
                end else begin
                    if (train_counter != 2'b00) begin
                        PHT[train_index] <= train_counter - 2'b01;
                    end
                end

                // Recover the branch history register if there was a misprediction
                if (train_mispredicted) begin
                    global_bhr <= {train_history[5:0], train_taken}; // Recover BHR
                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
);

    // Define parameters
    parameter PHT_SIZE = 128;
    parameter PHT_BITS = 2; // Two-bit saturating counters

    // Two-bit saturating counters
    // 2'b00: Strongly not taken
    // 2'b01: Weakly not taken
    // 2'b10: Weakly taken
    // 2'b11: Strongly taken

    // Define registers
    reg [PHT_BITS-1:0] PHT [0:PHT_SIZE-1]; // Pattern History Table
    reg [6:0] global_history; // Global branch history register

    // Internal wires
    wire [6:0] predict_index;
    wire [6:0] train_index;
    wire [PHT_BITS-1:0] pht_predict_value;

    // Compute the XOR indices
    assign predict_index = predict_pc ^ global_history;
    assign train_index = train_pc ^ train_history;

    // Generate prediction
    always @(*) begin
        if (predict_valid) begin
            pht_predict_value = PHT[predict_index];
            predict_taken = pht_predict_value[1]; // MSB indicates the prediction
            predict_history = global_history;
        end
    end

    // Update routine on the clock's rising edge
    always @(posedge clk or posedge areset) begin
        if (areset) begin
            // Asynchronous reset
            global_history <= 7'b0;
        end else begin
            if (train_valid) begin
                // Update branch history for mispredictions
                if (train_mispredicted) begin
                    global_history <= {train_history[5:0], train_taken};
                end

                // Update Pattern History Table
                if (train_taken) begin
                    if (PHT[train_index] < 2'b11) PHT[train_index] <= PHT[train_index] + 1'b1;
                end else begin
                    if (PHT[train_index] > 2'b00) PHT[train_index] <= PHT[train_index] - 1'b1;
                end
            end

            // Update global history based on prediction if training doesn't take precedence
            if (predict_valid && !(train_valid && train_mispredicted)) 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
);

    // Declarations
    reg [1:0] PHT[0:127]; // Pattern History Table with 128 entries (2-bit counters)
    reg [6:0] global_history; // Global branch history register

    integer i;

    // Asynchronous reset
    always @(posedge clk or posedge areset) begin
        if (areset) begin
            global_history <= 7'b0;
            predict_taken <= 1'b0;
            predict_history <= 7'b0;
            // Reset all PHT counters to weakly not taken (01)
            for (i = 0; i < 128; i = i + 1) begin
                PHT[i] <= 2'b01;
            end
        end else begin
            if (train_valid) begin
                // Calculate index for training using XOR between train_pc and train_history
                reg [6:0] train_index;
                train_index = train_pc ^ train_history;

                // Update PHT entry for training
                case ({train_taken, PHT[train_index]})
                    3'b10: PHT[train_index] <= PHT[train_index] + 1; // Taken branch, increment counter
                    3'b00: PHT[train_index] <= PHT[train_index] - 1; // Not taken branch, decrement counter
                    default: PHT[train_index] <= PHT[train_index]; // Saturating counters
                endcase

                // If branch is mispredicted, recover the global history register
                if (train_mispredicted) begin
                    global_history <= train_history;
                end
            end else if (predict_valid) begin
                // Calculate index for prediction using XOR between predict_pc and global_history
                reg [6:0] predict_index;
                predict_index = predict_pc ^ global_history;

                // Make prediction based on PHT entry
                predict_taken <= (PHT[predict_index] >= 2'b10);

                // Update global history register after prediction
                global_history <= {global_history[5:0], predict_taken};
            end
            // Always remember the state of the branch history register used to make prediction
            predict_history <= global_history;
        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 2-bit saturating counters
    reg [6:0] global_history;

    wire [6:0] predict_index;
    wire [6:0] train_index;

    assign predict_index = predict_pc ^ global_history;
    assign train_index = train_pc ^ train_history;

    integer i;

    // Initialize on reset
    initial begin
        for (i = 0; i < 128; i = i + 1) begin
            PHT[i] = 2'b01; // Weakly not taken
        end
        global_history = 7'd0;
    end

    always @(posedge clk or posedge areset) begin
        if (areset) begin
            for (i = 0; i < 128; i = i + 1) begin
                PHT[i] <= 2'b01; // Weakly not taken
            end
            global_history <= 7'd0;
        end else begin
            if (train_valid) begin
                // Train the PHT
                if (train_taken) begin
                    if (PHT[train_index] != 2'b11) begin
                        PHT[train_index] <= PHT[train_index] + 1;
                    end
                end else begin
                    if (PHT[train_index] != 2'b00) begin
                        PHT[train_index] <= PHT[train_index] - 1;
                    end
                end

                // Update global history
                if (train_mispredicted) begin
                    global_history <= {global_history[5:0], train_taken};
                end else begin
                    global_history <= {train_history[5:0], train_taken};
                end
            end else if (predict_valid) begin
                // Update global history for prediction
                global_history <= {global_history[5:0], predict_taken};
            end
        end
    end

    always @(*) begin
        if (predict_valid) begin
            predict_taken = (PHT[predict_index] >= 2'b10);
            predict_history = global_history;
        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
);

    // 128-entry Pattern History Table of 2-bit saturating counters
    reg [1:0] pht [127:0];
    reg [6:0] global_history;

    // Compute index by XORing PC and Global History
    wire [6:0] predict_index = predict_pc ^ global_history;
    wire [6:0] train_index = train_pc ^ train_history;

    always @(posedge clk or posedge areset) begin
        if (areset) begin
            // Initialize PHT and Global History Register on reset
            for (integer i = 0; i < 128; i = i + 1) begin
                pht[i] <= 2'b01; // Weakly not-taken state
            end
            global_history <= 7'b0;
        end else begin
            // Training logic
            if (train_valid) begin
                // Update the PHT entry for the training index
                if (train_taken) begin
                    if (pht[train_index] != 2'b11) begin
                        pht[train_index] <= pht[train_index] + 1'b1;
                    end
                end else begin
                    if (pht[train_index] != 2'b00) begin
                        pht[train_index] <= pht[train_index] - 1'b1;
                    end
                end

                // Handle misprediction
                if (train_mispredicted) begin
                    // Recover the global history register to the point after the misprediction
                    global_history <= {global_history[5:0], train_taken};
                end
            end

            // If no misprediction or no train_valid, update global history
            if (predict_valid && !train_valid) begin
                global_history <= {global_history[5:0], predict_taken};
            end
        end
    end

    always @(*) begin
        // Prediction logic
        if (predict_valid) begin
            case (pht[predict_index])
                2'b00, 2'b01: predict_taken = 1'b0; // Predict not-taken
                2'b10, 2'b11: predict_taken = 1'b1; // Predict taken
            endcase
            predict_history = global_history;
        end else begin
            predict_taken = 1'b0;
            predict_history = 7'b0;
        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
);

    // Two-bit saturating counter states
    localparam STRONGLY_NOT_TAKEN = 2'b00;
    localparam WEAKLY_NOT_TAKEN = 2'b01;
    localparam WEAKLY_TAKEN = 2'b10;
    localparam STRONGLY_TAKEN = 2'b11;

    // PHT: Pattern History Table as an array of two-bit saturating counters
    reg [1:0] PHT [0:127];

    // Global history register
    reg [6:0] global_history;

    // XOR result for index
    wire [6:0] index_predict, index_train;

    assign index_predict = predict_pc ^ global_history;
    assign index_train = train_pc ^ train_history;

    // PHT read during prediction
    reg [1:0] predict_pht_entry;

    always @(posedge clk or posedge areset) begin
        if (areset) begin
            // Reset global history and PHT entries
            global_history <= 7'b0;
            integer i;
            for (i = 0; i < 128; i = i + 1) begin
                PHT[i] <= WEAKLY_NOT_TAKEN;  // Initialize PHT entries to weakly not taken
            end
        end else begin
            // Prediction logic
            if (predict_valid) begin
                predict_pht_entry <= PHT[index_predict];
                predict_taken <= (predict_pht_entry[1] == 1'b1);  // If MSB is 1, predict taken
                predict_history <= global_history;
                // Update the global history register for the next operation
                global_history <= {global_history[5:0], predict_taken};
            end

            // Training logic
            if (train_valid) begin
                // Update PHT based on actual outcome
                case (PHT[index_train])
                    STRONGLY_NOT_TAKEN: PHT[index_train] <= train_taken ? WEAKLY_NOT_TAKEN : STRONGLY_NOT_TAKEN;
                    WEAKLY_NOT_TAKEN: PHT[index_train] <= train_taken ? WEAKLY_TAKEN : STRONGLY_NOT_TAKEN;
                    WEAKLY_TAKEN: PHT[index_train] <= train_taken ? STRONGLY_TAKEN : WEAKLY_NOT_TAKEN;
                    STRONGLY_TAKEN: PHT[index_train] <= train_taken ? STRONGLY_TAKEN : WEAKLY_TAKEN;
                endcase

                // If there was a misprediction, recover the global history register
                if (train_mispredicted) begin
                    global_history <= {train_history[5:0], train_taken};  // Recover branch history state
                end else begin
                    // Normally update global history at the next positive clock edge
                    global_history <= {global_history[5:0], train_taken};
                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
);

    // 128-entry table of 2-bit saturating counters (using 256 bits)
    reg [1:0] PHT [0:127];

    // 7-bit Global Branch History Register
    reg [6:0] global_history;

    integer i;

    // Async reset and initialize
    always @(posedge clk or posedge areset) begin
        if (areset) begin
            global_history <= 7'b0;
            for (i = 0; i < 128; i = i + 1) begin
                PHT[i] <= 2'b01; // Initialize to weakly not taken state
            end
        end
        else begin
            if (train_valid) begin
                // Calculate the index using XOR for training
                if (train_mispredicted) begin
                    global_history <= train_history;
                end else begin
                    global_history <= {global_history[5:0], train_taken};
                end
                // Update PHT entry based on the actual outcome
                if (train_taken) begin
                    if (PHT[train_pc ^ train_history] != 2'b11) begin
                        PHT[train_pc ^ train_history] <= PHT[train_pc ^ train_history] + 1;
                    end
                end else begin
                    if (PHT[train_pc ^ train_history] != 2'b00) begin
                        PHT[train_pc ^ train_history] <= PHT[train_pc ^ train_history] - 1;
                    end
                end
            end
            else if (predict_valid) begin
                global_history <= {global_history[5:0], predict_taken};
            end
        end
    end

    always @(*) begin
        if (predict_valid) begin
            // Calculate the index using XOR for prediction
            predict_history = global_history;
            predict_taken = (PHT[predict_pc ^ global_history][1] == 1);
        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]; // 128-entry table of 2-bit saturating counters
    reg [6:0] global_history_register;
    wire [6:0] predict_index, train_index;

    assign predict_index = predict_pc ^ global_history_register;
    assign train_index = train_pc ^ train_history;

    always @(*) begin
        if (PHT[predict_index] == 2'b00 || PHT[predict_index] == 2'b01) begin
            predict_taken = 0;
        end else begin
            predict_taken = 1;
        end
        predict_history = global_history_register;
    end

    always @(posedge clk or posedge areset) begin
        if (areset) begin
            integer i;
            for (i = 0; i < 128; i = i + 1) begin
                PHT[i] <= 2'b01; // Initialize weakly not taken
            end
            global_history_register <= 7'b0;
        end else begin
            if (train_valid) begin
                // Update PHT based on actual outcome
                if (train_taken) begin
                    if (PHT[train_index] != 2'b11) begin
                        PHT[train_index] <= PHT[train_index] + 1;
                    end
                end else begin
                    if (PHT[train_index] != 2'b00) begin
                        PHT[train_index] <= PHT[train_index] - 1;
                    end
                end

                // Update global history register
                global_history_register <= {global_history_register[5:0], train_taken};

                // Recover history register if misprediction
                if (train_mispredicted) begin
                    global_history_register <= {train_history[5:0], train_taken};
                end
            end else if (predict_valid) begin
                // Update global history register for predicted branch
                global_history_register <= {global_history_register[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 [0:127]; // 128-entry table of 2-bit saturating counters
    reg [6:0] global_history; // 7-bit global history register
    integer i;

    // Asynchronous reset
    always @(posedge clk or posedge areset) begin
        if (areset) begin
            global_history <= 7'b0;
            for (i = 0; i < 128; i = i + 1) begin
                PHT[i] <= 2'b01; // Weakly not taken state
            end
        end else begin
            if (train_valid) begin
                // Calculate index based on history and PC
                integer train_index;
                train_index = train_history ^ train_pc;

                // Train PHT
                if (train_taken) begin
                    if (PHT[train_index] != 2'b11) begin
                        PHT[train_index] <= PHT[train_index] + 1;
                    end
                end else begin
                    if (PHT[train_index] != 2'b00) begin
                        PHT[train_index] <= PHT[train_index] - 1;
                    end
                end

                // Recover global history register if mispredicted
                if (train_mispredicted) begin
                    global_history <= (global_history << 1) | train_taken;
                end
            end else if (predict_valid) begin
                // Prediction based on current PC and global history
                integer predict_index;
                predict_index = global_history ^ predict_pc;

                // Predict based on PHT
                predict_taken <= (PHT[predict_index] >= 2'b10);
                predict_history <= global_history;

                // Update global history (regardless of predict_taken)
                global_history <= (global_history << 1) | predict_taken;
            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
);

    // Define states for 2-bit saturating counter
    localparam ST = 2'b11; // Strongly Taken
    localparam WT = 2'b10; // Weakly Taken
    localparam WN = 2'b01; // Weakly Not Taken
    localparam SN = 2'b00; // Strongly Not Taken

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

    wire [6:0] predict_index;
    wire [6:0] train_index;

    // Compute indices using XOR hashing
    assign predict_index = predict_pc ^ GHR;
    assign train_index = train_pc ^ train_history;

    // Output the current global history for predictions
    assign predict_history = GHR;

    // Predict taken or not based on the PHT counter value
    assign predict_taken = (PHT[predict_index] == ST) || (PHT[predict_index] == WT);

    integer i;

    always @(posedge clk or posedge areset) begin
        if (areset) begin
            // Reset logic
            GHR <= 7'b0;
            // Initialize all PHT to Weakly Not Taken
            for (i = 0; i < 128; i = i + 1) begin
                PHT[i] <= WN;
            end
        end else begin
            // Prediction Phase: Update global history register
            if (predict_valid) begin
                GHR <= {GHR[5:0], predict_taken};
            end

            // Training Phase
            if (train_valid) begin
                // Update the PHT based on the actual outcome
                case (PHT[train_index])
                    ST: PHT[train_index] <= train_taken ? ST : WT;
                    WT: PHT[train_index] <= train_taken ? ST : WN;
                    WN: PHT[train_index] <= train_taken ? WT : SN;
                    SN: PHT[train_index] <= train_taken ? WN : SN;
                endcase

                // Recover the GHR if there was a misprediction
                if (train_mispredicted) begin
                    GHR <= {train_history[5:0], train_taken};
                end
            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
);

    reg [1:0] PHT [127:0];  // 128-entry table of 2-bit saturating counters
    reg [6:0] global_history;  // 7-bit global history register
    wire [6:0] predict_index;
    wire [6:0] train_index;
    wire [1:0] predict_counter;
    reg [1:0] train_counter;

    assign predict_index = predict_pc ^ global_history;
    assign train_index = train_pc ^ train_history;
    assign predict_counter = PHT[predict_index];

    // Two-bit saturating counter logic
    always @(posedge clk or posedge areset) begin
        if (areset) begin
            global_history <= 7'b0;
            integer i;
            for (i = 0; i < 128; i = i + 1) begin
                PHT[i] <= 2'b01;  // weakly not taken
            end
        end else begin
            if (train_valid) begin
                train_counter = PHT[train_index];
                if (train_taken) begin
                    if (train_counter != 2'b11)
                        train_counter = train_counter + 1'b1;
                end else begin
                    if (train_counter != 2'b00)
                        train_counter = train_counter - 1'b1;
                end
                if (train_mispredicted) begin
                    global_history <= {global_history[5:0], train_taken};
                end else if (predict_valid) begin
                    global_history <= {global_history[5:0], (predict_counter[1] == 1'b1)};
                end
                PHT[train_index] <= train_counter;
            end else if (predict_valid) begin
                global_history <= {global_history[5:0], (predict_counter[1] == 1'b1)};
            end
        end
    end

    assign predict_taken = predict_counter[1];
    assign predict_history = global_history;

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 counters
	reg [6:0] global_history;

	integer i;

	always @(posedge clk or posedge areset) begin
		if (areset) begin
			// Asynchronous reset
			for (i = 0; i < 128; i = i + 1)
				PHT[i] <= 2'b01; // Weakly taken state
			global_history <= 7'b0;
		end else begin
			// Training
			if (train_valid) begin
				integer train_index;
				train_index = train_pc ^ train_history;
				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

				if (train_mispredicted) begin
					global_history <= train_history; // Recover branch history
				end
			end

			// Update history register for prediction
			if (predict_valid && !train_valid) begin
				global_history <= {global_history[5:0], predict_taken};
			end
		end
	end

	always @(*) begin
		if (predict_valid) begin
			// Determine prediction
			integer predict_index;
			predict_index = predict_pc ^ global_history;
			predict_taken = (PHT[predict_index] >= 2'b10);

			// Provide current history used for prediction
			predict_history = global_history;
		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
);

	// Define the Global History Register (GHR)
	reg [6:0] GHR;

	// Define 128-entry Pattern History Table (PHT) with 2-bit saturating counters
	reg [1:0] PHT [0:127];

	// Temporary variables for prediction and training
	wire [6:0] predict_index;
	wire [6:0] train_index;
	reg [1:0] predict_value;
	reg [1:0] train_value;

	// Predict index is calculated by XOR'ing the PC with the GHR
	assign predict_index = predict_pc ^ GHR;
	// Train index is calculated by XOR'ing the train PC with the train history
	assign train_index = train_pc ^ train_history;

	// Output current prediction and history
	assign predict_taken = predict_value[1];
	assign predict_history = GHR;

	// Always block for prediction
	always @(*) begin
		if (predict_valid) begin
			predict_value = PHT[predict_index];
		end else begin
			predict_value = 2'b00; // Default prediction
		end
	end

	// Always block for sequential logic (PHT update and GHR update)
	always @(posedge clk or posedge areset) begin
		if (areset) begin
			// Asynchronous reset
			GHR <= 7'b0;
			integer i;
			for (i = 0; i < 128; i = i + 1) begin
				PHT[i] <= 2'b01; // Weakly not taken
			end
		end else begin
			// Handle training and updates
			if (train_valid) begin
				// Update PHT based on train outcome
				train_value = PHT[train_index];
				if (train_taken) begin
					if (train_value != 2'b11) begin
						PHT[train_index] <= train_value + 1;
					end
				end else begin
					if (train_value != 2'b00) begin
						PHT[train_index] <= train_value - 1;
					end
				end

				// Recover GHR if it's a misprediction
				if (train_mispredicted) begin
					GHR <= {train_history[5:0], train_taken};
				end else begin
					GHR <= {GHR[5:0], train_taken};
				end
			end else if (predict_valid) begin
				// Update GHR with prediction (if no training is done)
				GHR <= {GHR[5:0], predict_value[1]};
			end
		end
	end

endmodule