Harman 세미콘 아카데미/Verilog

2024.7.9 [Verilog]16 - PWM으로 모터 제어하기

U_Pong 2024. 7. 9. 21:27

2024.7.9 수업날


< ez motor 제어하기 >

pwm_128step_100 소스코드
//////////////////////////pwm 제어하기, 128분주기(100MHz로 나눈)
// 모터는 100Hz
module pwm_128step_100(
      input clk, reset_p,
      input [6:0]duty,             
      output reg pwm );     
      
      parameter sys_clk_freq = 100_000_000;           //시스템 클록,  100MHz
      parameter pwm_freq = 100;                          //pwm 출력, 100Hz
      parameter duty_step = 128;                                // 듀티 싸이클 128로 설정
      parameter temp = sys_clk_freq / pwm_freq / duty_step;         //  타이머 카운트 주기, parameter 상수는 그냥 수이기 때문에 회로 만들때는 나누기 회로가 만들어지지 않음
      parameter temp_half = temp / 2;
      
      integer cnt;                        // 카운터 변수 선언
      reg pwm_freqX128;          // 128배 주파수를 가지는 PWM 신호를 저장하는 레지스터 선언
      always @ (posedge clk or posedge reset_p) begin
            if(reset_p) begin
                  pwm_freqX128 = 0;
                  cnt = 0;
            end
            else begin
                  if(cnt >= (temp - 1))cnt = 0;               //78분주-->10,000/128
                  else cnt = cnt + 1;
                  
                  //if(cnt < (pwmXduty_steps / 2)) pwm_freqX128 = 0;                  // 마찬가지로 상수이기 때문에 상관 없음
                  if(cnt < temp_half) pwm_freqX128 = 0;
                  else pwm_freqX128 = 1;
            end
      end
      
      wire pwm_freqX128_nedge;
       edge_detector_n ed(
                  .clk(clk), .reset_p(reset_p), 
                  .cp(pwm_freqX128), .n_edge(pwm_freqX128_nedge));
      
      reg [6:0] cnt_duty;                        // 2^7=128분주기           
      always @ (posedge clk or posedge reset_p)begin
            if(reset_p) begin
                  cnt_duty = 0;
                  pwm = 0;
            end
            else if(pwm_freqX128_nedge)begin
                  cnt_duty = cnt_duty + 1;                        // 128에 한번 씩 0이됨
                  if(cnt_duty < duty)pwm = 1;
                  else pwm = 0;
            end
      end
      
endmodule

 

dc_motor_pwm_top 소스코드
//////////////////////////////////////////////// 2024.7.9
//////////////// 모터 pwm 제어
module dc_motor_pwm_top(
      input clk, reset_p,
      output motor_pwm,
      output [3:0] com,
      output [7:0] seg_7);
      
      reg [31:0] clk_div;
      always @(posedge clk) clk_div = clk_div + 1;
      
      pwm_128step_100 pwm_motor(
            .clk(clk), .reset_p(reset_p),
            .duty(clk_div[31:25]),
            .pwm(motor_pwm));
      
      fnd_4digit_cntr FND_distance(.clk(clk), .value(motor_pwm), .com(com), .seg_7(seg_7));
            
endmodule

 

pwm_128step_100 결과

 

 

dc_motor_pwm_fnd_top 소스코드
//////////////// 모터 pwm 제어 fnd 출력
module dc_motor_pwm_fnd_top(
      input clk, reset_p,
      output motor_pwm,
      output [3:0] com,
      output [7:0] seg_7);
      
      reg [32:0] clk_div;
      always @(posedge clk) clk_div = clk_div + 1;
      
      pwm_128step_100 pwm_motor(
            .clk(clk), .reset_p(reset_p),
            .duty(clk_div[32:26]),
            .pwm(motor_pwm));
      
      wire [15:0] duty_bcd;
      bin_to_dec btd_duty(.bin({5'b0, clk_div[32:26]}), .bcd(duty_bcd));
      
      fnd_4digit_cntr FND_duty(.clk(clk), .value(duty_bcd), .com(com), .seg_7(seg_7));
            
endmodule

 

dc_motor_pwm_fnd_top 결과1

 

dc_motor_pwm_fnd_top 결과2

PWM으로 모터 제어하기 끝!