探索EDA工具
来源:互联网 发布:交付软件需提供 编辑:程序博客网 时间:2024/05/16 13:58
在FPGA上设计一个DDS模块,在DE0 开发板上运行,在FPGA芯片内部合成出数字波形即可。不用输出模拟信号,本模块满足以下条件
- 使用板载晶振的50MHz时钟,合成以下频率的信号
- 1MHz 正弦波信号。
- 频率字字长32位,波表ROM尺寸为 10比特地址,1024个word。
- 波形格式为2补码格式,12比特量化。
- 每个CLK输出一个有效样点。
- 输入信号为频率字和频率字输入使能信号。
- 使用板载的拨码开关(Switch)控制生成的波形信号的不同频率。
注意:波表ROM代码是用matlab或C打印生成的。不要手写。
Signaltap 和 Matlab
- 思考题
- 如何用 Matlab分析该正弦信号的频率
- 上面你用的分析方法,其频率分析精度是多少?这个分析精度和那些参数有关系?
- 如何能验证你的频率分析方法是正确的?我的意思是,假设你要生成1MHz的正弦波,但是实际上,你生成的正弦波的频率是错的,并且你的Matlab分析方法也不对,在这种情况下,即使你生成了正确频率的正弦波,你的分析方法也会告诉你频率不对。
ModelSim 和 Matlab
建议设计如下
- 在许多大型设计中,进行Quartus编译和FPGA电路下载是电路设计流程中比较后期的事情。
- 进行电路编译之前,首先会进行HDL仿真,常用的工具是Modelsim。
- DDS电路是非常利于Modelsim仿真的设计,因为它只需要一个CLK信号和一个RST信号
- 请把你的DDS电路用ModelSim仿真一下, 首先在观察信号的输出波形,然后将输出数据导出到文本文件中
- 用Matlab从文本文件中读入你的DDS波形
- 再次分析你的波形频率
手绘RTL图
Quartus扫描 RTL图
SignalTap截图
- 相位累加器输出
- 波表ROM的输入地址
- 输出正弦波形图
SW1=10时,选频1MHz
–将SignalTapII抓取的ROMOUT值导出(Create SignalTapII List File),以便后续使用UltraEditor的列模式处理数据。
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()
matlab波形分析
- 使用matlab进行波形,首先得验证我们使用的方法是否正确,所以我们先用matlab产生一个频率为1MHz的,来测试我们用以进行波形分析的代码!
clear;Fs=2E7;F=1E6;N=60;n=0:N-1;t=n/Fs;x=sin(2*pi*F*t);y=fft(x,N);y_abs=abs(y);y1=abs(20*log10(y_abs));y2=20*log10(y_abs);f=(0:N-1)*Fs/N;subplot(2,2,1:2),stem(t,x);subplot(2,2,3),stem(f(1:N/2),y_abs(1:N/2));subplot(2,2,4),stem(f(1:N/2),y2(1:N/2));
- 正弦信号的频率为1MHz,采样频率为20MHz,60/(20/1)=3个整周期的采样点。
频谱图和增益图满足工程需求(噪声被压制在-300dB以下),所以可以用此方法进行后续的波形分析。
将FPGA导出的数据导入到matlab中进行波形分析:
clc;clear;f_1Mx=transpose(ROMOUT)/512;Fs=50E6;F=1E6;N=1024;n=0:N-1;t=n;% x=sin(2*pi*F*t);y=fftshift(fft(x,N));y_abs=abs(y);y1=20*log10(y_abs);%y2=20*log10(y_abs);% f=(0:N-1)*Fs/N;f=linspace(-(Fs/2),(Fs/2),N);subplot(4,4,1:4),plot(t,x);title('Sine Signal', 'fontsize',14); grid on; %添加网格线title('Sampled Sine Signal(Partially displayed)', 'fontsize',14); %改变标题字体的大小至14subplot(4,4,5:8);stem(x);xlim([100,200]);grid on; %添加网格线title('Sampled Sine Signal(Partially displayed)', 'fontsize',14); %改变标题字体的大小至14subplot(4,4,9:12),plot(f,y_abs);grid on; title('DFT Amplitude in Linear scale', 'fontsize',14);xlabel('Frequency(Hz)'); ylabel('Magnitude');subplot(4,4,13:16),plot(f,y1);grid on;title('DFT Amplitude in dB scale','fontsize',14);xlabel('Frequency(Hz)'); ylabel('Magnitude(dB)');
- 波形图
FPGA的时钟为50MHz,所以输出的点为采样频率为50MHz采集出来的。假设输出频率为1MHz,则matlab波形应该显示1024/(50/1)=20.48个周期采样点,频谱图应为两根分别在-1MHz和1MHz两个竖线。但实际频谱图不是两根笔直的谱线,出现了频谱泄漏,这是由于采样点数不为整周期采样点数造成的。
改善测试方法:1.将采样点数选为整数个周期点数。2。加窗来改善频谱泄漏。
- 将采样点数选为1000个点
clc;clear;f_1M_testx1=transpose(ROMOUT)/5120;%kaiser_Beta=0.5;Fs=50E6;F=1E6;N=1000;%win=kaiser(N,kaiser_Beta);%x1=x'.*win;n=0:N-1;t=n;% x=sin(2*pi*F*t);y=fftshift(fft(x1,N));y_abs=abs(y);y1=20*log10(y_abs);%y2=20*log10(y_abs);% f=(0:N-1)*Fs/N;f=linspace(-(Fs/2),(Fs/2),N);subplot(4,4,1:4),plot(t,x1);title('Sine Signal', 'fontsize',14); grid on; %添加网格线title('Sampled Sine Signal(Partially displayed)', 'fontsize',14); %改变标题字体的大小至14subplot(4,4,5:8);stem(x1);xlim([100,200]);grid on; %添加网格线title('Sampled Sine Signal(Partially displayed)', 'fontsize',14); %改变标题字体的大小至14subplot(4,4,9:12),plot(f,y_abs);grid on; title('DFT Amplitude in Linear scale', 'fontsize',14);xlabel('Frequency(Hz)'); ylabel('Magnitude');subplot(4,4,13:16),stem(f,y1);grid on;title('DFT Amplitude in dB scale','fontsize',14);xlabel('Frequency(Hz)'); ylabel('Magnitude(dB)');
– –波形非常好,基本上为两条笔直的谱线,但还是有一些噪声,这是由于DDS算法造成的误差。
- 加凯泽窗
clc;clear;f_1Mx=transpose(ROMOUT)/5120;kaiser_Beta=10;Fs=50E6;F=1E6;N=1000;win=kaiser(N,kaiser_Beta);x1=x'.*win;n=0:N-1;t=n;% x=sin(2*pi*F*t);y=fftshift(fft(x1,N));y_abs=abs(y);y1=20*log10(y_abs);%y2=20*log10(y_abs);% f=(0:N-1)*Fs/N;f=linspace(-(Fs/2),(Fs/2),N);subplot(4,4,1:4),plot(t,x1);title('Sine Signal', 'fontsize',14); grid on; %添加网格线title('Sampled Sine Signal(Partially displayed)', 'fontsize',14); %改变标题字体的大小至14subplot(4,4,5:8);stem(x1);xlim([100,200]);grid on; %添加网格线title('Sampled Sine Signal(Partially displayed)', 'fontsize',14); %改变标题字体的大小至14subplot(4,4,9:12),plot(f,y_abs);grid on; title('DFT Amplitude in Linear scale', 'fontsize',14);xlabel('Frequency(Hz)'); ylabel('Magnitude');subplot(4,4,13:16),stem(f,y1);grid on;title('DFT Amplitude in dB scale','fontsize',14);xlabel('Frequency(Hz)'); ylabel('Magnitude(dB)');
– –加上凯泽窗后,频谱泄漏的情况得到了改善,频域分辨率提高,看到了更多的频率细节。
总结:虽然对整数个周期样点进行matlab分析,能得到更真实的波形,但工程上,并不能保证我们采集的样点点数都满足整数个周期,我们通常都选取加入合适的窗函数来对实验数据进行观测。
阅读全文
0 0
- 探索EDA工具
- 探索 DDS 和 EDA 工具
- EDA工具
- 探索性数据分析(EDA)
- 常用EDA工具简介
- 开源EDA工具
- 开源EDA工具
- EDA工具使用教程链接
- 硬件开发的EDA工具
- EDA
- EDA?
- [转贴]IC设计流程和EDA工具
- 转:多种EDA工具的FPGA协同设计
- ic设计前端到后端的流程和eda工具?
- FPGA的EDA工具常见报错分析
- IC设计前端到后端的流程和eda工具。
- Linux awk 工具探索
- 自我探索工具
- mysql中的if函数小总
- python之SMTP邮件的发送与接收
- DateTime.Compare(t1,t2)比较两个日期大小
- Linux平台音频测试程序
- Unity3D游戏开发之虚拟现实项目开发流程
- 探索EDA工具
- Intent那些事
- JSON与MAP之间的转换
- spring请求中数据绑定到控制器的方式探究
- Yum命令
- Python2中的urllib、urllib2与Python3中的urllib以及第三方模块requests
- TFS使用心得
- 百度开发者中心资讯发布:百度云BCC/RDS正式支持Windows Server 2016与SQL Server 2016
- AOJ.883 rexp