DDS
来源:互联网 发布:淘宝上卖假货犯法吗 编辑:程序博客网 时间:2024/04/30 18:16
作业要求
在FPGA上设计一个DDS模块,在DE0 开发板上运行,在FPGA芯片内部合成出数字波形即可。不用输出模拟信号,本模块满足以下条件
- 使用板载晶振的50MHz时钟,合成以下频率的信号
- 1、500KHz 正弦波信号。 2、1MHz 正弦波信号。3、3MHz 正弦波信号。
- 频率字字长32位,波表ROM尺寸为 10比特地址,1024个word。
- 波形格式为2补码格式,12比特量化。
- 每个CLK输出一个有效样点。
- 输入信号为频率字和频率字输入使能信号。
- 使用板载的拨码开关(Switch)控制生成的波形信号的不同频率。
注意:波表ROM代码是用matlab或C打印生成的。不要手写。
内容要求
- 使用CSDN技术博客交作业
- 人工绘制的 电路结构RTL设计图,该图片用于说明你设计电路时的想法,注意要在RTL图中画出Verilog代码中的 生成D触发器 reg 变量。
- Quartus扫描生成的电路RTL图,该图片用于说明Quartus的电路编译结果。
- 相位累加器的输出,SignalTap截图。
- 波表ROM的输入地址,SignalTap截图。
- 至少捕获 一个完整的输出正弦波形周期的上述数据数值的SignalTap截图。
- 输出正弦波的样值波形,SignalTap截图。
- 提交Verilog、相关MATLAB 代码,请使用博客中提供的代码块功能。
- 分析输出的正弦波信号的频谱,Matlab 截图。
手绘RTL图
Quartus扫描 RTL图
SignalTap截图
- 相位累加器输出
- 波表ROM的输入地址
- 输出正弦波形图
SW1=01时,选频500KHz
SW1=10时,选频1MHz
SW1=11时,选频3MHz
–将SignalTapII抓取的ROMOUT值导出(Create SignalTapII List File),以便后续使用UltraEditor的列模式处理数据。
MATLAB截图
- 误差分析:
频率字长为32位,但地址位只有10位,舍弃掉了相位累加器的低22位,将高10位赋给地址位,精度降低。
对于500k的正弦波:理论k值为32h’028F5C28,实际为32h’02800000,绝对误差为32h’F5C28,合成的实际正弦波频率比500kHz低11718Hz,相对误差为2.4%;
对于1M的正弦波:理论k值为32h’051EB850,实际为32h’05000000,绝对误差为32h’1EB850合成的实际正弦波频率比1MHz低23437Hz,相对误差为2.4%;
对于3M的正弦波:理论k值为32h’0F5C28F0,实际为32h’0F400000,绝对误差为32h’1C28F0,合成的实际正弦波频率比3MHz低21484Hz,相对误差为0.7%;
以3M为例具体分析:
figure1:
figure2:
- 频谱分析:
figure1和figure2各自横向比较可以看出,当数据长度增加时,频率的分率有明显提升;figure1和figure2相互比较可以看出,补零可以看到峰值更多细节,但并不能提高分辨率。
频率分辨率可以理解为在使用DFT时,在频率轴上的所能得到的最小频率间隔f0=fs/N=1/NTs=1/T,其中N为采样点数,fs为采样频率,Ts为采样间隔。一段数据拿来就确定了时间T,注意:f0=1/T,而T=NTs,增加N必然减小Ts ,因此,增加N时f0是不变的。只有增加点数的同时导致增加了数据长度T才能使分辨率越好。补零并没有增加有效数据的长度,仍然为T。
verilog代码
- 选频模块module freq_choice(CLK,FWEN, //ENABLEfreq_in,freq_out);parameter VAL_FREQ_500K = 32'h028F_5C29;//32'd42949673input CLK;input FWEN;input [2-1:0]freq_in;output [32-1:0]freq_out;reg [32-1:0]freq_out;always@(posedge CLK)begin if(FWEN)begin case(freq_in) 2'b00:freq_out=0; //NO OUTPUT 2'b01:freq_out=VAL_FREQ_500K; //CHOOSE 500K 2'b10:freq_out=VAL_FREQ_500K*2; //CHOOSE 1M 2'b11:freq_out=VAL_FREQ_500K*6; //CHOOSE 3M default:freq_out=0; endcase end else freq_out <= freq_out; //HOLD ON endendmodule
- 相位累加器模块module dds_core( CLK , // CLOCK INCR , // INCREASE VALUE TEMP , // TEMPORARY VALUE COUT); // COUNTER VALUEinput CLK;input [31:0] INCR;output reg [31:0] TEMP ;output reg [9:0] COUT;always @ (posedge CLK) begin TEMP <= INCR + TEMP; COUT<=TEMP[31:31-9];endendmodule // module dds_core
- ROM码表// ************************************************************** //// FILE : DDS_CORE_ROM.v // DSCP : DDS CORE ROM FILE// ABOUT : auto generated rom file by gen_rom_rtl.m// ************************************************************** //// module DDS_CORE_ROM()module DDS_CORE_ROM( CLK , // clock RA , // read address RD ); // read datainput CLK;input [9 :0] RA;output [11 :0] RD;reg [11 :0] RD;always @ (posedge CLK) case(RA) 10'd 0 :RD = #1 12'b 000000000000; // 0 0x0 10'd 1 :RD = #1 12'b 000000001100; // 12 0xC 10'd 2 :RD = #1 12'b 000000011001; // 25 0x19 10'd 3 :RD = #1 12'b 000000100101; // 37 0x25 10'd 4 :RD = #1 12'b 000000110010; // 50 0x32 10'd 5 :RD = #1 12'b 000000111110; // 62 0x3E 10'd 6 :RD = #1 12'b 000001001011; // 75 0x4B 10'd 7 :RD = #1 12'b 000001010111; // 87 0x57 10'd 8 :RD = #1 12'b 000001100100; // 100 0x64 10'd 9 :RD = #1 12'b 000001110000; // 112 0x70 ...... default : RD = #1 0; endcaseendmodule
MATLAB代码
- ROM生成代码
此处特别鸣谢代码原创者杜老师
function generate_DDS_rom()clc;close all;disp('##########################################');disp('# generate_DDS_rom() RUN');disp('##########################################');%%///////////////////////////////////////////////////% set your rom config hererom_word_len = 12; % rom data word length in bitrom_addr_len = 10; % rom address word length in bitrom_file_name = 'DDS_CORE_ROM.v'; % rom file namerom_file_dir = './'; % rom file dir pathdescription = 'DDS CORE ROM FILE' % rom description%%///////////////////////////////////////////////////rom_vec_len = 2^rom_addr_len;index = [0:rom_vec_len-1] .';rom_data_vec_float = sin(2*pi*index/rom_vec_len);figure; plot(rom_data_vec_float); % for debugrom_data_vec_int = fix(rom_data_vec_float * (2^(rom_word_len-1) - 1));figure; plot(rom_data_vec_int); % for debugrom_cfg.rom_word_len = rom_word_len ;rom_cfg.rom_file_name = rom_file_name ;rom_cfg.rom_file_dir = rom_file_dir ;rom_cfg.description = description ;gen_rom_rtl(rom_cfg, rom_data_vec_int);end % generate_DDS_rom()% ///////////////////////////////////////////////////////////////////////////////% gen_rom_rtl()% generate synthesizable rom hdl code(need synthesizer support).% ///////////////////////////////////////////////////////////////////////////////% INPUT: % data vector, must be integer value% rom word len% rom file dir string% rom file name string% OUTPUT:% verilog format rom file, all data in 2's complement code formatfunction gen_rom_rtl(rom_cfg, data_vec); rom_word_len = rom_cfg.rom_word_len ; rom_file_name = rom_cfg.rom_file_name ; rom_file_dir = rom_cfg.rom_file_dir ; description = rom_cfg.description ; data_vec_len = length(data_vec); addr_word_len = ceil(log2(data_vec_len)); % check input be integer value data_vec_fixed = fix(data_vec); diff_sum = sum(data_vec == data_vec_fixed); % all integer elements will cause the diff_sum be vector length if(diff_sum < data_vec_len) fprintf(1,'# ERROR, gen_rom_rtl(), input data_vec must be integer value\n'); return; end rom_file_dir_name = strcat(rom_file_dir, rom_file_name); data_vec_fixed_2c = data_vec_fixed + (2^rom_word_len) .* (data_vec_fixed < 0); romNum = 2^addr_word_len; data_str_cell = cell(data_vec_len, 1); for(idx = 1:data_vec_len) data_str_cell{idx} = Dec2BinStr(data_vec_fixed_2c(idx), rom_word_len); end % for(idx = 1:data_vec_len) if(romNum > data_vec_len) for(idx = data_vec_len+1:romNum) data_str_cell{idx} = Dec2BinStr(0, rom_word_len); end end fid_rom_file = fopen(rom_file_dir_name, 'w'); if(fid_rom_file == -1) errMsg = strcat('ERROR, gen_rom_rtl(), create file',rom_file_dir_name, ',failed'); fprintf(1, '%s\n', errMsg); return; end % rom data print % get rom module name rom_name = rom_file_name; len_rom_file_name = length(rom_file_name); if(rom_name(len_rom_file_name-1:len_rom_file_name) == '.v') rom_name(len_rom_file_name-1:len_rom_file_name) = []; else fprintf(1,'#WARNINIG, gen_rom_rtl(), rom_file_name may error, check it!\n'); end fprintf(fid_rom_file, ... '// ************************************************************** //\n'); fprintf(fid_rom_file, ... '// FILE : %s \n', rom_file_name); fprintf(fid_rom_file, ... '// DSCP : %s\n', description); fprintf(fid_rom_file, ... '// ABOUT : auto generated rom file by gen_rom_rtl.m\n'); fprintf(fid_rom_file, ... '// DATE : %s \n', datestr(now)); fprintf(fid_rom_file, ... '// ************************************************************** //\n'); % generate the crom module fprintf(fid_rom_file, ... '// module %s()\n', rom_name); fprintf(fid_rom_file, ... 'module %s(\n', rom_name); fprintf(fid_rom_file, ... ' CLK , // clock\n'); fprintf(fid_rom_file, ... ' RA , // read address\n'); fprintf(fid_rom_file, ... ' RD ); // read data\n'); fprintf(fid_rom_file, ... 'input CLK;\n'); fprintf(fid_rom_file, ... 'input [%-2d :0] RA;\n', addr_word_len-1); fprintf(fid_rom_file, ... 'output [%-2d :0] RD;\n', rom_word_len-1); fprintf(fid_rom_file, ... 'reg [%-2d :0] RD;\n', rom_word_len-1); fprintf(fid_rom_file, ... 'always @ (posedge CLK)\n'); fprintf(fid_rom_file, ... ' case(RA)\n'); for addr = 0:1:data_vec_len-1 fprintf(fid_rom_file, ... ' %-2d''d %-6d:RD = #1 %-2d''b %s; ', ... addr_word_len,addr, rom_word_len, data_str_cell{addr+1}); fprintf(fid_rom_file, ... '// %6d 0x%s \n', ... data_vec_fixed(addr+1), dec2hex(data_vec_fixed_2c(addr+1))); end fprintf(fid_rom_file, ... ' default : RD = #1 0;\n'); fprintf(fid_rom_file, ... ' endcase\n'); fprintf(fid_rom_file, ... 'endmodule \n'); fclose(fid_rom_file); fprintf(1,'# File: %s written\n', rom_file_dir_name);end % function gen_rom_rtl() % ////////////////////////////////////////////////////////////////////function str = Dec2BinStr(data, word_len) str = ''; for(idx = word_len-1:-1:0) bit_val = bitand(1, bitshift(data, -idx)); str = strcat(str, int2str(bit_val)); endend % function Dec2BinStr()
- 3M正弦波频谱分析代码:
clear;%%选频3MHz,不补零,原数据f_3M%调用f_3M文件signal=transpose(ROMOUT); %矩阵转置:将列矩阵转置成行矩阵fs=50E6; %采样频率N=1024; %采样点数t=[0:1/fs:(N-1)/fs]; %采样时刻figure(1);subplot(2,2,1);plot(t,signal);title({'3M-未补零-原数据长度 ';'时域波形图'});xlabel('Time (s)');ylabel('Magnitude');Y = fft(signal,N); %做FFT变换Ayy = abs(Y); %取模Ayy=Ayy/(N/2); %换算成实际的幅度Ayy(1)=Ayy(1)/2;F=([1:N]-1)*fs/N; %换算成实际的频率值,Fn=(n-1)*Fs/Nfigure(1);subplot(2,2,3);stem(F(1:N/2),Ayy(1:N/2)); %显示换算后的FFT模值结果axis([0 5E6 0 2500]);title('幅度-频率曲线图');xlabel('Frequency (Hz)');ylabel('Magnitude');%%选频3MHz,不补零,半数数据f_3M_test %调用f_3M_test文件signal=transpose(ROMOUT); %矩阵转置:将列矩阵转置成行矩阵fs=50E6; %采样频率N=512; %采样点数t=[0:1/fs:(N-1)/fs]; %采样时刻figure(1);subplot(2,2,2);plot(t,signal);title({'3M-未补零-半原数据长度';'时域波形图'});xlabel('Time (s)');ylabel('Magnitude');Y = fft(signal,N); %做FFT变换Ayy = abs(Y); %取模Ayy=Ayy/(N/2); %换算成实际的幅度Ayy(1)=Ayy(1)/2;F=([1:N]-1)*fs/N; %换算成实际的频率值,Fn=(n-1)*Fs/Nfigure(1);subplot(2,2,4);stem(F(1:N/2),Ayy(1:N/2)); %显示换算后的FFT模值结果axis([0 5E6 0 2500]);title('幅度-频率曲线图');xlabel('Frequency (Hz)');ylabel('Magnitude');%%选频3MHz,补零,原数据f_3M; %调用f_3M文件signal=transpose(ROMOUT); %矩阵转置:将列矩阵转置成行矩阵b=zeros(1,1024);signal=[b,signal,b]; %补零,改善频谱fs=50E6; %采样频率N=1024*3; %采样点数Nv=1024; %有效采样点数t=[0:1/fs:(N-1)/fs]; %采样时刻figure(2);subplot(2,2,1);plot(t,signal);title({'3M-补零-原数据长度';'时域波形图'});xlabel('Time (s)');ylabel('Magnitude');Y = fft(signal,N); %做FFT变换Ayy = abs(Y); %取模Ayy=Ayy/(Nv/2); %换算成实际的幅度Ayy(1)=Ayy(1)/2;F=([1:N]-1)*fs/N; %换算成实际的频率值,Fn=(n-1)*Fs/Nfigure(2);subplot(2,2,3);stem(F(1:N/2),Ayy(1:N/2)); %显示换算后的FFT模值结果axis([0 5E6 0 2500]);title('幅度-频率曲线图');xlabel('Frequency (Hz)');ylabel('Magnitude');%%选频3MHz,补零,半数数据f_3M_test; %调用f_3M_test文件signal=transpose(ROMOUT); %矩阵转置:将列矩阵转置成行矩阵b=zeros(1,512);signal=[b,signal,b]; %补零,改善频谱fs=50E6; %采样频率N=512*3; %采样点数Nv=512; %有效采样点数t=[0:1/fs:(N-1)/fs]; %采样时刻figure(2);subplot(2,2,2);plot(t,signal);title({'3M-补零-半数据长度';'时域波形图'});xlabel('Time (s)');ylabel('Magnitude');Y = fft(signal,N); %做FFT变换Ayy = abs(Y); %取模Ayy=Ayy/(Nv/2); %换算成实际的幅度Ayy(1)=Ayy(1)/2;F=([1:N]-1)*fs/N; %换算成实际的频率值,Fn=(n-1)*Fs/Nfigure(2);subplot(2,2,4);stem(F(1:N/2),Ayy(1:N/2)); %显示换算后的FFT模值结果axis([0 5E6 0 2500]);title('幅度-频率曲线图');xlabel('Frequency (Hz)');ylabel('Magnitude');
0 0
- dds
- DDS
- dds
- DDS
- DDS
- DDS 文件
- DDS 文件格式
- RTI DDS
- 关于DDS
- DDS程序
- DDS格式
- dds纹理
- DDS文件格式
- DDS作业
- DDS作业
- Vivado DDS
- DDS File Reference DDS的档案编号
- DDS File Reference DDS的档案编号
- 使用 Hibernate 在 JPA 中 调用 generateSchema 会出现执行两次 SQL 语句问题的解决方法
- 关闭手机软键盘代码
- web服务端 缓存技术总结
- android BLE蓝牙开发
- 【外包服务】广州深圳APP、微信开发外包,物美价廉真的有!
- DDS
- 如何用两个栈来实现队列的方法
- service中的方法可以互相调用吗?-事物传播
- bootstrap-datetimepicker添加支持显示农历节假日信息。
- 前端开发人员2017年学习什么
- iframe使用问题
- 《视频直播技术详解》系列之一:开篇
- ios调起微信客户端失败 微信支付调起失败
- 论网站体验之必备--稳定的服务器