tag 标签: dds ip core

相关博文
  • 热度 13
    2017-7-9 16:48
    14780 次阅读|
    1 个评论
    沐浴着帝都的热浪,不知不觉研究生生活就开始了,下午和晚上急匆匆地去赶着上课,上午就抽出时间完成实验室的培训任务。这次是要用DDS 的IP 核产生一个1k的正弦波,经历的4天的折腾,总算是整出来了。话不多说,马上进入正题。开发环境用的 vivado 2015. 1. 新建一个工程,这里就不详细展开了。 2. 生成DDS IP 核, 点击 IP catalog, 然后双击 DDS compiler, 选择 sin cos lut only , 输出数据设置为 8bit(后期AD的输入要求8bit),(记着这里的相位数据是16 bit, 后期算输出频率要用) output selection 选择 sin(因为只需要正弦波),然后点击OK 3.编写顶层文件 因为开发板用的是 Xilinx 的Zedboard,它的系统频率为100MHz, 根据输出频率的计算公式,相位步进间隔= (fout / fdds_in) * 2^N (N 为前面相位的位宽),所以如果用系统的频率作为DDS的输入频率,相位步进间隔= (1k / 100M)* 2^16 = 0.65536,显然这在verilog 中无法实现,所以我们要设法使DDS IP 核的输入频率较小。这里我们通过对系统频率进行分频,获得 100KHz,作为DDS的输入频率,此时相位步进间隔为 655。 代码如下 module dds_top( input rst_n, input clk_100M, output data_tvalid, output data_tdata ); reg cnt; reg clk_100K; always @(posedge clk_100M or negedge rst_n)begin if(!rst_n)begin cnt=10'd0; clk_100K=0; end else if(cnt==10'd499)begin cnt=10'd0; clk_100K = ~clk_100K; end else begin cnt=cnt+1'b1; end end reg phase_tdata; always @(posedge clk_100K or negedge rst_n)begin if(!rst_n)begin phase_tdata=16'd0; end else if(phase_tdata 16'b1111_1111_1111_1111)begin phase_tdata = phase_tdata + 10'd655; // (1k / 100k) * 2^16 =655 end else begin phase_tdata=16'd0; end end dds_compiler_0 dds_inst( .aclk(clk_100K), .s_axis_phase_tvalid(1'b1), .s_axis_phase_tdata(phase_tdata), .m_axis_data_tvalid(data_tvalid), .m_axis_data_tdata(data_tdata) ); endmodule 4.编写测试文件 module simu( ); reg rst_n; reg clk_100M; wire data_tvalid; wire data_tdata; dds_top dds_top_inst( .rst_n(rst_n), .clk_100M(clk_100M), .data_tvalid(data_tvalid), .data_tdata(data_tdata) ); always #5 clk_100M = ~clk_100M; initial begin rst_n=0; clk_100M=0; #10; rst_n=1; #1000000; $stop; end endmodule 仿真时注意要设置足够长的仿真时间,data_tdata 要设置为 模拟显示,格式是 有符号型。 仿真波形如下(漂亮的正弦波,哈哈!): 后记 一直关注EDN和面包板,这是我第一次在这里写博客,希望有个好的开端吧!