//====================================================================
// depth_buffer.v - 深度缓冲器
// 第12课：Z缓冲深度测试与更新
//====================================================================
module depth_buffer #(
    parameter ADDR_WIDTH = 20,
    parameter DEPTH_WIDTH = 16,
    parameter COLOR_WIDTH = 24,
    parameter FRAC_BITS  = 12
)(
    input  wire                          clk, rst_n,
    input  wire                          frag_valid,
    input  wire [ADDR_WIDTH-1:0]         frag_addr,
    input  wire signed [DEPTH_WIDTH-1:0] frag_depth,
    input  wire [COLOR_WIDTH-1:0]        frag_color,
    output reg                           frag_ready,
    output reg                           write_valid,
    output reg  [ADDR_WIDTH-1:0]         write_addr,
    output reg  [COLOR_WIDTH-1:0]        write_color,
    input  wire                          write_ready,
    // 深度测试模式
    input  wire [2:0]                    depth_func   // 0=NEVER,1=LESS,2=EQUAL,3=LEQUAL,4=GREATER,5=NOTEQUAL,6=GEQUAL,7=ALWAYS
);
/* verilator lint_off WIDTHEXPAND */
/* verilator lint_off WIDTHTRUNC */
/* verilator lint_off CASEOVERLAP */
/* verilator lint_off CMPCONST */
/* verilator lint_off UNSIGNED */
/* verilator lint_off WIDTHCONCAT */

    // 深度缓冲存储(使用寄存器阵列模拟，实际用BRAM)
    reg signed [DEPTH_WIDTH-1:0] zbuf [0:255]; // 简化：256项
    reg signed [DEPTH_WIDTH-1:0] stored_depth;
    reg depth_test_pass;
    always @(*) begin
        case (depth_func)
            3'd0: depth_test_pass = 1'b0;                             // NEVER
            3'd1: depth_test_pass = (frag_depth < stored_depth);      // LESS
            3'd2: depth_test_pass = (frag_depth == stored_depth);     // EQUAL
            3'd3: depth_test_pass = (frag_depth <= stored_depth);     // LEQUAL
            3'd4: depth_test_pass = (frag_depth > stored_depth);      // GREATER
            3'd5: depth_test_pass = (frag_depth != stored_depth);     // NOTEQUAL
            3'd6: depth_test_pass = (frag_depth >= stored_depth);     // GEQUAL
            3'd7: depth_test_pass = 1'b1;                             // ALWAYS
            default: depth_test_pass = 1'b1;
        endcase
    end
    localparam S_READ=2'd0, S_TEST=2'd1, S_WRITE=2'd2;
    reg [1:0] state;
    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin state<=S_READ; frag_ready<=1; write_valid<=0; end
        else begin
            write_valid <= 0;
            case (state)
                S_READ: begin
                    frag_ready <= 1;
                    if (frag_valid) begin
                        frag_ready <= 0;
                        stored_depth <= zbuf[frag_addr[7:0]]; // 读取当前深度
                        state <= S_TEST;
                    end
                end
                S_TEST: begin
                    if (depth_test_pass) begin
                        zbuf[frag_addr[7:0]] <= frag_depth; // 更新深度
                        write_addr <= frag_addr;
                        write_color <= frag_color;
                        state <= S_WRITE;
                    end else begin
                        state <= S_READ;
                    end
                end
                S_WRITE: begin
                    write_valid <= 1;
                    state <= S_READ;
                end
                default: state <= S_READ;
            endcase
        end
    end
endmodule