当前位置:   article > 正文

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

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

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

主要关于调相方面

一、项目任务:

  • 设计一个幅值、频率、相位均可调的正弦波发生器。
    • 频率每次增加10kHz
    • 相位每次增加 PI/2
    • 幅值每次增加两倍
    • ROM的深度为1024、宽度为8

二、文章内容:

  1. 完成调相模块并验证功能
  2. 完成调幅模块
  3. 按结构图来连接各个模块并仿真验证

1、调相

  • 从图像上来理解调整相位就是原函数在X轴上进行水平移动。

  • 在本项目中函数的波形图按照顺序存在ROM中,我们只要按照比例调整读取ROM的地址,即可调相。

  • 前文中我们使用32位寄存器的高8位用做ROM的地址,因此只要有按键按下,我们按照相位同比例的调整读取ROM的地址即可。

  • ROM的深度为1024、宽度为8储存标准正弦函数,那么可知其式为:
    f ( x ) = 128 sin ⁡ ( x 512 π ) + 128 % 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 f(x)=128sin(512xπ)+128
    这里x对应的是ROM地址、y对应的是ROM中数据也即幅值。范围取x从0到1023、y从0到255。

  • 若按键一次,相位增加PI/2,则有:
    g ( x ) = 128 sin ⁡ ( x 512 π + π 2 ) + 128                    = 128 sin ⁡ ( ( x 512 + 1 2 ) π ) + 128                    = 128 sin ⁡ ( ( x + 256 512 ) π ) + 128 % 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! g(x)=128sin(x512π+π2)+128=128sin((x512+12)π)+128=128sin((x+256512)π)+128 g(x)=128sin(512xπ+2π)+128=128sin((512x+21)π)+128=128sin((512x+256)π)+128

  • 在这里插入图片描述

    其中绿色为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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
  • 验证:选取三个变频前后的点将其与理论计算的值进行对比

    重点关注在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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
  • 在这里插入图片描述

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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86

备注:

  • 之后有时间我想试着在屏幕上输出DDS产生的波形,看看效果。
  • 按键部分的功能是进行消陡然后输出一个同系统时钟的标志信号flag。

作者:13tree

出处:https://blog.csdn.net/weixin_41890387

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

声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号