거북이처럼 천천히

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

RTL Design/Verilog 연습

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

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

1. LED의 밝기를 128단계로 나누어 컨트롤하기

  • 이번에는 LED를 켜진 상태를 유지하면서 LED의 밝기를 128단계로 분리 한뒤, 시간 지남에 따라 점차 밝아지도록 설계해보도록 하겠다.
 

Verilog RTL 설계(7월 31일 - 4, PWM - 4)

1. Pulse wave의 duty ratio를 128단계로 나누어 컨트롤 하는 모듈을 설계한 뒤, LED를 통한 출력 Pulse wave의 duty ratio를 128단계로 나누어 컨트롤 하는 모듈 >// Duty ratio 128 step controlmodule PWM_prescaling_128_Contro

jbhdeve.tistory.com

 

 

 

 

 

2. PWM Control 모듈 소스 코드

< Source, Edge detector >

// Edge detector
module edge_detector (
    input clk, reset_p,
    input 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
            flip_flop_current <= 0;
            flip_flop_old <= 0;
        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, 10kHz PWM의 Duty ratio를 128단계 컨트롤 모듈 >

// PWM Control module
module pwm_cntr(
    input clk, reset_p,
    input [6:0] duty,
    output pwm );
    
    // Declare parameter 
    parameter clk_freq = 100_000_000;
    parameter clk_pwm = 10_000;
    parameter duty_stage = 128;
    
    // Declare temp.
    parameter temp = clk_freq / clk_pwm / duty_stage;
    parameter temp_half = temp / 2;
    
    // 10kHz PWM을 만들기 위해 78분주화 한다.
    reg [6:0] 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_pulse;
    assign temp_pulse = (cnt_temp < temp_half) ? 0 : 1;
    
    // Get one cycle pulse of temp_pulse
    wire temp_pulse_nedge;
    edge_detector edge_detector_0 (.clk(clk), .reset_p(reset_p), .cp(temp_pulse), .n_edge(temp_pulse_nedge));
    
    // PWM의 Duty ratio를 128단계로 나누어 컨트롤하기 위해 128분주화
    reg [6:0] cnt_pwm;
    
    always @(posedge clk or posedge reset_p) begin
        if(reset_p) cnt_pwm = 0;
        else cnt_pwm = cnt_pwm + 1;
    end
    
    assign pwm = (cnt_pwm < duty) ? 1 : 0;
endmodule

 

 

 

< Source, Top module of LED Control by using PWM >

// Top module 
module top_module_led_pwm (
    input clk, reset_p,
    output pwm );
   
   // Control duty.
   reg [31:0] cnt_duty;
   always @(posedge clk or posedge reset_p) begin
        if(reset_p) cnt_duty = 0;
        else cnt_duty = cnt_duty + 1;
   end
   
   // Control PWM 
   pwm_cntr control_pwm (.clk(clk), .reset_p(reset_p), .duty(cnt_duty[31:25]), .pwm(pwm));
    
endmodule

 

 

 

 

 

3. 구현 영상

  • 32bit 크기를 갖는 Counter인 cnt_duty는 Clock Pulse를 기준으로 1씩 Counting 된다.
  • 이번 구현에서는 cnt_duty의 31번째 bit ~ 25번째 bit를 duty 값으로 주었기 때문에 LED의 밝기가 0단계에서 부터 시작해서 127단계까지 천천히 밝아졌다가 다시 0단계로 돌아오는 데까지 걸리는 시간은 2^32 * 10ns = 42.9496초 소요될 것으로 예상할 수 있다.
  • 실험 결과, LED의 밝기가 0단계에서 부터 시작해서 127단계까지 천천히 밝아졌다가 다시 0단계로 돌아오는 데까지 걸리는 시간은 42초 정도가 소요되었다.