Notice
Recent Posts
Recent Comments
Link
관리 메뉴

거북이처럼 천천히

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

RTL Design/Verilog 연습

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

유로 청년 2024. 8. 11. 14:03

1. Duty ratio를 128단계로 나눈 10kHz PWM 설계

  • LED의 밝기를 128단계로 나누어 컨트롤하기 위해 Duty ratio를 128단계로 나누어 컨트롤 할 수 있는 PWM 설계한다.
  • Duty ratio를 128단계 나누어 컨트롤하기 위해서 128 분주화, 78.125 분주화, 총 2번의 분주를 할 것이다.
  • Duty ratio를 128단계로 나눈 10kHz PWM에 대한 자세한 설명은 아래 게시글 참고하길 바란다.
    https://jbhdeve.tistory.com/284
 

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

1.  LED의 밝기를 128단계로 나누어 컨트롤하기.이번에는 LED의 밝기를 128단계로 나누어 컨트롤 할 수 있도록 모듈 설계해보도록 하겠다.이를 통해 "왜 2단계로 나누어 Prescaling을 진행하는가?"를 정

jbhdeve.tistory.com

 

 

 

2. 소스 코드 

< 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 <= 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, Duty ratio를 128단계 나눈 10kHz PWM >

module PWM_cntr(
    input clk, reset_p,
    input [6:0] stage,
    output pwm );
    
    // Declare parameter
    parameter sys_clk = 100_000_000; // Clock Pulse의 주파수
    parameter duty_stage = 128;      // Duty ratio 128 stage
    parameter pwm_freq = 10_000;     // PWM Frequency = 10kHz
    
    // 10kHz PWM을 만들기 위해서는 몇 분주화를 해야 하는가?
    parameter temp = sys_clk / duty_stage / pwm_freq;
    parameter temp_half = temp / 2;
    
    // 10kHz 주파수를 갖는 PWM를 만들기 위한 78.125 분주화.
    reg [6:0] cnt_sysclk;
    always @(posedge clk or posedge reset_p) begin
        if(reset_p) cnt_sysclk = 0;
        else begin
            if(cnt_sysclk >= temp - 1) cnt_sysclk = 0;
            else cnt_sysclk = cnt_sysclk + 1;
        end
    end
    
    wire temp_freq;
    assign temp_freq = (cnt_sysclk < temp_half) ? 1 : 0;
    
    // Get one cycle pulse of temp_freq.
    wire temp_freq_nedge;
    edge_detector edge_detector_0 (.clk(clk), .reset_p(reset_p), .cp(temp_freq), .n_edge(temp_freq_nedge));
    
    // LED의 밝기를 128단계로 나누어 컨트롤 하기 위해서
    // temp_freq_nedge가 활성화되면 128분주화한다.
    reg [6:0] cnt_pwm;
    
    always @(posedge clk or posedge reset_p) begin
        if(reset_p) cnt_pwm = 0;
        else if(temp_freq_nedge) cnt_pwm = cnt_pwm + 1;
    end
    
    // 입력 받은 duty ratio만큼 duty ratio를 갖는 pwm 생성
    assign pwm = (cnt_pwm < stage) ? 1 : 0;
    
endmodule

 

 

 

 

3. Simulation 

< Duty ratio = 50 >

  • Duty ratio = {(139us - 100us) / 100us} * 128 =  49.92 = 50 임을 확인할 수 있다.

 

 

 

< Duty ratio = 100 >

  • Duty ratio = {(177.708us - 100.465us) / 100us} * 128 = 98.871 = 100 임을 확인할 수 있다.