module top_of_book_builder (
    input wire clk,
    input wire rst,
    input wire upd_valid,
    input wire upd_side,
    input wire [3:0] price_idx,
    input wire [15:0] upd_qty,
    output reg book_valid,
    output reg [3:0] best_bid_idx,
    output reg [15:0] best_bid_qty,
    output reg [3:0] best_ask_idx,
    output reg [15:0] best_ask_qty,
    output reg [3:0] spread_ticks
);
    reg [15:0] bid_book [0:15];
    reg [15:0] ask_book [0:15];

    integer i;
    reg bid_found;
    reg ask_found;
    reg [3:0] next_bid_idx;
    reg [15:0] next_bid_qty;
    reg [3:0] next_ask_idx;
    reg [15:0] next_ask_qty;
    reg [15:0] level_qty;

    always @(posedge clk) begin
        if (rst) begin
            for (i = 0; i < 16; i = i + 1) begin
                bid_book[i] <= 16'd0;
                ask_book[i] <= 16'd0;
            end

            book_valid <= 1'b0;
            best_bid_idx <= 4'd0;
            best_bid_qty <= 16'd0;
            best_ask_idx <= 4'd0;
            best_ask_qty <= 16'd0;
            spread_ticks <= 4'd0;
        end else if (upd_valid) begin
            if (upd_side == 1'b0)
                bid_book[price_idx] <= upd_qty;
            else
                ask_book[price_idx] <= upd_qty;

            bid_found = 1'b0;
            next_bid_idx = 4'd0;
            next_bid_qty = 16'd0;
            for (i = 15; i >= 0; i = i - 1) begin
                if ((upd_side == 1'b0) && (price_idx == i[3:0]))
                    level_qty = upd_qty;
                else
                    level_qty = bid_book[i];

                if (!bid_found && (level_qty != 16'd0)) begin
                    bid_found = 1'b1;
                    next_bid_idx = i[3:0];
                    next_bid_qty = level_qty;
                end
            end

            ask_found = 1'b0;
            next_ask_idx = 4'd0;
            next_ask_qty = 16'd0;
            for (i = 0; i < 16; i = i + 1) begin
                if ((upd_side == 1'b1) && (price_idx == i[3:0]))
                    level_qty = upd_qty;
                else
                    level_qty = ask_book[i];

                if (!ask_found && (level_qty != 16'd0)) begin
                    ask_found = 1'b1;
                    next_ask_idx = i[3:0];
                    next_ask_qty = level_qty;
                end
            end

            if (bid_found && ask_found) begin
                book_valid <= 1'b1;
                best_bid_idx <= next_bid_idx;
                best_bid_qty <= next_bid_qty;
                best_ask_idx <= next_ask_idx;
                best_ask_qty <= next_ask_qty;
                spread_ticks <= next_ask_idx - next_bid_idx;
            end else begin
                book_valid <= 1'b0;
                best_bid_idx <= 4'd0;
                best_bid_qty <= 16'd0;
                best_ask_idx <= 4'd0;
                best_ask_qty <= 16'd0;
                spread_ticks <= 4'd0;
            end
        end
    end
endmodule
