PWM 是一種調節輸出功率的技術(俗稱調壓),其原理在於改變輸出方波的占空比,具體輸出見下圖:
輸出信號為電壓值,當負載為恆阻時,上圖中的輸出功率分別為 25%、50%、75%。
實現方法如下:
- 設置一個計數器,上圖中的第一行就是個 4 位的計數器,每滿 15 自動變為 0。那么可以得到輸出頻率等於時鍾的 1/16。
- 當計數器的值小於某個值的時候輸出 0,高於或者等於某個值的時候輸出 1。
假設控制的是一個小燈為 1/8 功率輸出,那么我們需要的值就是 13 (4'hD),當計數器小於等於 13 輸出 0,否則輸出 1。
具體代碼如下:
如果時鍾為 50MHz,一個時鍾周期為 2ns,根據推算可以得出上述的 PWM 輸出信號的周期為 32 ns,頻率大約 1.5MHz。由於 1.5MHz 的頻率遠遠的超過了人眼 100Hz 的分辨極限,所以在人看來 LED 會一直發光但亮度較低。
然而並不是所有的外設都能承受 1.5MHz 這么高的頻率。很多器件內包含有三極管,但三極管是存在截止頻率上限問題,當輸出管腳通過三極管來放大輸出電流時,過高的頻率會導致輸出失效,所以絕大多數情況下我們需要降低 PWM 的輸出頻率。
使用環形計數器可以得到任意整數分頻的電路,這在電子鍾篇中已經試用過了。我們可以把分頻模塊的輸出作為另一個電路的時鍾輸入,可是這種方法生成的時鍾信號不夠穩定。鎖相環可以對時鍾信號進行任意比例分頻,倍頻和移相等操作。鎖相環分為數字式(DLL)和模擬式(PLL)兩種,Altera 公司在 FPGA 里集成了模擬式鎖相環,Xilinx 公司的器件集成的既有模擬的也有用數字式的。
與 ASICS 的自由布線相比,FPGA 內部可用的時鍾就顯得十分有限了。FPGA 可用的時鍾牽扯到全局時鍾網絡的問題。由於這里不涉及畫板子的問題,對於時鍾網絡就不多做贅述了。
鎖相環的使用方法: 首先在 tools 菜單欄找到並打開 MegaWizard Plug-In Manager,按照下面的步驟配置使用 PLL IP 核
這個 IP 核輸出多達 5 個 信號,由於我們只需要用到一個輸出 c0,所以 c1 ~ c4 設置為默認(不開啟)即可。
這樣的話 PLL 核就配置好了,原理圖連接方法:
本文中時鍾為 50MHz,可以計算得到輸出頻率
50M = 50_000_000 –> 50_000_000 / 25_000 = 2000 –> 2000/16 = 125
125Hz 的一個周期為 0.008s = 0ms = 8_000 us,使用圖形仿真輸入來驗證顯然不太現實,此外我們在工程中使用了 IP 核,出於效率的考慮應當選用 Modelsim。但我在使用 Modelsim 仿真時出現了問題,Modelsim 總是報告分頻系數不正確,然而當我把分頻系數降為 10 ,仿真器卻可以正常工作。我猜測可能是因為 Modelsim 在仿真 Cyclone IV E 系列 PLL 的時候調用的是 Cyclone III 的仿真文件,而 Cyclone IV 的 PLL 與 Cyclone III 也許並不完全一致,也有可能是仿真庫文件出現了問題。
覺得效果不夠明顯可以在 pwm 代碼中添加一個全亮的燈作為參照也可以把 duty 改為 4'hE(1/16 功率),此外還可以嘗試增大鎖相環中的分頻系數讓小燈閃動(只要鎖相環配置時出現 able to implement the requested PLL 就表示配置可行)。