六、基於Verilog的訊號發生器DDS的設計
1、前言
採用 Verilog 設計了一個簡單的訊號發生器,可輸出正弦波、方波、三角波、鋸齒波這 4 種頻率、相位和幅值可調的波形。
2、具體功能
module dds( input wire clk, input wire rst_n, input wire [19:0] freq, input wire [1:0] wave_sel, input wire [1:0] amp_adj, output wire [9:0] wave_adj ); wire [31:0] step_val; wire [9:0] addr; wire [7:0] q; freq_ctrl_v2 freq_ctrl_inst( .clk (clk), .rst_n (rst_n), .wave_sel (wave_sel), .freq (freq), .step_val (step_val) ); phase_adder phase_adder_inst( .clk (clk), .rst_n (rst_n), .wave_sel (wave_sel), .step_val (step_val), .addr (addr) ); rom_ip rom_ip_inst ( .address ( addr ), .clock ( clk ), .q ( q ) ); amp_adj amp_adj_inst( .clk (clk), .rst_n (rst_n), .wave (q), .amp_factor (amp_adj), .wave_adj (wave_adj) ); endmodule
在設計的模組中,包含以下功能:
(1)通過 freq 訊號輸入需要的頻率的值;
(2)通過 wave_sel 訊號選擇所需的波形;
(3)通過 amp_adj 訊號選擇波形放大的倍數。
在該設計中,包含 3 個模組:頻率控制器,根據輸入的頻率值輸出步進值 step_val 。
相位累加器,根據步進值 step_val 控制對應地址的變化。
波形放大器,對 rom 輸出的資料進行放大。
3、設計實現
1、由於正弦波無法直接通過 FPGA 直接產生,因此在 FPGA 中例化一個位寬為 10bit、深度為 1024 的 rom ip核,採用 matlab 產生一個由 256 個取樣點構成的正弦波形、一個由 256 個取樣點構成的方波波形、一個由 256 個取樣點構成的三角波波形、一個由 256 個取樣點構成的鋸齒波的資料點作為該 rom 的初始化檔案。FPGA只需要從 ROM 中讀取相應地址中的資料即可輸出對應波形。
2、在產生正弦波的過程中,FPGA 讀取 ROM 地址中的資料速率決定了正弦波的週期,例如,當 FPGA 的主時鐘為 50MHz,在每個時鐘上升沿讀取完地址 0~255 這 256 個地址的資料後輸出一個完整的正弦波,即經過了一個正弦波週期,此時波形週期為 20ns x 256 = 5120ns。如果每 2 個上升沿讀取的地址才加 1, 則週期為 40ns x 256 = 10240ns 。如果每個上升沿讀取的地址加 2, 則週期為 40ns x128= 2560ns 。因此通過這種改變方法可以改變輸出波形的週期。
但是,此時只能輸出某些頻率的波形,因此在這裡使用了 32 位的計數器cnt[31:0],把高 8 位給 addr[7:0],這樣一來,如果 cnt 在上升沿加 1 ,需要 2^32 個時鐘週期才能產生一個週期的正弦波,此時頻率為 50MHz /(2^32),約為 0.01164Hz,即可以產生的正弦波最小頻率為 0.01164Hz,通過增大 cnt 在每隔上升沿加的值 step_val 即可改變頻率。
3、amp_adj[1:0] 訊號可改變波形,將其賦給 addr[9:8],即可改變 rom 的基地址,通過這種方式改變波形。
4、amp_adj[1:0] 訊號對波形進行放大,只要將得到的波形訊號與該訊號加 1 的值相乘即可。
4、總結
以上是 DDS 的設計思想,具體的實現原始碼可關注我的公眾號:深入淺出玩兒轉FPGA(fpgafun)即可獲取。