(DDS)正弦波形發生器——幅值、頻率、相位可調(二)

13tree發表於2022-02-10

(DDS)正弦波形發生器——幅值、頻率、相位可調(二)

主要關於調相方面

一、專案任務:

  • 設計一個幅值、頻率、相位均可調的正弦波發生器。
    • 頻率每次增加10kHz
    • 相位每次增加 PI/2
    • 幅值每次增加兩倍
    • ROM的深度為1024、寬度為8

二、文章內容:

  1. 完成調相模組並驗證功能
  2. 完成調幅模組
  3. 按結構圖來連線各個模組並模擬驗證

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/

本文版權歸作者所有,如需轉載請保留此段宣告。

相關文章