반도체 Study/디지털 설계

Verilog- FPGA를 이용한 DC 모터 구동

잇(IT) 2024. 6. 11. 19:04
728x90

https://insoobaik.tistory.com/635

 

STM32 - PWM를 이용한 모터 제어 및 부저를 이용한 멜로디 생성

보호되어 있는 글입니다. 내용을 보시려면 비밀번호를 입력하세요.

insoobaik.tistory.com

PWM에 대한 내용은 위 글을 통해 참고하면된다.

STM32를 가지고 PWM을 통해 모터를 동작시킨 것과 동일하게 FPGA, Verilog를 통해 DC 모터 제어를 해 볼 것이다.


Motor Motor Status IN1 IN2 IN3 IN4
MOTOR_A Foward Rotation 1/PWM 0    
Reverse 0 1/PWM    
STOP 0 0    
Break 1 1    

 

DC 모터의 경우 ARR값에 대한 CCR값을 통해 속도를 조절 할 수 있다.

DC 모터의 속도는 ARR에 의해 정해진 타이머 주기의 평균 전압에 의해 정해지며, 평균 전압은 duty cycle 비율에 따라 달라지게 된다.


verilog code

module moter(
input [3:0] sw,
input clk,
input rst,
output reg pwm_out,
output wire nsleep
);

reg [25:0] counter;
reg [3:0] pwm_counter;
assign nsleep = 1;

always @(posedge clk or posedge  rst) begin
        if(rst) begin
                pwm_out <= 0;
                counter <= 0;
                pwm_counter <= 0;

         end else begin

        if(counter>=49999) begin
                counter <= 0;
                pwm_counter <= pwm_counter +1;

                if(pwm_counter>=15) begin
                        pwm_counter <= 0;
            end

            end else begin

        counter <= counter+1;
            end

        if(pwm_counter <sw)
                pwm_out <= 1;
        else

        pwm_out <= 0;

        end
end

ila_0 u12(.clk(clk), .probe0(pwm_out), .probe1(pwm_counter));
endmodule

위 코드는 4개의 스위치를 통해 총 duty cycle을 총 16단계로 나눈 코드다.

 

스위치를 통해 들어온 값을 비교하여 pwm_counter를 통해 sw 들어온 값보다 적은 숫자까지 1의 값을 전달하고, 나머지는 0의 값을 전달하도록 한다.

 

스위치와 pwm_counter 둘 전부 [3:0] 즉 0~15까지 카운트가 가능하며 만약 스위치의 값이 0100의 값이 들어오게 되면 pwm_counter는 3까지 1을 전달하고 나머지는 0을 전달하게 된다.

이는 duty cycle이 25%가 되는 것을 의미한다.

 

testbench

module tb_moter;
    reg [3:0] sw1;
    reg clk;
    reg rst;
    wire pwm_out1;
    wire pwm_out2;
    wire pwm_out3;
    wire pwm_out4;
    wire nsleep;
    reg [3:0] sw2;
    reg [3:0] sw3;
    reg [3:0] sw4;
    
    
    moter moter_dut1(.sw(sw1), .clk(clk), .rst(rst), .pwm_out(pwm_out1), .nsleep(nsleep));
    moter moter_dut2(.sw(sw2), .clk(clk), .rst(rst), .pwm_out(pwm_out2), .nsleep(nsleep));
    moter moter_dut3(.sw(sw3), .clk(clk), .rst(rst), .pwm_out(pwm_out3), .nsleep(nsleep));
    moter moter_dut4(.sw(sw4), .clk(clk), .rst(rst), .pwm_out(pwm_out4), .nsleep(nsleep));
    
    always #5 clk = ~clk;
    
    initial begin
        sw1 = 0;
        clk = 0;
        rst = 1;
        
        #10 
        rst = 0;
        sw1 = 4'b0001;
        
    end
    
    initial begin
        sw2 = 0;
        clk = 0;
        rst = 1;
        
        #10 
        rst = 0;
        sw2 = 4'b0010;
    end
    
    initial begin
        sw3 = 0;
        clk = 0;
        rst = 1;
        
        #10 
        rst = 0;
        sw3 = 4'b0100;
    end
    
    initial begin
        sw4 = 0;
        clk = 0;
        rst = 1;
        
        #10 
        rst = 0;
        sw4 = 4'b1000;
    end
endmodule

testbench를 통해 크게 4가지 경우에 신호를 시뮬레이션을 통해 확인해볼 것이다.

스위치 입력에 따른 4가지 상황에서 duty cycle이 다른 것을 확인할 수 있다. 1의 신호가 길수록 DC 모터의 속도는 빨라진다.

 

코드를 통해 생성된 논리 게이트들은 위와 같다.

위 논리 게이트를 통해 입력 신호를 받아 출력 신호로 DC 모터의 속도를 조절하게 된다.

 

이후 I/O Port를 FPGA 보드의 각 Port에 맞게 설정한 뒤 Bitstream을 통해 실행 파일을 FPGA 보드에 전달하면 아래와 같이 DC 모터가 제어되는 것을 확인할 수 있다.

 

수행 영상

 

 

 

 

728x90