// pipeline_reg.v - Single pipeline stage with valid/ready handshake
//
// valid_i && ready_o -> register data -> valid_o next cycle.
// ready_o = !valid_o || ready_i.
//
// Parameters:
//   DW = data width (default 12)
//
// Interface:
//   clk, rst_n    - clock, active-low reset
//   data_i, valid_i, ready_o - input side
//   data_o, valid_o, ready_i - output side

module pipeline_reg #(parameter DW = 12) (
    input              clk,
    input              rst_n,
    input  [DW-1:0]    data_i,
    input              valid_i,
    output             ready_o,
    output [DW-1:0]    data_o,
    output             valid_o,
    input              ready_i
);

    reg               valid_r;
    reg [DW-1:0]      data_r;

    // ready_o: accept new data when output slot is free
    assign ready_o = !valid_r || ready_i;

    // Drive outputs from internal register
    assign valid_o = valid_r;
    assign data_o  = data_r;

    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            valid_r <= 1'b0;
            data_r  <= {DW{1'b0}};
        end else begin
            if (valid_r && ready_i) begin
                // Output consumed, clear valid
                valid_r <= 1'b0;
            end

            if (valid_i && ready_o) begin
                // Capture new data
                data_r  <= data_i;
                valid_r <= 1'b1;
            end
        end
    end

endmodule
