module stepper_cntr (
    input clk, reset_p,
    input [4:0] step_mode,
    input step_start,              // 모터 구동 시작 신호, high일 때만 구동
    input [11:0] step_angle,
    input step_dir,                // 모터의 회전 방향 1'b1 = 시계 방향, 1'b0 = 반시계 방향
    output reg [3:0] step_out      // 모터 드라이버로 출력되는 4개의 신호 (IN1, IN2, IN3, IN4)
    );

    localparam IDLE     = 5'b00001;
    localparam ONEWAY   = 5'b00010;
    localparam ROUND    = 5'b00100;
    localparam ONEWAY_M = 5'b01000;
    localparam ONEROUND = 5'b10000;

    reg [3:0] half_step [7:0];      //8개의 하프 스텝 시퀀스를 배열로 정의
    initial begin
        half_step[0] = 4'b1000;
        half_step[1] = 4'b1100;
        half_step[2] = 4'b0100;
        half_step[3] = 4'b0110;
        half_step[4] = 4'b0010;
        half_step[5] = 4'b0011;
        half_step[6] = 4'b0001;
        half_step[7] = 4'b1001;
    end

    reg [23:0] cnt_sysclk = 1;      //스텝 지연 시간을 제어하기 위한 카운터
    reg [2:0] step_index = 0;       //배열의 인덱스를 나타냄  0에서 7까지 반복하며 모터를 회전
    reg [15:0] step_cnt_r = 0;
    reg [15:0] step_cnt_o = 0;
    reg round_dir = 1;
    always @(posedge clk or posedge reset_p) begin
        if (reset_p)begin
            cnt_sysclk <= 1;
            step_index <= 0;
            step_out <= 4'b0000;
            step_cnt_r <= 0;
            step_cnt_o <= 0;
            round_dir <= 1;
        end
        else begin
            if (step_start) begin
                if (cnt_sysclk >= 200_000) begin    // 실제 200_000
                    cnt_sysclk <= 1;
                    case (step_mode)
                        IDLE     : begin
                            step_index <= 0;
                            step_out <= 4'b0000;
                            round_dir <= 1;
                        end
                        ONEWAY   : begin
                            if (step_dir) begin // 시계 방향
                                if (step_index >= 7) step_index <= 0;
                                else step_index <= step_index + 1;
                            end
                            else begin // 반시계 방향
                                if (step_index <= 0) step_index <= 7;
                                else step_index <= step_index - 1;
                            end
                        end
                        ROUND    : begin
                            if (step_cnt_r >= (step_angle * 11)) begin
                                step_cnt_r <= 0;
                                round_dir <= ~round_dir;
                            end
                            else begin
                                step_cnt_r <= step_cnt_r + 1;
                                if (round_dir) step_index <= step_cnt_r % 8;
                                else step_index <= 7 - (step_cnt_r % 8);
                            end
                        end
                        ONEWAY_M : begin
                            if (step_dir) begin
                                if (step_cnt_o <= (step_angle * 11)) step_cnt_o <= step_cnt_o + 1; 
                                step_index <= step_cnt_o % 8;
                            end
                            else begin
                                if (step_cnt_o > 0) step_cnt_o <= step_cnt_o - 1; 
                                step_index <= 7 - (step_cnt_o % 8);
                            end
                        end
                        ONEROUND : begin
                            if (step_dir) begin
                                if (step_cnt_o <= (step_angle * 11)) begin
                                    step_cnt_o <= step_cnt_o + 1; 
                                end
                            end
                            else begin
                                if (step_cnt_o > 0) begin
                                    step_cnt_o <= step_cnt_o - 1; 
                                end
                            end
                            step_index <= step_cnt_o % 8;
                        end
                        default  : begin
                            step_index <= 0;
                            step_out <= 4'b0000;
                            round_dir <= 1;
                        end
                    endcase
                    step_out <= half_step[step_index];
                end
                else cnt_sysclk <= cnt_sysclk + 1;
            end
            else begin // 정지 동작 
                cnt_sysclk <= 0;
                step_index <= 0;
                step_out <= 4'b0000;
            end
        end
    end
endmodule