(DDS)正弦波形发生器——幅值、频率、相位可调(二)

(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/

本文版权归作者所有,如需转载请保留此段声明。

posted @ 2022-02-10 17:59  13tree  阅读(1575)  评论(2编辑  收藏  举报