HDL-实验(3):DDS作业

来源:互联网 发布:pl sql scott登录不了 编辑:程序博客网 时间:2024/05/16 08:39

1.人工绘制的 电路结构RTL设计图

这里写图片描述
DDS 具体工作过程如下:每来一个时钟脉冲CLK,N位全加器将频率控制字FQWD与累加寄存器输出的累加相位数据N相加,把相加后的结果送至累加寄存器的输入端。累加寄存器一方面将上一时钟周期作用后所产生的新的数据反馈到加法器的输入端,以使加法器在下一时钟的作用下继续与频率控制数字相加;另一方面将这个值作为取样地址值送入幅度/相位转换电路,此电路根据取样地址输出相应的波形数据。最后经D/A 转换器和低通滤波器将波形数据转换成所需要的模拟波形。
DDS的工作原理:在本次实验中一共用了4个拨码开关SW[3..0],其中拨码开关SW[3]用于频率控制时能,SW[2..0]用于产生不同的频率控制字,根据输出频率公式:f=(Mfc2N),已知相位累加器的位数N=10,故要输出某一确定频率即调整频率控制字M的大小即可。

2.Quartus扫描生成的电路RTL图

这里写图片描述
(1)generate_freq_word模块的RTL结构图:
这里写图片描述
(2)phase_accumulator模块的RTL结构图:
这里写图片描述
(3)DDS_CORE_ROM模块的RTL结构图:
这里写图片描述

3.相位累加器的输出,SignalTap截图

(1)当频率控制字:FQWD=10

此时一个完整的正弦波周期采样102个点,在50MHZ的晶振脉冲下,采样一个点的时间为0.02s,故当频率控制字为10时,输出正弦波的频率约为:f=(11020.02)500KHZ

相位累加器的输出:

这里写图片描述
波表ROM的输入地址
输出正弦波的样值波形如下:
这里写图片描述

(2)当频率控制字:FQWD=20

此时一个完整的正弦波周期采样51个点,在50MHZ的晶振脉冲下,采样一个点的时间为0.02s,故当频率控制字为20时,输出正弦波的频率约为:f=(1510.02)1MHZ

相位累加器的输出波表ROM的输入地址输出正弦波的样值波形如下:

这里写图片描述
####(3)当频率控制字:FQWD=60
此时一个完整的正弦波周期采样17个点,在50MHZ的晶振脉冲下,采样一个点的时间为0.02s,故当频率控制字为60时,输出正弦波的频率约为:f=(1170.02)3MHZ

相位累加器的输出波表ROM的输入地址输出正弦波的样值波形如下:

这里写图片描述

6.Verilog代码

//***********************************************************************//生成频率控制字模块module generate_freq_word(  CLK   ,   // 时钟信号  FQIN,//用于生成频率字的输入信号   EN,//频率控制时能,高有效  CNT  ); //输出值,即生成的频率字 input CLK;input [2:0] FQIN;input EN;output [31:0] CNT;reg [31:0] CNT;always @ (FQIN) begin   if(EN) begin        case(FQIN)            3'b001: CNT <= 32'd10;//用第1个拨码开关用于生成频率控制字10            3'b010: CNT <= 32'd20;//用第2个拨码开关用于生成频率控制字20             3'b100: CNT <= 32'd60;//用第3个拨码开关用于生成频率控制字60         endcase    endendendmodule//***********************************************************************//相位累加器模块module phase_accumulator(  CLK       ,   //时钟信号  FQWD      ,   // 输出频率控制字  FWEN      ,//频率控制时能,高有效  CNTVAL  );  // 累加值input CLK;       input [31:0] FQWD; //频率字字长32位     input FWEN;output [9:0] CNTVAL;     reg [9:0] CNTVAL;always @ (posedge CLK) begin   if(FWEN)      CNTVAL <= FQWD + CNTVAL;    else       CNTVAL <= CNTVAL;end endmodule   

Matlab代码

说明:老师,由于Matlab基础较差,所以短时间内写出这段代码真的很有难度,所以借鉴了您的,但是一直在学习Matlab中,还希望您能谅解!

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(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()

波表ROM代码

注:波表ROM代码是用matlab生成的

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       ......        default : RD = #1 0;  endcaseendmodule 

7.Matlab 正弦波信号频谱分析

(1)当输出频率为500KHZ时

signal_tap_data_500KHZ.m文件

signal_out=[ 852    , 964   , 1073 , 1178 , 1279  , 1374   , 1465  , 1550 , 1629  , 1702 , 1768  , 1828  , 1881  , 1927  , ... ... ];
500KHZ频谱图matlab代码
 clear;signal_tap_data_500KHZ;fs=50E6; %采样频率N=1024; %采样点数t=[0:1/fs:(N-1)/fs]; %采样时刻xlabel('Time (s)');ylabel('Magnitude(dB)');signal=transpose(signal_out); %矩阵转置 y=fft(signal,N);%对信号进行傅里叶变换yy=abs(y);     %求得傅里叶变换后的振幅yy=yy/(N/2); %换算成实际的幅度figure(1);plot(t,signal);F=([1:N]-1)*fs/N; %换算成实际的频率值,Fn=(n-1)*Fs/Nfigure(2);stem(F(1:N/2),yy(1:N/2)); %显示换算后的FFT模值结果axis([0 5E6 0 2500]);title('幅度-频率曲线图');xlabel('Frequency (Hz)');ylabel('Magnitude');
500KHZ频谱图:

这里写图片描述
这里写图片描述

1MHZ频谱图:

这里写图片描述
这里写图片描述

3MHZ频谱图:

这里写图片描述
这里写图片描述

0 0
原创粉丝点击