module user_module_019235602376235615(
  input [7:0] io_in, 
  output [7:0] io_out
);

    // 6bit angles and 6 bit outputs
    // y0 = 0, x0 = 0.60728

    /*
    How to convert angles to binary angles:
    angle = 180/62*bin_angle

    Convert sine and cosine values to binary:
    value = 2/62*bin_value
    */

    wire clk = io_in[0];
    wire reset = io_in[1];
    wire [5:0] z0 = io_in[7:2]; // input angle supports from -90 to +90 degrees

    // ROM
    reg [5:0]x0;
    reg [5:0]angle[5:0];
    always @(posedge clk) begin
        x0 <= 6'd19; // x0 = 0.60728
        angle[0] <= 6'd16; // angle 0 = 45
        angle[1] <= 6'd9; // angle 1 = 26.565
        angle[2] <= 6'd5; // angle 2 = 14.036
        angle[3] <= 6'd2; // angle 3 = 7.125
        angle[4] <= 6'd1; // angle 4 = 3.576
        angle[5] <= 6'd1; // angle 5 = 1.7899
    end

    // Registers 
    reg [5:0] reg_x, reg_y, reg_x_next, reg_y_next, reg_z, reg_z_next;
    reg en;
    always @(posedge clk) begin
        if (reset) begin
            reg_x <= x0;
            reg_y <= 0;
            reg_z <= z0;
        end else if (en) begin
            reg_x <= reg_x_next;
            reg_y <= reg_y_next;
            reg_z <= reg_z_next;
        end
    end

    // ALU
    wire d;
    assign d = reg_z[5];
    always @(*) begin

        if (d) begin // if d then x is add and y is sub and z is add
                    reg_x_next <= reg_x + ($signed(reg_y) >>> i);
                    reg_y_next <= reg_y - ($signed(reg_x) >>> i);
                    reg_z_next <= reg_z + angle[i];
                end else begin // if !d then x is sub and y is add and z is sub
                    reg_x_next <= reg_x - ($signed(reg_y) >>> i);
                    reg_y_next <= reg_y + ($signed(reg_x) >>> i);
                    reg_z_next <= reg_z - angle[i];
        end


    end


    // Control unit
    reg [1:0] state;
    `define RESET 2'b0
    `define CALC 2'd1
    `define DONE 2'd2
    reg [2:0]i;
    reg done;
    always @(posedge clk) begin
        case (state)
            `RESET: begin
                done <= 0;
                i <= 0;
                
                if (!reset) begin
                    state <= `CALC;
                    en <= 1;
                end
                    
            end
            `CALC: begin
                if ( i < 5) begin
                    i <= i+1;
                    if (i == 4)
                        en <= 0;
                end
                    
                else begin
                    state <= `DONE;
                    
                end
            end
            `DONE: begin
                done <= 1;
                if (reset) 
                    state <= `RESET;
            end
            default: begin
                state <= 0;
            end

        endcase
    end

    // Ooutput controler
    assign io_out[7] = done;
    wire x_yb;
    assign x_yb = clk;
    assign io_out[6] = x_yb;
    wire [5:0] data_out;
    assign io_out[5:0] = data_out;

    assign data_out = (done) ? (clk) ? reg_x : reg_y : 0;

 
endmodule