//====================================================================
// rotating_cube.v - 3D旋转立方体
// 第26课：立方体旋转与透视渲染集成
//====================================================================
module rotating_cube #(
    parameter COORD_WIDTH = 16,
    parameter COLOR_WIDTH = 24,
    parameter FRAC_BITS  = 12,
    parameter FB_WIDTH   = 640,
    parameter FB_HEIGHT  = 480
)(
    input  wire                          clk, rst_n,
    input  wire                          frame_start,
    input  wire signed [COORD_WIDTH-1:0] rot_x, rot_y, rot_z,
    output reg                           frame_done,
    output reg                           fb_wen,
    output reg  [COORD_WIDTH-1:0]        fb_x, fb_y,
    output reg  [COLOR_WIDTH-1:0]        fb_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 */

    function signed [COORD_WIDTH-1:0] qmul;
        input signed [COORD_WIDTH-1:0] a, b;
        reg signed [2*COORD_WIDTH-1:0] prod;
        begin prod = a * b; qmul = prod[2*COORD_WIDTH-FRAC_BITS-1:COORD_WIDTH-FRAC_BITS]; end
    endfunction
    // 立方体8个顶点(单位立方体±1)
    reg signed [COORD_WIDTH-1:0] cube_x [0:7];
    reg signed [COORD_WIDTH-1:0] cube_y [0:7];
    reg signed [COORD_WIDTH-1:0] cube_z [0:7];
    reg [COLOR_WIDTH-1:0] cube_color [0:5]; // 6面颜色
    // 变换后顶点
    reg signed [COORD_WIDTH-1:0] trans_x [0:7];
    reg signed [COORD_WIDTH-1:0] trans_y [0:7];
    reg signed [COORD_WIDTH-1:0] trans_z [0:7];
    // 12个三角形的索引
    reg [3:0] tri_indices [0:35]; // 12×3
    reg [2:0] vert_idx;
    reg [3:0] tri_idx;
    reg [5:0] idx_ptr;
    localparam S_INIT=3'd0, S_TRANSFORM=3'd1, S_PROJECT=3'd2, S_RASTER=3'd3, S_DONE=3'd4;
    reg [2:0] state;
    integer i;
    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            state <= S_INIT; frame_done <= 0; fb_wen <= 0;
        end else begin
            fb_wen <= 0; frame_done <= 0;
            case (state)
                S_INIT: begin
                    if (frame_start) begin
                        // 初始化单位立方体顶点
                        cube_x[0] <= -16'h1000; cube_y[0] <= -16'h1000; cube_z[0] <= -16'h1000;
                        cube_x[1] <=  16'h1000; cube_y[1] <= -16'h1000; cube_z[1] <= -16'h1000;
                        cube_x[2] <=  16'h1000; cube_y[2] <=  16'h1000; cube_z[2] <= -16'h1000;
                        cube_x[3] <= -16'h1000; cube_y[3] <=  16'h1000; cube_z[3] <= -16'h1000;
                        cube_x[4] <= -16'h1000; cube_y[4] <= -16'h1000; cube_z[4] <=  16'h1000;
                        cube_x[5] <=  16'h1000; cube_y[5] <= -16'h1000; cube_z[5] <=  16'h1000;
                        cube_x[6] <=  16'h1000; cube_y[6] <=  16'h1000; cube_z[6] <=  16'h1000;
                        cube_x[7] <= -16'h1000; cube_y[7] <=  16'h1000; cube_z[7] <=  16'h1000;
                        cube_color[0] <= 24'hff0000; cube_color[1] <= 24'h00ff00;
                        cube_color[2] <= 24'h0000ff; cube_color[3] <= 24'hffff00;
                        cube_color[4] <= 24'hff00ff; cube_color[5] <= 24'h00ffff;
                        vert_idx <= 0; state <= S_TRANSFORM;
                    end
                end
                S_TRANSFORM: begin
                    // 简化：绕Y轴旋转 + 平移到z=-5
                    trans_x[vert_idx] <= qmul(cube_x[vert_idx], 16'h1000) + qmul(cube_z[vert_idx], rot_y);
                    trans_y[vert_idx] <= cube_y[vert_idx];
                    trans_z[vert_idx] <= -qmul(cube_x[vert_idx], rot_y) + qmul(cube_z[vert_idx], 16'h1000) - 16'h5000;
                    if (vert_idx < 7) vert_idx <= vert_idx + 1;
                    else begin vert_idx <= 0; state <= S_PROJECT; end
                end
                S_PROJECT: begin
                    // 简化透视投影: sx = x*fov/z + cx, sy = y*fov/z + cy
                    trans_x[vert_idx] <= qmul(trans_x[vert_idx], 16'h4000) / trans_z[vert_idx] + 16'h5000;
                    trans_y[vert_idx] <= qmul(trans_y[vert_idx], 16'h4000) / trans_z[vert_idx] + 16'h3C00;
                    if (vert_idx < 7) vert_idx <= vert_idx + 1;
                    else begin state <= S_RASTER; tri_idx <= 0; end
                end
                S_RASTER: begin
                    // 简化：直接输出顶点(实际需要光栅化)
                    fb_wen <= 1;
                    fb_x <= trans_x[vert_idx];
                    fb_y <= trans_y[vert_idx];
                    fb_color <= cube_color[tri_idx[2:0]];
                    if (tri_idx < 11) tri_idx <= tri_idx + 1;
                    else state <= S_DONE;
                end
                S_DONE: begin frame_done <= 1; state <= S_INIT; end
                default: state <= S_INIT;
            endcase
        end
    end
endmodule