module timestamp_delta_encoder (
    input  wire        clk,
    input  wire        rst,
    input  wire        in_valid,
    input  wire [31:0] in_timestamp,
    output reg         out_valid,
    output reg  [1:0]  out_tag,
    output reg  [31:0] out_value
);
    reg        has_prev;
    reg [31:0] prev_timestamp;
    reg        pending_valid;
    reg [1:0]  pending_tag;
    reg [31:0] pending_value;

    reg        next_out_valid;
    reg [1:0]  next_out_tag;
    reg [31:0] next_out_value;
    reg        next_has_prev;
    reg [31:0] next_prev_timestamp;
    reg [31:0] delta;

    always @(*) begin
        next_out_valid = 1'b0;
        next_out_tag = 2'b00;
        next_out_value = 32'b0;

        next_has_prev = has_prev;
        next_prev_timestamp = prev_timestamp;
        delta = in_timestamp - prev_timestamp;

        if (in_valid) begin
            next_out_valid = 1'b1;

            if (!has_prev) begin
                next_out_tag = 2'b10;
                next_out_value = in_timestamp;
            end else if (delta <= 32'd255) begin
                next_out_tag = 2'b00;
                next_out_value = {24'd0, delta[7:0]};
            end else if (delta <= 32'd65535) begin
                next_out_tag = 2'b01;
                next_out_value = {16'd0, delta[15:0]};
            end else begin
                next_out_tag = 2'b10;
                next_out_value = delta;
            end

            next_has_prev = 1'b1;
            next_prev_timestamp = in_timestamp;
        end
    end

    always @(posedge clk) begin
        if (rst) begin
            has_prev <= 1'b0;
            prev_timestamp <= 32'b0;
            pending_valid <= 1'b0;
            pending_tag <= 2'b00;
            pending_value <= 32'b0;
            out_valid <= 1'b0;
            out_tag <= 2'b00;
            out_value <= 32'b0;
        end else begin
            out_valid <= pending_valid;
            out_tag <= pending_tag;
            out_value <= pending_value;

            has_prev <= next_has_prev;
            prev_timestamp <= next_prev_timestamp;
            pending_valid <= next_out_valid;
            pending_tag <= next_out_tag;
            pending_value <= next_out_value;
        end
    end
endmodule
