Verilog HDL DDS设计(作业3)
2016-12-19 23:00
519 查看
实验内容
在FPGA上设计一个DDS模块,在DE0 开发板上运行,在FPGA芯片内部合成出数字波形即可。不用输出模拟信号,本模块满足以下条件:使用板载晶振的50MHz时钟,合成以下频率的信号
1、500KHz 正弦波信号。 2、1MHz 正弦波信号。 3、3MHz 正弦波信号。
频率字字长32位,波表ROM尺寸为 10比特地址,1024个word
波形格式为2补码格式,12比特量化
每个CLK输出一个有效样点。
输入信号为频率字和频率字输入使能信号
使用板载的拨码开关(Switch)控制生成的波形信号的不同频率。
注:波表ROM代码是用matlab或C打印生成的。不要手写
实验要求
人工绘制的 电路结构RTL设计图,该图片用于说明你设计电路时的想法,注意要在RTL图中画出Verilog代码中的 生成D触发器 reg 变量Quartus扫描生成的电路RTL图,该图片用于说明Quartus的电路编译结果
相位累加器的输出,SignalTap截图
波表ROM的输入地址,SignalTap截图
至少捕获 一个完整的输出正弦波形周期的上述数据数值的SignalTap截图。
输出正弦波的样值波形,SignalTap截图
提交Verilog、相关MATLAB 代码,请使用博客中提供的代码块功能
分析输出的正弦波信号的频谱,Matlab 截图
Visio绘制的RTL
Quartus扫描生成的RTL
顶层RTLSwitchRTL
dds_core RTL
RAM RTL
SignalTap截图
频率控制字FQWD=10:注:此时正弦波一个周期采样102个点,50MHz下采样周期0.02us,输出正弦波频率约为 f=1102∗0.02≈0.5(MHz)。
频率控制字FQWD=20:
注:此时正弦波一个周期采样52个点,50MHz下采样周期0.02us,输出正弦波频率约为 f=152∗0.02≈1(MHz)。
频率控制字FQWD=40:
注:此时正弦波一个周期采样26个点,50MHz下采样周期0.02us,输出正弦波频率约为 f=126∗0.02≈2(MHz)。
频率控制字FQWD=60:
注:此时正弦波一个周期采样17个点,50MHz下采样周期0.02us,输出正弦波频率约为 f=117∗0.02≈3(MHz)。
matlab频谱分析
将SignalTap中的波形数据抓出来,放进matlab里面进行分析,并绘制频谱图500KHz
1MHz
3MHz
补零后~
3MHz代码
1. 基础模块代码(Verilog)
module switch_freq_word( CLK , //输入时钟 SWCHIN , //输入拨码开关控制字 FQWD , //输出频率字,作为dds_core的递增累加值 FWEN ); //输出频率字的更新使能,为1时才能更新频率字 parameter VAL_FREQ_BASE = 6'd10; // 50MHz clock, 500kHz out wave freqword value input CLK,FWEN; input [2:0] SWCHIN; //使用3位拨码开关控制8种频率字的选择,最低500kHz,最高3MHz output reg[31:0] FQWD; //用来存放VAL_FREQ_BASE以及它的倍数 //output reg FWEN; always @(posedge CLK) begin if (FWEN) begin case(SWCHIN) 3'd0: FQWD <= VAL_FREQ_BASE; //500kHz e657 3'd1: FQWD <= VAL_FREQ_BASE * 2; 3'd2: FQWD <= VAL_FREQ_BASE * 3; 3'd3: FQWD <= VAL_FREQ_BASE * 4; 3'd4: FQWD <= VAL_FREQ_BASE * 5; 3'd5: FQWD <= VAL_FREQ_BASE * 6;//3MHz default: FQWD <= VAL_FREQ_BASE; endcase end else begin FQWD <= #1 FQWD; end // FQWD <= VAL_FREQ_BASE * SWCHIN; end endmodule /********************************************* 带计数增量的计数器 输入:CLK时钟信号、INCR递增累加值 输出:SINOUT计数值 功能:SINOUT作为输出地址,对ROM表进行提取,地址为 多少就提取出相应的ROM值进行输出 *********************************************/ module dds_core( CLK , // clock INCR , // 计数增量 SINOUT); // counter value input CLK; input [31:0] INCR; output reg[9:0] SINOUT; always @ (posedge CLK) begin SINOUT <= INCR + SINOUT; end endmodule // module dds_core
2. DDS ROM表代码(Verilog)
此波表ROM代码是用matlab或C打印生成的(略写)module DDS_CORE_ROM( CLK , // clock RA , // read address RD ); // read data input 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 ...... default : RD = #1 0; endcase endmodule
3. DDS ROM表生成代码(MATLAB)
此代码原作者为杜伟韬老师,在此向大神杜伟韬老师表示真挚的敬意function generate_DDS_rom() clc; close all; disp('# generate_DDS_rom() Running~'); %%/////////////////////////////////////////////////// % set your rom config here rom_word_len = 12; % rom data word length in bit rom_addr_len = 10; % rom address word length in bit rom_file_name = 'DDS_CORE_ROM.v'; % rom file name rom_file_dir = './'; % rom file dir path description = 'DDS CORE ROM FILE' ;% rom description %%/////////////////////////////////////////////////// rom_vec_len = 2^rom_addr_len; %2^10=1024 index = (0:rom_vec_len-1) ; %0~1023 rom_data_vec_float = sin(2*pi*index/rom_vec_len); %最大值为1的1024点正弦波 figure; plot(rom_data_vec_float); % for debug rom_data_vec_int = fix(rom_data_vec_float * (2^(rom_word_len-1) - 1)); %最大值为2047,为了保证最高位为符号位 figure; plot(rom_data_vec_int); % for debug rom_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 format function 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(strcmp(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)); end end % function Dec2BinStr()
注:这是个函数,在matlab里面键入函数名字即可运行生成ROM文件
4. SignalTap波形频谱分析(MATLAB)
此代码根据SignalTap生成波形的数据(鼠标右击波形名字-Create SignalTapII List File),绘制频谱图(需要对文件进行修改,只保留所需数据列)以下以3MHz时为例:(略写)
signal_tap_data_3M.m文件
signal_out=[ -2044 , -1943 , -1582 , -1008 , -300 , 448 , 1137 , 1673 , ... ... ];
调用数据并绘图
clear; signal_tap_data_3M; signal=transpose(signal_out); %矩阵转置 fs=50E6; %采样频率 N=1024; %采样点数 t=[0:1/fs:(N-1)/fs]; %采样时刻 figure(1);plot(t,signal); 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/N figure(2); stem(F(1:N/2),Ayy(1:N/2)); %显示换算后的FFT模值结果 axis([0 5E6 0 2500]); title('幅度-频率曲线图'); xlabel('Frequency (Hz)'); ylabel('Magnitude');
带有补零的绘图代码
clear; signal_tap_data_3M; signal=transpose(signal_out); %矩阵转置 b=zeros(1,1024); signal=[b,signal,b]; %补零,改善频谱 fs=50E6; %采样频率 N=1024*3; %采样点数 Nv=1024; %有效数据点数 t=[0:1/fs:(N-1)/fs]; %采样时刻 figure(1);plot(t,signal); 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/N figure(2); plot(F(1:N/2),Ayy(1:N/2)); %显示换算后的FFT模值结果 axis([0 5E6 0 2500]); title('幅度-频率曲线图'); xlabel('Frequency (Hz)'); ylabel('Magnitude');
相关文章推荐
- Verilog HDL DDS设计(作业3)
- Verilog HDL计数器设计(作业1)
- Verilog HDL计数器设计(作业1)
- Verilog HDL设计规范及经验谈(转载)
- hjr-FPGA:verilog HDL 编程与 testbench 设计
- (笔记)Verilog HDL设计时关于阻塞赋值和非阻塞赋值的8条指导原则以及原因。
- Verilog HDL && Quartus 设计规范、代码风格
- FPGA作业二——verilog设计
- verilogHDL设计中的同步时序逻辑
- Verilog HDL计数器组合电路(作业2)
- 【续】FPGA电路逻辑的Verilog HDL编程方式设计与验证
- Verilog HDL计数器组合电路(作业2)
- Verilog HDL 有限状态机的设计
- verilog HDL 的阻塞和非阻塞语句在FPGA各种设计中的分析
- Verilog HDL 典型组合逻辑电路设计
- Verilog HDL 与数字电路设计
- VerilogHDL可综合设计的注意事项
- 项目软件过程的迭代设计作业(案例设计)
- 可能学VHDL比VerilogHDL好吧?
- 用Quartus II + Verilog 做FPGA/CPLD设计/仿真的几个基本问题(自己总结的,对初学者有效)