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