探索 DDS 和 EDA 工具

来源:互联网 发布:淘宝装修软件破解版 编辑:程序博客网 时间:2024/05/16 11:36

1、Signal Tap 和 Matlab


1.1 signal tap

  • 合成500kHz的正弦波,其signaltap图如下:

  • signaltap


1.2 Matlab分析

1.2.1 测试代码

  • 首先写出一个测试代码:生成一个频率为1kHz的正弦波,用该测试代码分析其频谱是否正确,若正确,则可以用来分析DDS生成的正弦波。

  • 代码如下:test_1kHz.m

%/////////////////////////////////////////////////////////////////////////////////////////////////////////% function : %           draw 1kHz sine signal%           DFT analyse%/////////////////////////////////////////////////////////////////////////////////////////////////////////N   = 64                ; % vector lengthidx = [0:N-1].'         ; % index column vectorf0 = 1E3                ; % sine signal freq, in Hzfs = 32E3               ; % sample rate, in Hzx1 = sin(2*pi*f0/fs*idx); % sampled sine signalmax_abs_x = max(abs(x1));% normalize x to (-1,1)x1 = x1 / max_abs_x;figure                  ; % open new figuresubplot(2,2,1:2)        ;set(gca,'fontsize',14)  ;stem(x1)                ; % plot(x1)grid on                 ; % draw grid on figuretitle1_str = sprintf(...  'Sampled Sine Signal, Frequency %dHz, Sample rate %dHz', f0, fs);title(title1_str, 'fontsize',14);axis([0 N 1.1*min(x1) 1.1*max(x1)]);%设定坐标轴范围xlabel('n');ylabel('Magnitude');y1     = fft(x1)        ;% shift zero frequency to the data center% fftshift的作用正是让正半轴部分和负半轴部分的图像分别关于各自的中心对称。% 因为直接用fft得出的数据与频率不是对应的,fftshift可以纠正过来y1     = fftshift(y1)   ;y1_abs = abs(y1)        ;%idx_f = linspace(-(fs/2),(fs/2), N);idx_f = (-length(y1)/2: length(y1)/2-1)'*fs/length(y1);%频率轴subplot(2,2,3); stem(idx_f,y1_abs,'LineWidth',1,'MarkerSize',6)   ;xlim([-(fs/2) (fs/2)]);%设定x坐标轴范围grid on; set(gca,'fontsize',12)                             ;title('DFT Amplitude in Linear scale', 'fontsize',14)       ;xlabel('Frequency/Hz');ylabel('Magnitude');y1_abs_dB = 20*log10(y1_abs)    ;min_y1 = min(y1_abs_dB)         ;subplot(2,2,4)                  ; stem(idx_f,y1_abs_dB, 'LineWidth',1,'MarkerSize',6,'BaseValue',min_y1); xlim([-(fs/2) (fs/2)]);%设定x坐标轴范围grid on; set(gca,'fontsize',12)                     ;title('DFT Amplitude in dB scale', 'fontsize',14)   ;xlabel('Frequency/Hz');ylabel('Magnitude/dB');
  • 运行之后的图片如下:
  • test_1kHz
  • 由图可知可以用此代码分析频谱。

1.2.2 分析 DDS 生成的正弦信号频率

  • Signaltap的数据导入到Matlab,分析频域结果

  • 选中signal tap里的SINOUT行-右键-create signal tapⅡ list file,将该文件中的代码放到sublime中,shift+右键选中SINOUT一列的数据,放到SINOUT_500k.m文件的数组中,该文件包含一个数组,可用来调用。

  • 分析其频域结果的代码如下:FFT_500k.m
