广告

原创 Vivado 下调用DDS IP 核产生 1KHz的正弦波

2017-7-9 16:48 1786 0 分类: FPGA/CPLD
   沐浴着帝都的热浪,不知不觉研究生生活就开始了,下午和晚上急匆匆地去赶着上课,上午就抽出时间完成实验室的培训任务。这次是要用DDS 的IP 核产生一个1k的正弦波,经历的4天的折腾,总算是整出来了。话不多说,马上进入正题。开发环境用的 vivado 2015.

1. 新建一个工程,这里就不详细展开了。

2. 生成DDS IP 核,

1111

点击 IP catalog,

222222

然后双击 DDS compiler,

333333

选择 sin cos lut only , 输出数据设置为 8bit(后期AD的输入要求8bit),(记着这里的相位数据是16 bit, 后期算输出频率要用)

444444

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 [7:0] data_tdata

);

reg [9:0]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 [15:0] 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 [7:0] 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 要设置为 模拟显示,格式是 有符号型。 仿真波形如下(漂亮的正弦波,哈哈!):

666666


后记

一直关注EDN和面包板,这是我第一次在这里写博客,希望有个好的开端吧!


广告

文章评论 0条评论)

登录后参与讨论
相关推荐阅读
LoneSurvivor 2018-02-25 08:26
C++输入/输出流(2)
1. get()函数#include<iostream>using namespace std;int main(){    char s1[80], s2[...
LoneSurvivor 2018-02-23 12:19
C++输入/输出流(1)
1. 输入/输出流类层次 C++的输入/输出流类库是用派生方法建立起的,它有2个平行的基类,streambuf和ios。其他的流类都是从这两个基类直接或间接派生的。1.1  ...
LoneSurvivor 2018-02-19 11:36
C++多态(4)——特殊运算符重载和类类型转换
1.“++”和“--”的重载     运算符“++”和“--”的重载要区分前置和后置两种形式。如果不区分前置和后置,则使用operator++()或operator—()即可...
LoneSurvivor 2018-02-12 11:15
C++多态(3)——运算符重载
1.     运算符重载的定义     运算符重载也是实现多态的一个重要手段。运算符重载实现的是编译时的多态,即静态多态性。C++预...
LoneSurvivor 2018-02-12 10:31
C++多态(2)——纯虚函数与抽象类
   抽象类是一种特殊的类,它提供了统一的操作界面。建立抽象类是为了多态地使用抽象类的成员函数。抽象类是包含纯虚函数的类。 1.    ...
LoneSurvivor 2018-02-11 16:24
C++多态(1)
1.     多态      多态是人类思维方式的一种直接模拟,多态性是指不同对象接收到相同的消息时,根据对象类的不同而产...
我要评论
0
0
广告
关闭 热点推荐上一条 /1 下一条