本程式進行FPGA的PWM設計。利用FPGA執行PWM,比用單晶片更為精準。通常在單晶片上,係以8 bits或10 bits進行PWM,也就是可執行0~255的1/255或0~1023的1/1023,通常只能以近似的數字換算成百分比。但在FPGA上,可設計0~100的1/100間隔的PWM,以達到更精確的控制。
為讓應用範圍更廣,本設計採用參數式設計,利用parameter讓使用者可自訂分割值,最大可切割至1023等份,也就是切割成1000等份時,精密度為0.1%。若未輸入parameter,預設為100等份,也就是1%。
程式相當簡單,一個從0計數到n-1的計數器,也就是可分為n等份,輸出則為0~n個高準位,共n+1種狀態。
PWM.v
- // The input clock frequency is 100 times higher than the cycle frequency.
- module PWM(
- input clk,
- input rst,
- input [9:0] iduty,
- output reg opwm
- );
- parameter part = 100;
- reg [9:0] count;
- always @ (posedge clk or negedge rst)
- begin
- if (!rst)
- begin
- count <= 0;
- end
- else if (count == part-1)
- begin
- count <= 0;
- end
- else
- count <= count + 1;
- end
- always @ (posedge clk or negedge rst)
- begin
- if (!rst)
- begin
- opwm <= 1'b0;
- end
- else if (count < iduty)
- begin
- opwm <= 1'b1;
- end
- else
- begin
- opwm <= 1'b0;
- end
- end
- endmodule
- `timescale 1ns/1ns
- module PWM_tb;
- reg clk;
- reg rst;
- reg [9:0] iduty;
- wire opwm;
- reg [9:0] delta_duty;
- PWM u(
- .clk(clk),
- .rst(rst),
- .iduty(iduty),
- .opwm(opwm)
- );
- defparam u.part = 10;
- initial
- begin
- #0
- clk = 0;
- rst = 0;
- iduty = 0;
- delta_duty = 1;
- #100 rst = 1;
- #200000 delta_duty = -1;
- #200000 delta_duty = 1;
- end
- always
- #10 clk = ~clk;
- always
- #2000 iduty = iduty+delta_duty;
- endmodule
把iduty和delta_duty改為Decimal。
當iduty輸入為0時,PWM輸出為0%,當iduty在10以上的時候,為100%的輸出。因為目前僅分為10等份。
刪除testbench檔案PWM_tb.v中第18行的defparam u.part = 10;,會成為預設分割的100等份。把輸入iduty改為類比形式Analog顯示。
若可直接輸入cycle和duty的寫法可如下:
- module PWM(
- rst,
- clk,
- duty,
- cycle,
- oPWM
- );
- input clk,rst;
- input [11:0] duty, cycle;
- output reg oPWM;
- reg [11:0] count;
- always @ (posedge clk or negedge rst)
- begin
- if (!rst)
- begin
- count <= 0;
- end
- else if (count == cycle-1)
- begin
- count <= 0;
- end
- else
- count <= count + 1;
- end
- always @ (posedge clk or negedge rst)
- begin
- if (!rst)
- begin
- oPWM <= 0;
- end
- else if (count < duty)
- begin
- oPWM <= 1;
- end
- else
- oPWM <= 0;
- end
- endmodule