一.DDS的原理
直接数字频率合成器(DDS),功能是通过输入频率输入字从而实现改变输出信号的频率的功能,它所利用的原理就是虽然对于一段正弦信号来说其幅度值是非线性的,但是其相位的值却是线性增加的,如下图所示:DDS的核心公式便脱颖而出
公式中N代表的是频率字输入的位数,当位数越大的时候输出的频率的频率分辨率便会越高,DDS的核心原理也如上图所示:
二.ROM的设计实现
如果仅仅是为了设计方针可以通过$redmem来实现对某一文件的读取,但是为了实现可以综合的系统的设计我们采用如下的采用vivado自带的IP内核来设计,其实实现的过程是非常简单的,我们要完成的最主要的任务就是用vivado(我所使用的开发平台)完成ROM的IP核的配置工作,以及其他的工作即可,那么接下来我们来介绍一下ROM的配置:
首先第一步:(打来项目的IP catalog)
第二步,搜索block memory关键词
第三步,设置ROM的一些参数,包括其中的存储内容.coe文件以及其数据深度和数据宽度(数据深度指的是:最大可以存储的数据个数,比如12位的数据深度就是可以存储4096个数据。数据宽度指的是:存储数据的位数,即存储的几位数据)
第四步,点击确认生成器件,在器件生成后依旧可以对器件进行修改,我们可以通过以下操作来引用ROM模块(右边是在sourses的IP sources的)。
三..coe文件的生成
move=2^12;
%先生成文件,和头格式
fid = fopen('all.coe','w');
fprintf(fid,'MEMORY_INITIALIZATION_RADIX=10;\n');
fprintf(fid,'MEMORY_INITIALIZATION_VECTOR=\n');
%先写入sin函数值地址0~4095
t=0:2*pi/2^12:2*pi;
y=0.5*sin(t)+0.5;
r=ceil(y*(2^8-1)); %将小数转换为整数,ceil是向上取整。
for i = 1:1:2^12
fprintf(fid,'%d',r(i));
fprintf(fid,',');
if i%15==0
fprintf(fid,'\n');
end
end
%下面写入方波
t=1:1:2^12;
y=(t<=2047);
r=ceil(y*(2^8-1));
for i = 1:1:2^12
fprintf(fid,'%d',r(i));
fprintf(fid,',');
if i%15==0
fprintf(fid,'\n');
end
end
%最后写入三角波
t=1:1:2^12;
y=[0.5:0.5/1024:1-0.5/1024, 1-0.5/1024:-0.5/1024:0, 0.5/1024:0.5/1024:0.5];
r=ceil(y*(2^8-1));
for i = 1:1:2^12
fprintf(fid,'%d',r(i));
if i==2^12
fprintf(fid,';');
else
fprintf(fid,',');
end
if i%15==0
fprintf(fid,'\n');
end
end
fclose(fid);
以上是正弦波,方波以及三角波的形成matlab代码
四.verilog代码的编写
module top#(parameter move=4096)(
input [13:0]fw,//
input clk,//
input reset,// output [9:0]out
); reg [14:0]phase;
reg [13:0] relat;
wire [13:0] addr; always@(posedge clk or negedge reset)
begin
if(!reset)
begin
phase<=0;
relat<=0;
end
else
begin
if((fw>=move))
begin
if(fw>=2*move) relat=fw-2*move;
else relat=fw-move;
end
else relat=fw;
phase=((phase+relat)>12'd4095)?0:(phase+relat);
end
end assign addr=phase+(fw-relat); rom r(.clk(clk),.phase(addr),.out(out)); endmodule
在波形设置的窗口可以设置模拟数字波形,这里还要注意的一点是如果要显示方波一定在模拟波形的设置里面的hold勾上,因为verilog默认是线性画图。