거북이처럼 천천히

10kHz인 PWM 설계 (Duty ratio stage 128단계) - (4) 본문

RTL Design/Verilog 연습

10kHz인 PWM 설계 (Duty ratio stage 128단계) - (4)

유로 청년 2024. 8. 11. 21:19

1. Parameter를 통해 다용도로 사용 가능한 PWM 컨트롤 모듈 설계

 

  • PWM는 LED 뿐만 아니라 모터 제어에도 사용하며, LED는 10kHz, 모터는 100Hz 주파수를 갖는 PWM을 목표로 설계한다.
  • 이를 위해 parameter를 사용하여 다용도로 사용 가능한 PWM Control Module를 설계하도록 하겠다.
  • 아래 소스 코드에 대한 자세한 설명은 아래 게시글을 참고하길 바란다.
    https://jbhdeve.tistory.com/286
 

Verilog RTL 설계(8월 1일 - 1, PWM - 5)

1. Period = 100usec, Frequency = 10kHz인 Pulse wave를 128단계로 나누어 컨트롤하는 모듈 설계 Pulse wave를 128단계로 나누어 컨트롤하는 모듈 >// PWM Duty ratio 128module PWM_Duty_Ratio_cntr( input clk, reset_p, input [6:0] duty

jbhdeve.tistory.com

 

 

 

2. Parameter를 통해 다용도로 사용 가능한 PWM Control Module

< Source, edge detector >

// Edge detector 
module edge_detector (
    input clk, reset_p,
    input cp,
    output n_edge, p_edge );
    
    reg flip_flop_current, flip_flop_old;
    
    always @(posedge clk or posedge reset_p) begin
        if(reset_p) begin
            flip_flop_current <= 0;
            flip_flop_old <= flip_flop_current;
        end
        else begin
            flip_flop_current <= cp;
            flip_flop_old <= flip_flop_current;
        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

 

 

 

< Source, 다용도로 설계된 PWM Control Module >

  • Parameter 값으로 system clock, 만들고자 하는 PWM의 주파수, Duty ratio의 단계를 받게 된다.
// Control PWM
module pwm_cntr #(
    parameter sys_clk = 100_000_00,
    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
    );
    
    // 10kHz PWM 을 만들기 위한 분주화 작업
    // 10kHz PWM 을 만들기 위해 78분주화 
    integer cnt_temp;
    always @(posedge clk or posedge reset_p) begin
        if(reset_p) cnt_temp = 0;
        else begin
            if(cnt_temp >= temp - 1) 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를 control하기 위한 분주화 작업
    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

 

 

 

< Source, RGB LED control module >

// Top module of PWM
module top_module_pwm (
    input clk, reset_p,
    output [2:0] 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
    
    // Control PWM
    pwm_cntr #(.duty_step(97)) pwm_cntr_red (.clk(clk), .reset_p(reset_p), .duty(counter[31:26]), .pwm(pwm[0]));
    pwm_cntr #(.duty_step(93)) pwm_cntr_green (.clk(clk), .reset_p(reset_p), .duty(counter[29:24]), .pwm(pwm[1]));
    pwm_cntr #(.duty_step(89)) pwm_cntr_blue (.clk(clk), .reset_p(reset_p), .duty(counter[27:22]), .pwm(pwm[2]));
    
endmodule

 

 

 

 

 

3.  구현 영상

  • Red LED는 42.9496초를 주기로 밝았다 꺼졌다를 반복하게 된다.
  • Green LED는 10.7374초 주기로 밝았다 꺼졌다를 반복하게 된다.
  • Blue LED는 2.6843초 주기로 밝았다 꺼졌다를 반복하게 된다.
  • RGB 색상이 서로 다른 주기를 갖고, 밝기가 변화하기 때문에 이로 인해 다양한 색상이 LED로 표현이 가능하다.