三 DDS正弦信号产生实验
3.1 实验目标
- 设计DDS,50MHz的时钟速率,输出波形频率10MHz
- DDS的输出数据格式为2补码,相位累加器32比特,ROM波表尺寸10bit和波形量化比特数10bit
- 首先在signaltap里观察波形的正确性,然后把signaltap的数据导入到matlab,分析频域结果
3.2 实验原理
注意
频率控制字K与ROM位数没有关系
1、正弦波波形是可以一段一段曲折拼成的
2、例,频率控制字位数FW_WL=32,ROM地址位数RA_WL=10。加法器输出10位数据,该10位数据这样得出:
acc_R <= #1 fwin_R + acc_R;
addr_R <= acc_R[FW_WL-1:FW_WL-1-(RA_WL-1)];
取的ROM地址是前10位,即一段时间内,ROM表的输出没有变化,最后可以看出是锯齿拼成正弦波
3.3程序matlab与verilog
3.3.1 matlab生成rom代码
(1)生成10bit rom
%假设用到的DA芯片为10,width,对应量化
%正弦波ROM的深度为1024(地址总数),对应采样
%该ROM中数据为一个整周期正弦波1024点采样,每个样点采用10比特量化,数据范围(-1,1),二进制补码格式
%本实验中量化10bit
function []=rom_gen()
depth=1024;
%width=8;
width=10;
%x=ceil(power(2,8)/2*sin(0:pi*2/depth:2*pi))
x=ceil((power(2,width)/2-1)*sin(0:pi*2/depth:2*pi));
fid=fopen('D:\useful\fpga\quaters\basic6\prj6\matlabtest\sine_rom.v','w');
fprintf(fid,'module sine_rom(\n');
fprintf(fid,' input clk,\n');
fprintf(fid,' input [9:0] RA,\n');
fprintf(fid,' output reg[9:0] RD );\n');
fprintf(fid,'always @ (posedge clk)\n');
fprintf(fid,'case(RA)\n');
for k=1:depth
%fprintf(fid,'10''d %d :RD=#1 8''b %d ;\n',k-1,x(k));
fprintf(fid,'10''d %d :RD=#1 10''b %s ;\n',k-1,dec2binPN(x(k),10));
end
fprintf(fid,'default: RD=#1 0;\n');
fprintf(fid,'endcase\n');
fprintf(fid,'endmodule\n');
(2)二进制补码函数 dec2binPN.m
% https://wenku.baidu.com/view/6c477149336c1eb91a375d3a.html
function [numbin]=dec2binPN(numdec, N)
if(numdec>=0)
numbin1=dec2bin(numdec,N);
else
numbin1=dec2bin(abs(numdec),N);
l1=length(numbin1);
numbin4=0;
for i=1:l1
if(numbin1(l1-i+1)==num2str(1))
%matlab字符串数组s(n):s第n位
%按位取反,用十进制表示
numbin4=numbin4+0;
else
numbin4=numbin4+power(2,i-1);
end
end
numbin4=numbin4+1;
numbin1=dec2bin(numbin4,N);
end
numbin=numbin1;
3.3.2 Verilog代码
(1)顶层文件top_sin_wav.v
`timescale 1ns/1ns
module top_sin_wave(
CLK , // clock, posedge v