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. 实现

posted @ 2020-05-02 11:37  叮叮当当sunny  阅读(887)  评论(0编辑  收藏  举报