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]);
2. Simulink驗證
在Simulink中構建一個簡單的電路模型,對波形進行觀察。
觀察電流波形,可以看到其接近三角波,PWM調制結果正確。
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計算結果相一致。