DDS

作业要求

在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,           //ENABLE
freq_in,
freq_out);
parameter VAL_FREQ_500K = 32'h028F_5C29;//32'd42949673
input         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
 end
endmodule

 - 相位累加器模块

module dds_core(
  CLK   ,   // CLOCK 
  INCR  ,   // INCREASE  VALUE 
  TEMP  ,   // TEMPORARY VALUE
  COUT);    // COUNTER   VALUE
input             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];

end

endmodule   // 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 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 
     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;
  endcase
endmodule     

MATLAB代码

  • ROM生成代码

此处特别鸣谢代码原创者杜老师

function generate_DDS_rom()
clc;
close all;
disp('##########################################');
disp('# generate_DDS_rom() RUN');
disp('##########################################');

%%///
%   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;
index = [0:rom_vec_len-1] .';
rom_data_vec_float = sin(2*pi*index/rom_vec_len);
figure; plot(rom_data_vec_float);    % for debug
rom_data_vec_int = fix(rom_data_vec_float * (2^(rom_word_len-1) - 1));
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(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()
  • 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/N
figure(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/N
figure(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/N
figure(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/N
figure(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');
深度学习是机器学习的一个子领域,它基于人工神经网络的研究,特别是利用多层次的神经网络来进行学习和模式识别。深度学习模型能够学习数据的高层次特征,这些特征对于图像和语音识别、自然语言处理、医学图像分析等应用至关重要。以下是深度学习的一些关键概念和组成部分: 1. **神经网络(Neural Networks)**:深度学习的基础是人工神经网络,它是由多个层组成的网络结构,包括输入层、隐藏层和输出层。每个层由多个神经元组成,神经元之间通过权重连接。 2. **前馈神经网络(Feedforward Neural Networks)**:这是最常见的神经网络类型,信息从输入层流向隐藏层,最终到达输出层。 3. **卷积神经网络(Convolutional Neural Networks, CNNs)**:这种网络特别适合处理具有网格结构的数据,如图像。它们使用卷积层来提取图像的特征。 4. **循环神经网络(Recurrent Neural Networks, RNNs)**:这种网络能够处理序列数据,如时间序列或自然语言,因为它们具有记忆功能,能够捕捉数据中的时间依赖性。 5. **长短期记忆网络(Long Short-Term Memory, LSTM)**:LSTM 是一种特殊的 RNN,它能够学习长期依赖关系,非常适合复杂的序列预测任务。 6. **生成对抗网络(Generative Adversarial Networks, GANs)**:由两个网络组成,一个生成器和一个判别器,它们相互竞争,生成器生成数据,判别器评估数据的真实性。 7. **深度学习框架**:如 TensorFlow、Keras、PyTorch 等,这些框架提供了构建、训练和部署深度学习模型的工具和库。 8. **激活函数(Activation Functions)**:如 ReLU、Sigmoid、Tanh 等,它们在神经网络中用于添加非线性,使得网络能够学习复杂的函数。 9. **损失函数(Loss Functions)**:用于评估模型的预测与真实值之间的差异,常见的损失函数包括均方误差(MSE)、交叉熵(Cross-Entropy)等。 10. **优化算法(Optimization Algorithms)**:如梯度下降(Gradient Descent)、随机梯度下降(SGD)、Adam 等,用于更新网络权重,以最小化损失函数。 11. **正则化(Regularization)**:技术如 Dropout、L1/L2 正则化等,用于防止模型过拟合。 12. **迁移学习(Transfer Learning)**:利用在一个任务上训练好的模型来提高另一个相关任务的性能。 深度学习在许多领域都取得了显著的成就,但它也面临着一些挑战,如对大量数据的依赖、模型的解释性差、计算资源消耗大等。研究人员正在不断探索新的方法来解决这些问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值