赞
踩
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,相位累加器寄存器就会以两倍的速度“滚动”计算,输出频率也会增加一倍。以上内容可总结如下:
DDS系统主要由相位累加器、波形存储器、数模(D/A)转换器和低通滤波器等四个大的结构组成,其结构框图如下图所示。
参考时钟:
图中,参考频率f_clk为固定值,一般我们选择系统时钟(system clock),这里设置的是100MHz。
频率控制字:
用来调整输出信号的频率。如何根据参考频率得到输出频率,DDS IP的官方文档给出了相应公式。
相位控制字:
相位累加器:
由N位加法器与N位累加寄存器构成,它根据频率控制字k,完成相位值的累加,并将此累加值输入到波形存储器中。
波形存储器:
将相位累积器的值作为当地址,查找与相位值对应的信号数据,输出到D/A转换器。
D/A转换器:
将波形存储器输出的数字量转换为与之对应的模拟量。
低通滤波器:
由于D/A转换器存在量化误差,输出波形中存在混叠,需要在输出端使用低通滤波器进行滤波,提高信号的输出性能。
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
`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
图中,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的值是不一样的。
`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
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。