(DDS)正弦波形發生器——幅值、頻率、相位可調(二)
主要關於調相方面
一、專案任務:
- 設計一個幅值、頻率、相位均可調的正弦波發生器。
- 頻率每次增加10kHz
- 相位每次增加 PI/2
- 幅值每次增加兩倍
- ROM的深度為1024、寬度為8
二、文章內容:
- 完成調相模組並驗證功能
- 完成調幅模組
- 按結構圖來連線各個模組並模擬驗證
1、調相
-
從影像上來理解調整相位就是原函式在X軸上進行水平移動。
-
在本專案中函式的波形圖按照順序存在ROM中,我們只要按照比例調整讀取ROM的地址,即可調相。
-
前文中我們使用32位暫存器的高8位用做ROM的地址,因此只要有按鍵按下,我們按照相位同比例的調整讀取ROM的地址即可。
-
ROM的深度為1024、寬度為8儲存標準正弦函式,那麼可知其式為:
\[% MathType!MTEF!2!1!+- % feaahqart1ev3aaatCvAUfeBSjuyZL2yd9gzLbvyNv2CaerbuLwBLn % hiov2DGi1BTfMBaeXatLxBI9gBaerbd9wDYLwzYbItLDharqqtubsr % 4rNCHbWexLMBbXgBd9gzLbvyNv2CaeHbl7mZLdGeaGqiVu0Je9sqqr % pepC0xbbL8F4rqqrFfpeea0xe9Lq-Jc9vqaqpepm0xbba9pwe9Q8fs % 0-yqaqpepae9pg0FirpepeKkFr0xfr-xfr-xb9adbaqaaeGaciGaai % aabeqaamaabaabauaakeaacaqGMbGaaiikaiaadIhacaGGPaGaeyyp % a0JaaGymaiaaikdacaaI4aGaci4CaiaacMgacaGGUbGaaiikamaala % aabaGaamiEaaqaaiaaiwdacaaIXaGaaGOmaaaacqaHapaCcaGGPaaa % aa!4ECD! {\rm{f}}(x) = 128\sin (\frac{x}{{512}}\pi )+128 \]這裡x對應的是ROM地址、y對應的是ROM中資料也即幅值。範圍取x從0到1023、y從0到255。
-
若按鍵一次,相位增加PI/2,則有:
\[% MathType!MTEF!2!1!+- % feaahqart1ev3aaatCvAUfeBSjuyZL2yd9gzLbvyNv2CaerbuLwBLn % hiov2DGi1BTfMBaeXatLxBI9gBaerbd9wDYLwzYbItLDharqqtubsr % 4rNCHbWexLMBbXgBd9gzLbvyNv2CaeHbl7mZLdGeaGqiVu0Je9sqqr % pepC0xbbL8F4rqqrFfpeea0xe9Lq-Jc9vqaqpepm0xbba9pwe9Q8fs % 0-yqaqpepae9pg0FirpepeKkFr0xfr-xfr-xb9adbaqaaeGaciGaai % aabeqaamaabaabauaakqaabeqaaiaadEgacaGGOaGaamiEaiaacMca % cqGH9aqpcaaIXaGaaGOmaiaaiIdaciGGZbGaaiyAaiaac6gacaGGOa % WaaSaaaeaacaWG4baabaGaaGynaiaaigdacaaIYaaaaiabec8aWjab % gUcaRmaalaaabaGaeqiWdahabaGaaGOmaaaacaGGPaGaey4kaSIaaG % ymaiaaikdacaaI4aaabaGaaGjbVlaaysW7caaMe8UaaGjbVlaaysW7 % caaMe8UaaGjbVlaaysW7caaMe8Uaeyypa0JaaGymaiaaikdacaaI4a % Gaci4CaiaacMgacaGGUbGaaiikaiaacIcadaWcaaqaaiaadIhaaeaa % caaI1aGaaGymaiaaikdaaaGaey4kaSYaaSaaaeaacaaIXaaabaGaaG % OmaaaacaGGPaGaeqiWdaNaaiykaiabgUcaRiaaigdacaaIYaGaaGio % aaqaaiaaysW7caaMe8UaaGjbVlaaysW7caaMe8UaaGjbVlaaysW7ca % aMe8UaaGjbVlabg2da9iaaigdacaaIYaGaaGioaiGacohacaGGPbGa % aiOBaiaacIcacaGGOaWaaSaaaeaacaWG4bGaey4kaSIaaGOmaiaaiw % dacaaI2aaabaGaaGynaiaaigdacaaIYaaaaiaacMcacqaHapaCcaGG % PaGaey4kaSIaaGymaiaaikdacaaI4aaaaaa!9896! \begin{array}{l} g(x) = 128\sin (\frac{x}{{512}}\pi + \frac{\pi }{2}) + 128\\ \;\;\;\;\;\;\;\;\; = 128\sin ((\frac{x}{{512}} + \frac{1}{2})\pi ) + 128\\ \;\;\;\;\;\;\;\;\; = 128\sin ((\frac{{x + 256}}{{512}})\pi ) + 128 \end{array} \] -
其中綠色為f(x),紫色為調整相位後的g(x)。
-
即每次按下按鍵後相當於將影像向左平移256,那麼也就是按下按鍵後,提前讀取256個地址之後的資料。
-
module phase_ctrl( input clk, input rst_n, input f_phase, output [9:0] initiala_address ); assign initiala_address = 10'd256; endmodule module addr_ctrl( input clk, input rst_n, input [31:0] freq_num, input [9:0] initiala_address, input f_phase, output [9:0] address ); reg [31:0] cnt; always @(posedge clk,negedge rst_n) begin if(rst_n == 0) cnt <= 32'd0; else if(f_phase == 1) cnt[31:22] <= cnt[31:22] + initiala_address; else cnt <= cnt + freq_num; end assign address = cnt[31:22]; endmodule
-
驗證:選取三個變頻前後的點將其與理論計算的值進行對比
重點關注在f_phase拉高前後,正弦波上3個點(address,data)的大小
-
(43,161) (43+256,251)=(299,251)
-
(754,0) (754+256)=(1010,117)
-
(856,18) (856+256-1024,193)=(88,193)
-
-
理論計算:
-
(43,161)(43,251) (754,0)(754,117) (856,18) (856,193)
-
可以看到調相模組準確的完成了每次按鍵按下,相移PI/2的任務。
-
2、調幅
-
這一部分在程式碼方面比較簡單,實際驗證還需要數模轉換和示波器的配合,限於條件無法達到,因此只展模擬結果。
-
在程式上要注意位寬的變化,由於不斷的放大,因此將輸出data設計為32位。
-
每次按鍵按下。幅值放大兩倍。
-
module amplitude_ctrl( input clk, input rst_n, input f_ampli, input [7:0] data_in, output [31:0] data ); reg [23:0] ampli_num; always @(posedge clk,negedge rst_n) begin if(rst_n == 0) ampli_num <= 24'd1; else if(f_ampli == 1) ampli_num <= ampli_num * 24'd2; else ampli_num <= ampli_num; end assign data = ampli_num * data_in; endmodule
3、模組連線及總體功能驗證
-
系統結構圖為:
-
ModelSim模擬:
-
頻率變化:
-
相位變化:
-
幅值變化:
-
-
測試程式碼:
`timescale 1ns/1ns module key_dds_tb(); reg clk; reg rst_n; reg key_freq; reg key_phase; reg key_ampli; wire [31:0] data; key_dds key_dds_inst( .clk (clk), .rst_n (rst_n), .key_freq (key_freq), .key_phase(key_phase), .key_ampli(key_ampli), .data (data) ); initial clk = 1; always #10 clk = !clk; initial begin rst_n = 0; key_freq = 1; key_phase = 1; key_ampli = 1; #200 rst_n = 1; #200 key_freq = 1; #10000000 key_freq = 0; #2000 key_freq = 1; #10000000 key_freq = 0; #1000000 key_freq = 1; #10000000 key_phase = 1; #2000000 key_phase = 0; #70000 key_phase = 1; #11500 key_phase = 0; #70000 key_phase = 1; #25000 key_phase = 0; #23333 key_phase = 1; #1000000 key_ampli = 1; #10000000 key_ampli = 0; #2000 key_ampli = 1; #1000000 #10000 $stop; end endmodule
備註:
- 之後有時間我想試著在螢幕上輸出DDS產生的波形,看看效果。
- mif檔案
- 按鍵部分的功能是進行消陡然後輸出一個同系統時鐘的標誌訊號flag。
作者:13tree
出處:https://www.cnblogs.com/13tree/
本文版權歸作者所有,如需轉載請保留此段宣告。