Language/Verilog

Vivado : PWM 제어

짱도르딘 2024. 7. 31. 17:32
728x90

PWM

 

LED의 밝기는 Duty rate에 따라 달라진다. LED 뿐만 아닌 모터의 경우에는 속도도 달라진다.

 

PWM을 제어해 보기 위해 아래와 같은 코드를 구현해 보았다.

 

우선 Duty를 100단계로 설정하기 위하여 duty에 7비트를 선언하였다.

 

첫 번째 100 분주기는 1us 단위로 pulse를 준다.

그다음 두 번째 100 분주기는 1us 단위의 pulse를 100us 주기로 하고, duty값에 따라 변화하는 파형을 보기 위해 아래와 같이 총 10,000 분주기를 설정하였다.

 

//LED 밝기 제어 컨트롤러
module pwm_100step(
    input clk, reset_p,
    input [6:0] duty, // 100단계 만큼
    output pwm);
    
    reg [6:0] cnt_sysclk;

    always @(negedge clk or posedge reset_p)begin
        if(reset_p)cnt_sysclk = 0;
        else begin
            if(cnt_sysclk >= 50) cnt_sysclk = 0;
            else cnt_sysclk = cnt_sysclk + 1;
        end    
    end
    
    assign clk_div_100 = (cnt_sysclk < 50) ? 1 : 0;
    
    edge_detector_n ed(
    .clk(clk), .reset_p(reset_p), .cp(clk_div_100),
    .n_edge(clk_div_100_nedge));
    
    reg [6:0] cnt;
    
    // 100분주
    always @(negedge clk or posedge reset_p)begin
        if(reset_p)cnt = 0;
        else begin
            if(cnt >= 99) cnt = 0;
            else cnt = cnt + 1;
        end    
    end
    
    assign pwm = (cnt < duty) ? 1 : 0; // 90보다 작을동안 1, 아니면 0
    
endmodule

 

아래는 duty 값에 따라 변화하는 파형을 나타낸다. duty값을 각각 10, 90으로 나누어 출력해 보았다.

duty 10인 경우

 

duty 90인 경우


물리적으로 확인해 보기 위하여 Top모듈을 선언하여 진행하였다.

 

코드는 아래와 같다.

module led_pwm_top(
    input clk, reset_p,
    output pwm);

    reg [31:0] clk_div;
    always @(posedge clk) clk_div = clk_div + 1;

    pwm_128step pwm_inst(.clk(clk), .reset_p(reset_p), .duty(clk_div[27:21]), .pwm(pwm));

endmodule

 

동작은 아래의 영상과 같다.

 

 

 

동작을 확인해 보면 LED의 밝기가 점점 밝아지는 것을 확인할 수 있다.

728x90