FPGA PWM呼吸燈


1. MATLAB仿真

首先對該PWM算法進行驗證,載波和調制信號均為三角波,頻率相差50倍。

f=50000;%時鍾頻率
num=10;%重復周期數
radio=50;%調制比
carrier=zeros(1,f/radio);%載波
for i=1:(f/radio)
    if i<=(f/(2*radio))
        carrier(i)=i;
    else
        carrier(i)=(f/radio)-i;
    end
end
modulating=repelem(carrier,radio);%調制信號
carrier=repmat(carrier,1,radio);
time=0:1/f:num-1/f;
output=zeros(f,1);%PWM輸出
output(1)=1;
for i=2:f
    if((carrier(i)>modulating(i) && carrier(i-1)<=modulating(i-1)) || ...
            (carrier(i)<modulating(i) && carrier(i-1)>=modulating(i-1)))
        output(i)=~output(i-1);
    else
        output(i)=output(i-1);
    end
end
output=repmat(output,num,1);
PWM=timeseries(output,time');

繪出圖像,如下圖所示,可以看到輸出信號占空比先增大后減小,輸出信號均值跟隨調制信號變化。

subplot(2,1,1);
stairs((0:f-1)/f,[carrier;modulating]');
subplot(2,1,2);
plot((0:f-1)/f,output(1:f));
ylim([-0.2,1.2]);

image

2. Simulink驗證

在Simulink中構建一個簡單的電路模型,對波形進行觀察。

 

image

觀察電流波形,可以看到其接近三角波,PWM調制結果正確。

image

3. 源文件

將上面的算法用Verilog進行描述。

carrier為載波,modulating為調制信號,flag_c指示carrier處於上升沿還是下降沿,同樣,flag_m指示modulating的狀態。

clk上升沿到來,carrier變化一次,radio加一;radio計數達50,modulating變化一次。

module breath_led(
    output reg led = 1'b0,  // LED1, 1 on, 0 off
    input      clk,  // FPGA PL clock, 50 MHz
    input      rst_n // FPGA reset pin
);
 reg [18:0] carrier = 19'b0;
 reg [18:0] modulating = 19'b0;
 reg [5:0] radio = 6'b0;
 reg flag_c = 0;
 reg flag_m = 0;
    //clock input 50000000
parameter CLOCK_FREQ = 50000000;
parameter COUNTER_MAX = CLOCK_FREQ/100;

    always @(posedge clk, negedge rst_n) begin
        if(!rst_n) begin
            carrier <= 19'b0;
            flag_c <= 0;
        end
        else begin
            if(flag_c == 0)
                carrier <= carrier + 1'b1;
            else
                carrier <= carrier - 1'b1;
            if(carrier == COUNTER_MAX-1)
                flag_c <= 1;
            else if(carrier == 1)
                flag_c <= 0;
        end
    end
    always @(posedge clk, negedge rst_n) begin
        if(!rst_n) begin
            radio <= 6'b0;
            modulating <= 19'b0;
            flag_m <= 0;
        end
        else begin
            if(radio == 49) begin
                radio <= 6'b0;
                if(flag_m == 0)
                    modulating <= modulating + 1'b1;
                else
                    modulating <= modulating - 1'b1;
                if(modulating == COUNTER_MAX-1)
                    flag_m <= 1;
                else if(modulating == 1)
                    flag_m <= 0;
            end
            else
                radio <= radio + 1'b1;
        end
    end
    always @(posedge clk, negedge rst_n) begin
        if(!rst_n) begin
            led <= 1'b0;
        end
        else begin
            if(carrier>modulating)
                led <= 1'b0;
            if(carrier<modulating)
                led <= 1'b1;
        end
    end
endmodule

4. 仿真文件

`define clk_cycle 10
module breath_led_sim();
    reg clk, rst_n;
    wire led;
    always #`clk_cycle clk = ~clk;
    initial begin
        clk = 0;
        rst_n = 1;
        #10 rst_n = 0;
        #10 rst_n = 1;
    end
breath_led breath_led(.rst_n(rst_n), .clk(clk), .led(led));
endmodule

 仿真1s,觀察波形,如下圖所示。與MATLAB計算結果相一致。

image

5. 實現


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM