当前位置:   article > 正文

基于FPGA的DDS 信号发生器(一)_dds中波形存储器

dds中波形存储器

1 DDS原理

1.1 书上的解释

DDS(Direct Digital Synthesizer)技术是一种全新的频率合成方法,是从相位概念出发直接合成所需波形的一种频率合成技术,通过控制相位的变化速度,直接产生各种不同频率、不同波形信号的一种频率合成方法。
在这里插入图片描述
系统的核心是相位累加器,其内容会在每个时钟周期(system clock)更新。相位累加器每次更新时,存储在Δ相位寄存器中的数字字M就会累加至相位寄存器中的数字。假设Δ相位寄存器中的数字为00…01(即M=1),相位累加器中的初始内容为00…00。相位累加器每个时钟周期都会按00…01(M=1)更新。如果累加器为32位宽,则在相位累加器返回至00…00前需要2^32(超过40亿)个时钟周期,周期会不断重复。

相位累加器的截断输出用作正弦(或余弦)查找表的地址。查找表中的每个地址均对应正弦
波的从0°到360°的一个相位点。查找表包括一个完整正弦波周期的相应数字幅度信息。
(实际上,只需要90°的数据,因为两个MSB中包含了正交数据)。因此,查找表可将相位
累加器的相位信息映射至数字幅度字,进而驱动DAC。图3用图形化的“相位轮”显示了这
一情况。
考虑n = 32,M = 1的情况。相位累加器会逐步执行2^ 32 (2^n/M)个可能的输出中的每一个,直至溢出并重新开始。相应的输出正弦波频率等于输入时钟频率 2 ^ 32分频。若M=2,相位累加器寄存器就会以两倍的速度“滚动”计算,输出频率也会增加一倍。以上内容可总结如下:
在这里插入图片描述

1.2 自己的理解

DDS系统主要由相位累加器、波形存储器、数模(D/A)转换器和低通滤波器等四个大的结构组成,其结构框图如下图所示。
在这里插入图片描述
参考时钟:
图中,参考频率f_clk为固定值,一般我们选择系统时钟(system clock),这里设置的是100MHz。
频率控制字:
用来调整输出信号的频率。如何根据参考频率得到输出频率,DDS IP的官方文档给出了相应公式。
在这里插入图片描述
在这里插入图片描述
相位控制字:
在这里插入图片描述
相位累加器:
由N位加法器与N位累加寄存器构成,它根据频率控制字k,完成相位值的累加,并将此累加值输入到波形存储器中。
波形存储器:
将相位累积器的值作为当地址,查找与相位值对应的信号数据,输出到D/A转换器。
D/A转换器:
将波形存储器输出的数字量转换为与之对应的模拟量。
低通滤波器:
由于D/A转换器存在量化误差,输出波形中存在混叠,需要在输出端使用低通滤波器进行滤波,提高信号的输出性能。

2 DDS IP的参数设置

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

3 Vivado实现

3.1 编写源文件

PI的值如何确定的,在后面解释

`timescale 1ns / 1ps


module top(
    input           sys_clk     ,
    input           rst_n       
    );
 
 
reg [15:0] angle;    
always@(posedge sys_clk or negedge rst_n)
begin
    if(!rst_n)
        angle=16'd0;
    else
        angle=angle+3;
end

// 例化求正弦值的ip核 
wire    [15:0]     sin_value;    
dds_sin dds_sin_inst (
      .aclk(sys_clk),                               // input wire aclk
      .s_axis_phase_tvalid(1'b1),                   // input wire s_axis_phase_tvalid
      .s_axis_phase_tdata(angle),                   // input wire [15 : 0] s_axis_phase_tdata
     
      .m_axis_data_tvalid(),                        // output wire m_axis_data_tvalid
      .m_axis_data_tdata(sin_value)                 // output wire [15 : 0] m_axis_data_tdata
);    


wire    [15:0]     theta; 
wire    [15:0]     sin_theta;   
wire    [15:0]     PI  ;
assign PI=32750;    // sin(pi/2)=1,找到最大值对应的横坐标即为pi/2
assign theta = PI/2;    

// 例化求正弦值的ip核  
dds_sin dds_sin_1_inst (
      .aclk(sys_clk),                               // input wire aclk
      .s_axis_phase_tvalid(1'b1 ),                   // input wire s_axis_phase_tvalid
      .s_axis_phase_tdata(theta ),                   // input wire [15 : 0] s_axis_phase_tdata
     
      .m_axis_data_tvalid(      ),                        // output wire m_axis_data_tvalid
      .m_axis_data_tdata(sin_theta)                 // output wire [15 : 0] m_axis_data_tdata
    );    
      

    
    
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

3.2 编写testbench文件

`timescale 1ns / 1ps


module sim_top;

    //input
    reg sys_clk;
    reg rst_n;
    // 初始化

    //例化源文件
    top top_inst(
        .sys_clk    (sys_clk    ),
        .rst_n      (rst_n      )     
        );
        
        
    initial
        begin
            //初始化输入
            sys_clk=0;
            rst_n=0;
            #100;
            rst_n=1;
        end
        // create clock;
        always #5 sys_clk=~sys_clk;



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

3.3 仿真结果

在这里插入图片描述

图中,s_axis_phase_tdata对应的就是theta
m_axis_data_tdata对应的就是sin_theta。可以看出,PI的定义的正确的。

PI的值如何确定的?
*parameter PI=32768; //PI的值如何确定?
利用DDS IP 得到每一个数值(1~100000)下的正弦值,找到正弦最大值(1)所对应的下标。根据sin(pi/2)=1。从而得到PI的值。需要注意的是,不同的位宽得到的PI的值是不一样的。

4 通过DDS计算得到权值

`timescale 1ns / 1ps


module top(
    input    sys_clk,
    input    rst_n    
    );
    
   
reg  [15:0]  angle =0;  
wire [15:0]  sin_angle ;  
// 产生均匀变化的angle
always@(posedge sys_clk)
begin   
    if(rst_n==0)
    begin
        angle=0;
    end    
   else if (angle==65536-1)
    begin
        angle=0;
    end
    else 
    begin
        angle=angle+1'b1;
    end 
           
end 
 
 // sin_angle 
 dds_sin dds_sin_angle_inst (
       .aclk(sys_clk),                               // input wire aclk
       .s_axis_phase_tvalid(1'b1),                   // input wire s_axis_phase_tvalid
       .s_axis_phase_tdata(angle),                   // input wire [15 : 0] s_axis_phase_tdata
      
       .m_axis_data_tvalid(),                        // output wire m_axis_data_tvalid
       .m_axis_data_tdata(sin_angle)                 // output wire [15 : 0] m_axis_data_tdata
     ); 
     
     
     
wire [15:0]   theta=90; //子波束i的指向角度
wire [15:0]   fine =30; 
wire [15:0]   W_1I ;//权值的第1个元素的实部、虚部
wire [15:0]   W_1Q ;
wire [15:0]   W_2I ;//权值的第2个元素的实部、虚部
wire [15:0]   W_2Q ;       
parameter PI=32768;  // 根据每个角度的正弦值的曲线仿真得到(pi/2对应的正弦值最大,PI/2=max_下标)
wire  [15:0]  theta1    ;//子波束i的指向角度
wire  [15:0]  fine1     ;
 assign theta1= theta*PI/180;
 assign fine1= fine*PI/180;
  
 wire [15:0]  sin_theta;
 wire [15:0]  sin_fine;
 wire [15:0]  cos_fine;
 

 // sin_theta 
 dds_sin dds_sin_theta_inst (
       .aclk(sys_clk),                               // input wire aclk
       .s_axis_phase_tvalid(1'b1),                   // input wire s_axis_phase_tvalid
       .s_axis_phase_tdata(theta1),                   // input wire [15 : 0] s_axis_phase_tdata
      
       .m_axis_data_tvalid(),                        // output wire m_axis_data_tvalid
       .m_axis_data_tdata(sin_theta)                 // output wire [15 : 0] m_axis_data_tdata
     ); 
     
  // sin_fine 
 dds_sin dds_sin_fine_inst (
       .aclk(sys_clk),                               // input wire aclk
       .s_axis_phase_tvalid(1'b1),                   // input wire s_axis_phase_tvalid
       .s_axis_phase_tdata(fine1),                   // input wire [15 : 0] s_axis_phase_tdata
      
       .m_axis_data_tvalid(),                        // output wire m_axis_data_tvalid
       .m_axis_data_tdata(sin_fine)                 // output wire [15 : 0] m_axis_data_tdata
     );   
     
   // cos_fine 
 dds_cos dds_cos_fine_inst (
       .aclk(sys_clk),                               // input wire aclk
       .s_axis_phase_tvalid(1'b1),                   // input wire s_axis_phase_tvalid
       .s_axis_phase_tdata(fine1),                   // input wire [15 : 0] s_axis_phase_tdata
      
       .m_axis_data_tvalid(),                        // output wire m_axis_data_tvalid
       .m_axis_data_tdata(cos_fine)                 // output wire [15 : 0] m_axis_data_tdata
     );       
     
  
 wire [31:0] sin_theta_mul_sin_fine1; 
 wire [31:0] sin_theta_mul_cos_fine1;
 wire [31:0] sin_theta_mul_cos_fine_add_sin_theta_mul_sin_fine1;
 
 wire [15:0] sin_theta_mul_sin_fine;//sin(theta)*sin(fine)
 wire [15:0] sin_theta_mul_cos_fine; //sin(theta)*cos(fine)
 wire [15:0] sin_theta_mul_cos_fine_add_sin_theta_mul_sin_fine; //sin(theta)*cos(fine)+sin(theta)*sin(fine)
 
 // 乘法计算
 //sin(theta)*sin(fine)
 mult_16x16 inst_sin_theta_mul_sin_fine (
   .CLK(sys_clk),  // input wire CLK
   .A(sin_theta),      // input wire [15 : 0] A
   .B(sin_fine),      // input wire [15 : 0] B
   .P(sin_theta_mul_sin_fine1)      // output wire [31 : 0] P
 );
 //sin(theta)*cos(fine)
 mult_16x16 inst_sin_theta_mul_cos_fine (
   .CLK(sys_clk),  // input wire CLK
   .A(sin_theta),      // input wire [15 : 0] A
   .B(cos_fine),      // input wire [15 : 0] B
   .P(sin_theta_mul_cos_fine1)      // output wire [31 : 0] P
 );
 //sin(theta)*cos(fine)+sin(theta)*sin(fine)
 assign sin_theta_mul_cos_fine_add_sin_theta_mul_sin_fine1=sin_theta_mul_cos_fine1+sin_theta_mul_sin_fine1;
 
 
 // 截位,保留高16位
 assign sin_theta_mul_sin_fine=sin_theta_mul_sin_fine1[31:16];
 assign sin_theta_mul_cos_fine=sin_theta_mul_cos_fine1[31:16];
 assign sin_theta_mul_cos_fine_add_sin_theta_mul_sin_fine=sin_theta_mul_cos_fine_add_sin_theta_mul_sin_fine1[31:16];
 
 
 wire [31:0] PI_mul_sin_theta_mul_sin_fine1;
 wire [31:0] PI_mul_sin_theta_mul_cos_fine1;
 wire [31:0] PI_mul_sin_theta_mul_cos_fine_add_sin_theta_mul_sin_fine1;
 
 wire [15:0] PI_mul_sin_theta_mul_sin_fine; //PI*sin(theta)*sin(fine)
 wire [15:0] PI_mul_sin_theta_mul_cos_fine; //PI*sin(theta)*cos(fine)
 wire [15:0] PI_mul_sin_theta_mul_cos_fine_add_sin_theta_mul_sin_fine; //PI*(sin(theta)*cos(fine)+sin(theta)*sin(fine))
 
 //PI*sin(theta)*sin(fine)
 mult_16x16 inst_PI_mul_sin_theta_mul_sin_fine (
   .CLK(sys_clk),  // input wire CLK
   .A(PI),      // input wire [15 : 0] A
   .B(sin_theta_mul_sin_fine),      // input wire [15 : 0] B
   .P(PI_mul_sin_theta_mul_sin_fine1)      // output wire [31 : 0] P
 );
 //PI*sin(theta)*cos(fine)
 mult_16x16 inst_PI_mul_sin_theta_mul_cos_fine (
   .CLK(sys_clk),  // input wire CLK
   .A(PI),      // input wire [15 : 0] A
   .B(sin_theta_mul_cos_fine),      // input wire [15 : 0] B
   .P(PI_mul_sin_theta_mul_cos_fine1)      // output wire [31 : 0] P
 );
 //PI*(sin(theta)*cos(fine)+sin(theta)*sin(fine))
 mult_16x16 inst_PI_mul_sin_theta_mul_cos_fine_add_sin_theta_mul_sin_fine(
   .CLK(sys_clk),  // input wire CLK
   .A(PI),      // input wire [15 : 0] A
   .B(sin_theta_mul_cos_fine_add_sin_theta_mul_sin_fine),      // input wire [15 : 0] B
   .P(PI_mul_sin_theta_mul_cos_fine_add_sin_theta_mul_sin_fine1)      // output wire [31 : 0] P
 );
 
 
 // 截位
 assign PI_mul_sin_theta_mul_sin_fine=PI_mul_sin_theta_mul_sin_fine1[31:16];
 assign PI_mul_sin_theta_mul_cos_fine=PI_mul_sin_theta_mul_cos_fine1[31:16];
 assign PI_mul_sin_theta_mul_cos_fine_add_sin_theta_mul_sin_fine=PI_mul_sin_theta_mul_cos_fine_add_sin_theta_mul_sin_fine1[31:16];
 
 
  /*
     函数功能:
     DDS计算某角度所对应的权值
 */     
 assign  W_1I =16'b0111_1111_1111_1111;
 assign  W_1Q =16'b0000_0000_0000_0000;
 
 
  // W_2I  cos(PI*(sin(theta)*sin(fine)))
 dds_cos dds_W_2I_inst (
       .aclk(sys_clk),                               // input wire aclk
       .s_axis_phase_tvalid(1'b1),                   // input wire s_axis_phase_tvalid
       .s_axis_phase_tdata(PI_mul_sin_theta_mul_sin_fine),                   // input wire [15 : 0] s_axis_phase_tdata
      
       .m_axis_data_tvalid(),                        // output wire m_axis_data_tvalid
       .m_axis_data_tdata(W_2I)                 // output wire [15 : 0] m_axis_data_tdata
     );  
 
  // W_2Q  sin(-PI*(sin(theta)*sin(fine)))
 dds_sin dds_W_2Q_inst (
       .aclk(sys_clk),                               // input wire aclk
       .s_axis_phase_tvalid(1'b1),                   // input wire s_axis_phase_tvalid
       .s_axis_phase_tdata(-PI_mul_sin_theta_mul_sin_fine),                   // input wire [15 : 0] s_axis_phase_tdata
      
       .m_axis_data_tvalid(),                        // output wire m_axis_data_tvalid
       .m_axis_data_tdata(W_2Q)                 // output wire [15 : 0] m_axis_data_tdata
     );  
 
 
   
 ila_0 ila_0_inst (
	.clk(sys_clk), // input wire clk
	
	.probe0(theta), // input wire [15:0]  probe0  
	.probe1(fine ), // input wire [15:0]  probe1 
	.probe2(W_1I ), // input wire [15:0]  probe2 
	.probe3(W_1Q ), // input wire [15:0]  probe3 
	.probe4(W_2I ), // input wire [15:0]  probe4 
	.probe5(W_2Q ) // input wire [15:0]  probe5
);
   
    
    
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
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号