Notice
Recent Posts
Recent Comments
Link
관리 메뉴

거북이처럼 천천히

Verilog RTL 설계(8월 1일 - 2, PWM을 통한 Motor 제어 - 1) 본문

RTL Design/Verilog RTL 설계

Verilog RTL 설계(8월 1일 - 2, PWM을 통한 Motor 제어 - 1)

유로 청년 2024. 8. 12. 09:13

1. PWM을 통한 Motor 제어

  • 이전까지는 PWM을 통해 LED diode의 밝기를 제어를 해보았으며, LED diode 외에도 PWM을 통해 Motor 제어가 가능하다.
  • 따라서 이번에는 PWM을 통해 Motor의 속도를 제어해보도록 하겠다.
  • LED Diode인 경우, LED가 깜박임 없이 연속적으로 켜있는 상태를 유지하기 위해서는 10kHz 주파수를 갖는 PWM을 설계할 필요가 있었으며, Motor 경우에는 Motor가 연속적으로 회전하는 상태를 유지하기 위해서는 100Hz 주파수를 갖는 PWM이 필요하다.

 

 

 

 

2. Motor 구동에 필요한 5V 전압을 인가하기 위해 아래와 같이 회로를 구성하였다.

  • Basys3의 Vcc 전압은 3.3V을 공급해주지만, Motor를 구동하기 위해서는 5V의 전압이 필요하다.
  • 따라서 Motor를 구동하기 위해 필요한 5V 전압을 얻기 위해 ATmega 128A의 Vcc를 사용하기로 했다.
  • ATmega128A를 통해 Motor 구동에 필요한 5V 전압을 얻되, Motor 제어는 basys3의 pin을 이용하게 된다.

 

 

 

 

 

3. Motor  제어에 필요한 PWM Control Module 설계

  • Parameter를 통해 다용도로 사용가능한 PWM Control Module를 설계하여 사용하도록 하겠다.
  • Motor를 연속적으로 동작시키기 위해서는 100Hz PWM이 필요하며, PWM의 Duty ratio을 4단계로 나누어 Motor를 동작시키도록 하겠다.

 

< Source, edge detecor >

// Edge detector 
module edge_detector (
    input clk, reset_p,
    output cp,
    output p_edge, n_edge );
    
    reg flip_flop_current, flip_flop_old;
    
    always @(posedge clk or posedge reset_p) begin
        if(reset_p) begin
              if(reset_p) begin
                    flip_flop_current <= 0;
                    flip_flop_old <= 0;
              end
              else begin
                    flip_flop_current <= cp;
                    flip_flop_old <= flip_flop_current;
              end
        end
    end
    
    assign p_edge = ({flip_flop_current, flip_flop_old} == 2'b10) ? 1 : 0;
    assign n_edge = ({flip_flop_current, flip_flop_old} == 2'b01) ? 1 : 0;
    
endmodule
  • 두 개의 D Flip-Flop을 이용하여 입력 펄스의 Edge를 감지하는 모듈이다.

 

 

< Source, PWM Control Module >

// PWM Control module
module pwm_cntr #(
    parameter sys_clk = 100_000_000,
    parameter pwm_freq = 10_000,
    parameter duty_step = 128,
    
    parameter temp = sys_clk / pwm_freq / duty_step,
    parameter temp_half = temp / 2) (
    input clk, reset_p,
    input [31:0] duty,
    output pwm );
    
    // pwm frequency를 만들기 위한 temp 분주화 작업
    integer cnt_temp;
    
    always @(posedge clk or posedge reset_p) begin
        if(reset_p) cnt_temp = 0;
        else begin
            if(cnt_temp >= temp_half) cnt_temp = 0;
            else cnt_temp = cnt_temp + 1; 
        end
    end
    
    wire temp_pwm;
    assign temp_pwm = (cnt_temp < temp_half) ? 0 : 1;
    
    // get one cycle pulse of temp_pwm
    wire temp_pwm_nedge;
    edge_detector edge_detector_0 (.clk(clk), .reset_p(reset_p), .cp(temp_pwm), .n_edge(temp_pwm_nedge));
    
    
    // pwm의 duty ratio를 duty step단계로 나누어 컨트롤 하기 위해서 duty step 분주화 작업 
    integer cnt_duty;
    
    always @(posedge clk or posedge reset_p) begin
        if(reset_p) cnt_duty = 0;
        else if(temp_pwm_nedge) begin
            if(cnt_duty >= duty_step-1) cnt_duty = 0;
            else cnt_duty = cnt_duty + 1;
        end
    end
    
    assign pwm = (cnt_duty < duty) ? 1 : 0;
endmodule
  • System Clock의 주파수와 PWM의 주파수, Duty ratio의 단계를 Parameter로 설정하여 용도 및 환경에 따라 해당 값을 변화시킬 수 있도록 설계하였으며, 이를 통해 범용성을 확대시킬 수 있었다.
  • 첫 번째 분주화 작업은 원하는 PWM의 주파수를 만들고자 시행하는 분주화 작업이며, 해당 과정에서는 Clock Pulse를 temp 분주하여 sys_clk / temp Hz 주파수를 갖는 새로운 펄스파가 생성된다.
  • 두 번째 분주화 작업은 PWM의 duty ratio을 원하는 단계로 나누어 컨트롤 하기 위한 분주화 작업이며, 첫 번째 분주화 작업에서 얻은 펄스파를 duty_step 분주하여 sys_clk / temp / duty_step == pwm_freq Hz 주파수를 갖는 새로운 펄스파형이 생성된다.

 

 

< Source, Top module of Motor Control >

// Top module of PWM Control
module top_module_pwm (
    input clk, reset_p,
    output pwm );
    
    // Clock Pulse Counter.
    reg [31:0] counter;
    always @(posedge clk or posedge reset_p) begin
        if(reset_p) counter = 0;
        else counter = counter + 1;
    end
    
    // PWM Control module
    pwm_cntr #(.pwm_freq(100), .duty_step(4)) pwm_cntr_motor (.clk(clk), .reset_p(reset_p), .duty(counter[31:30]), .pwm(pwm));
    
endmodule
  • Motor을 제어하기 위해 PWM의 주파수를 100Hz를 갖도록 인스턴스를 생성하였으며, Motor을 4단계로 구동시키기 위해 duty ratio을 4단계로 구분하였다.
  • Motor는 0단계 ~ 3단계로 나누어 구동하며, 0단계에서 3단계까지 갔다가 다시 0단계로 돌아오는 한 싸이클 동안 걸리는 시간은 42.9496초가 소요된다.

 

 

 

4. 구현 영상