clear;SINOUT_500k; %调用SINOUT_500k.m文件x=transpose(SINOUT); %矩阵转置max_abs_x = max(abs(x));% normalize x to (-1,1)x = x / max_abs_x;N   = 1024                ; % vector lengthidx = [0:N-1].'         ; % index column vectorf0 = 500E3              ; % sine signal freq, in Hzfs = 50E6               ; % sample rate, in Hzfigure                  ; % open new figuresubplot(3,1,1)        ;set(gca,'fontsize',14)  ;plot(x)            ; % plot(x)grid on                 ; % draw grid on figuretitle1_str = sprintf(...  'Sine Signal, Frequency %dkHz, Sample rate %dMHz', f0/1E3, fs/1E6);title(title1_str, 'fontsize',14);axis([0 N 1.1*min(x) 1.1*max(x)]);%设定坐标轴范围xlabel('n');ylabel('Magnitude');y1     = fft(x)        ;% shift zero frequency to the data center% fftshift的作用正是让正半轴部分和负半轴部分的图像分别关于各自的中心对称。% 因为直接用fft得出的数据与频率不是对应的,fftshift可以纠正过来y1     = fftshift(y1)   ;y1_abs = abs(y1)        ;idx_f = (-length(y1)/2: length(y1)/2-1)'*fs/length(y1);%频率轴subplot(3,1,2); plot(idx_f,y1_abs,'LineWidth',1,'MarkerSize',6)   ;xlim([-(fs/2) (fs/2)]);%设定x坐标轴范围grid on; set(gca,'fontsize',12)                             ;title('DFT Amplitude in Linear scale', 'fontsize',14)       ;xlabel('Frequency/Hz');ylabel('Magnitude');y1_abs_dB = 20*log10(y1_abs)    ;min_y1 = min(y1_abs_dB)         ;subplot(3,1,3)                  ; plot(idx_f,y1_abs_dB, 'LineWidth',1,'MarkerSize',6); axis([-(fs/2) (fs/2) -10 60]);%设定坐标轴范围grid on; set(gca,'fontsize',12)                     ;title('DFT Amplitude in dB scale', 'fontsize',14)   ;xlabel('Frequency/Hz');ylabel('Magnitude/dB');
  • 频谱图如下:
  • 500k_1024
  • 频率分辨率为:fs / N = 50M / 1024 , 降低采样频率和增大采样数据的点数都可以提高频率分辨率。

1.2.3 给信号加Kaiser窗

  • 代码:FFT_kaiser_500k.m
clear;SINOUT_500k; %调用SINOUT_500k.m文件x = reshape(SINOUT , 1024, 1);max_abs_x = max(abs(x));% normalize x to (-1,1)x = x / max_abs_x;N   = 1024              ; % vector lengthidx = [0:N-1].'         ; % index column vectorf0 = 500E3              ; % sine signal freq, in Hzfs = 50E6               ; % sample rate, in Hz% get window function datakaiser_beta = 10         ;  % beta of kaiser winwin = kaiser(N,kaiser_beta);win_x       =  win .* x;figure                  ; % open new figuresubplot(3,1,1)          ;set(gca,'fontsize',14)  ;plot(win_x)                 ; % plot(x)grid on                 ; % draw grid on figuretitle1_str = sprintf(...  'Sine Signal, Frequency %dkHz, Sample rate %dMHz, Kaiser window,β=%d', f0/1E3, fs/1E6, kaiser_beta);title(title1_str, 'fontsize',14);axis([0 N 1.1*min(win_x) 1.1*max(win_x)]);%设定坐标轴范围xlabel('n');ylabel('Magnitude');y1     = fft(win_x)        ;% shift zero frequency to the data center% fftshift的作用正是让正半轴部分和负半轴部分的图像分别关于各自的中心对称。% 因为直接用fft得出的数据与频率不是对应的,fftshift可以纠正过来y1     = fftshift(y1)   ;y1_abs = abs(y1)        ;idx_f = (-length(y1)/2: length(y1)/2-1)'*fs/length(y1);%频率轴subplot(3,1,2); plot(idx_f,y1_abs,'LineWidth',1,'MarkerSize',6)   ;xlim([-(fs/2) (fs/2)]);%设定x坐标轴范围grid on; set(gca,'fontsize',12)                             ;title1_str = sprintf(...  'DFT Amplitude in Linear scale, Kaiser window,β=%d', kaiser_beta);title(title1_str, 'fontsize',14);xlabel('Frequency/Hz');ylabel('Magnitude');y1_abs_dB = 20*log10(y1_abs)    ;min_y1 = min(y1_abs_dB)         ;subplot(3,1,3)                  ; plot(idx_f,y1_abs_dB, 'LineWidth',1,'MarkerSize',6); axis([-(fs/2) (fs/2) -60 60]);%设定坐标轴范围grid on; set(gca,'fontsize',12)                     ;title1_str = sprintf(...  'DFT Amplitude in dB scale, Kaiser window,β=%d', kaiser_beta);title(title1_str, 'fontsize',14);xlabel('Frequency/Hz');ylabel('Magnitude/dB');
  • 频谱图:
  • β=0,相当于矩形窗
  • 矩形窗
  • β=7,相当于布莱克曼窗
  • 布莱克曼窗
  • 对于固定长度为N的凯泽窗,调节β值可以得到不同的主瓣和旁瓣特征。凯泽窗可以压制旁瓣,代价是主瓣变宽。

2、ModelSim 和 Matlab


