//====================================================================
// texture_mapper.v - 纹理映射器
// 第13课：UV坐标计算与纹理寻址
//====================================================================
module texture_mapper #(
    parameter COORD_WIDTH = 16,
    parameter COLOR_WIDTH = 24,
    parameter TEX_ADDR_WIDTH = 14,
    parameter TEX_SIZE = 128,
    parameter FRAC_BITS = 12
)(
    input  wire                          clk, rst_n,
    input  wire                          frag_valid,
    input  wire [COORD_WIDTH-1:0]        frag_u, frag_v,
    input  wire [1:0]                    wrap_mode,   // 0=REPEAT,1=CLAMP,2=MIRROR
    output reg                           frag_ready,
    output reg  [TEX_ADDR_WIDTH-1:0]     tex_addr,
    output reg                           tex_req,
    input  wire [COLOR_WIDTH-1:0]        tex_data,
    input  wire                          tex_valid,
    output reg                           color_valid,
    output reg  [COLOR_WIDTH-1:0]        frag_color
);
/* verilator lint_off WIDTHEXPAND */
/* verilator lint_off WIDTHTRUNC */
/* verilator lint_off CASEOVERLAP */
/* verilator lint_off CMPCONST */
/* verilator lint_off UNSIGNED */
/* verilator lint_off WIDTHCONCAT */

    reg [COORD_WIDTH-1:0] u_wrapped, v_wrapped;
    reg [TEX_ADDR_WIDTH-1:0] u_idx, v_idx;
    localparam S_IDLE=3'd0, S_WRAP=3'd1, S_ADDR=3'd2, S_FETCH=3'd3, S_OUTPUT=3'd4;
    reg [2:0] state;
    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin state<=S_IDLE; frag_ready<=1; color_valid<=0; end
        else begin
            color_valid <= 0; tex_req <= 0;
            case (state)
                S_IDLE: begin
                    frag_ready <= 1;
                    if (frag_valid) begin frag_ready <= 0; state <= S_WRAP; end
                end
                S_WRAP: begin
                    case (wrap_mode)
                        2'd0: begin // REPEAT
                            u_wrapped <= frag_u % (TEX_SIZE * 16'd16);
                            v_wrapped <= frag_v % (TEX_SIZE * 16'd16);
                        end
                        2'd1: begin // CLAMP
                            u_wrapped <= (frag_u > TEX_SIZE*16-1) ? (TEX_SIZE*16-1) : ((frag_u < 0) ? 0 : frag_u);
                            v_wrapped <= (frag_v > TEX_SIZE*16-1) ? (TEX_SIZE*16-1) : ((frag_v < 0) ? 0 : frag_v);
                        end
                        default: begin u_wrapped <= frag_u; v_wrapped <= frag_v; end
                    endcase
                    state <= S_ADDR;
                end
                S_ADDR: begin
                    u_idx <= u_wrapped[COORD_WIDTH-1:4]; // 除以16取整数部分
                    v_idx <= v_wrapped[COORD_WIDTH-1:4];
                    tex_addr <= v_idx * TEX_SIZE + u_idx;
                    tex_req <= 1;
                    state <= S_FETCH;
                end
                S_FETCH: begin
                    if (tex_valid) begin
                        frag_color <= tex_data;
                        state <= S_OUTPUT;
                    end
                end
                S_OUTPUT: begin
                    color_valid <= 1; state <= S_IDLE;
                end
                default: state <= S_IDLE;
            endcase
        end
    end
endmodule