2.1 Modelsim

  • 在上次DDS作业中,是用bdf原理图的方法将各个模块连起来,这里新建一个dds_top.v文件连接各个模块,方便用modelsim仿真。

  • dds_top.v文件:

module dds_top(    CLK ,    RST ,    FWEN    ,    SWFW    ,    SINOUT);input CLK , RST;input FWEN;input  [3-1:0] SWFW;output [11 :0] SINOUT;wire [32-1:0] fqwd_W;wire [32-1:0] cntval_W;wire [10-1:0] addr_W;wire [12-1:0] romout_W;cnt_fre_words u_cfw(    .CLK    (CLK)   ,    .RST    (RST) ,    .FWEN   (FWEN),    .SWFW   (SWFW),    .FQWD   (fqwd_W),    .CNTVAL (cntval_W)    );DDS_CORE_ROM u_sinrom(    .CLK    (CLK      ),  // clock    .RA     (addr_W   ),  // read address    .RD     (SINOUT)); // read dataassign addr_W = cntval_W[31:22];endmodule
  • 一个最基本的Testbench包含三个部分,信号定义、模块接口和功能代码。自动生成testbench有两种方法,我采用第二种,自动生成的只是信号的定义,仍需要自己往testbench里添加模块接口和功能代码。

  • 接着要给给被测试设计的输入接口添加激励:CLK 和 RST;参考博客:FPGA攻略之Testbench篇

  • 最后,要把输出数据导出到文本文件中,用到的语句有:

    $fopen()
    $fdisplay()
    $fclose()

  • dds_top_tb.v文件如下:可观测信号输出波形,并将输出数据导出到文本文件SINOUT_data.txt中。

`timescale 1ns/1nsmodule dds_top_tb  ;   reg    FWEN   ;   reg    RST   ;   wire signed  [11:0]  SINOUT   ; //define signed , when exported , the txt data is signed , or default unsigned  reg    CLK   ;   reg  [2:0]  SWFW   ;   dds_top     DUT  (        .FWEN (FWEN ) ,      .RST (RST ) ,      .SINOUT (SINOUT ) ,      .CLK (CLK ) ,      .SWFW (SWFW ) ); /*----------------------------------------------  pumping signal : clock  generate the system clock : CLK  assign an initial value to CLK  value reversal by 10ns , repeat  generate a square wave signal  T = 20 ns , fclk = 50MHz----------------------------------------------*/  initial    CLK = 0;  always    #10 CLK = ~CLK ;/*----------------------------------------------  pumping signal : reset  RST : asynchronous reset----------------------------------------------*/  initial begin    RST = 0 ;       // RST , active high    #100 RST = 1 ;  // delay 100 ns    #500 RST = 0 ;  // delay 500 ns  end/*----------------------------------------------  FWEN : frequency word update enable  SWFW : switch frequency word----------------------------------------------*/  initial begin    FWEN = 1 ;    SWFW = 3'b001 ; //select 500kHz SINOUT  end/*----------------------------------------------  generate SINOUT_data.txt  export SINOUT waveform data to txt file----------------------------------------------*/  integer i ;  integer write_out_file ;  initial begin    write_out_file = $fopen("SINOUT_data.txt") ;//opend file    for(i = 0; i < 1054 ; i = i+1) begin      #20;      $fdisplay(write_out_file,"%d", SINOUT);   //write date , %d : Decimal , %h Hexadecimal      if(i == 1054)        $fclose(write_out_file);                //close file    end  endendmodule
  • modelsim仿真:

    • Lbirary 窗格,simulate 测试文件(右键–>simulate)

    • Objects 框:选中信号(Ctrl多选),右键–>Add to–>Wave–>Selected Signals

    • 运行后,将输出信号的 format 改成 Analog (automatic)

    • 输出波形如下图所示:1024个时钟周期得到10.25个输出波形

    • modelsim

    • 输出波形周期:105429×20ns10.25=2000ns

    • 输出频率:12000ns=500kHz

2.2 Matlab验证

  • 将modelsim生成的文本文件数据导入到Matlab,得到频谱图如下:

  • modelsim_tb

  • 与signaltap的数据导入MATLAB后生成的波形图进行对比,二者在频率上一致,均为 488.3 kHz。

  • 本设计中采样1024个数据,截取10.25个周期,不是周期截断,因而在最终的频谱图中将含有除原始频率成分以外的其它频率,即发生频谱泄露。改善频谱泄露的方法有:增大 FFT 变换的点数或选择合适的窗函数。

1 0
原创粉丝点击