EDA实验DDS设计

一、实验内容

在FPGA上设计一个DDS模块,在DE0 开发板上运行,在FPGA芯片内部合成出数字波形即可。不用输出模拟信号,本模块满足以下条件:
使用板载晶振的50MHz时钟,合成以下频率的信号
- 1 、500KHz 正弦波信号。 2、1MHz 正弦波信号。 3、3MHz 正弦波信号。
-频率字字长32位,波表ROM尺寸为 10比特地址,1024个word
- 波形格式为2补码格式,12比特量化
- 每个CLK输出一个有效样点。
- 输入信号为频率字和频率字输入使能信号
- 使用板载的拨码开关(Switch)控制生成的波形信号的不同频率。

二、设计思路RTL电路图

EDA实验DDS设计_第1张图片

设计中根据DDS输出波形频率的计算公式:
确定输出频率。
上式中为输出频率,为输入频率,即为系统基准时钟频率50MHz。m为地址加法器的宽度,K为频率控制字。设计中通过控制K的大小控制输出频率,由于K只能取整数,输出频率可能会有一定偏差。

三、Quartus扫描生成的RTL电路图

EDA实验DDS设计_第2张图片

四、实验相关程序代码

1、地址加法器模块

module addr_cnt(CLK,sel_K,CLR,En,ROMaddr);
  input CLK;
  input [1:0] sel_K;
  input En,CLR;
  output [9:0] ROMaddr;
  reg [9:0] cnt_out;
  assign ROMaddr=cnt_out;
 always @ (posedge CLK or negedge CLR)
   if(~CLR)
     cnt_out<=10'd0;
  else if(~En)
     cnt_out<=cnt_out;
   else begin

     case(sel_K)
      2'b00:cnt_out<=cnt_out+10'b00000_01010;

      2'b01:cnt_out<=cnt_out+10'b00000_10100;

    default:cnt_out<=cnt_out+10'b00001_11101;

    endcase
  end
endmodule

2、顶层设计模块

module Sine_Signal (Dout,ROMaddr,CLK,CLR,En,sel_K);       //顶层模块
  output [11:0] Dout;                                    //离散的正弦波形输出
  output [9:0] ROMaddr;                                 //ROM的地址
  input CLK    /* synthesis chip_pin="G21" */  ;         //50MHz时钟
  input CLR   /* synthesis chip_pin="H2" */ ;          //清零KEY0
  input En     /* synthesis chip_pin="J6" */;           //使能SW0
  input [1:0] sel_K  /* synthesis chip_pin="H6,H5" */; //输出频率控制字选择SW2、SW1
 addr_cnt U0_inst(                                    //实例引用地址计数器模块
         .CLK(CLK),
         .CLR(CLR),
         .En(En),
         .sel_K(sel_K),
         .ROMaddr(ROMaddr)
         );
  myROM   myROM_inst(                                   //实例引用上面定制的ROM模块
         .address(ROMaddr),                                //ROM的地址输入端
         .clken(En),
         .clock(CLK),                                   //时钟输入端
         .q(Dout)                                       //数据输出端
         );
endmodule

3、正弦波形存储模块C语言程序

#include
#include
#define PI 3.141593
#define DEPTH 1024    /* 数据深度,即存储单元的个数 */
#define WIDTH 12       /* 存储单元的宽度 */
int main(void)
{
    int n,temp;
    float v;
    FILE * fp;
          /* 建立文件名为sine1024.mif新文件,允许写入数据,
          文件名随意,但扩展名必须为.mif */
    fp = fopen("sine1024.mif","w+");
    if(NULL==fp)
        printf("Can not creat file!\r\n");
    else
    {
        printf("File created successfully!\n");
              /* 生成文件头,注意不要忘了";" */
        fprintf(fp,"DEPTH=%d;\n",DEPTH);
        fprintf(fp,"WIDTH=%d;\n",WIDTH);
        fprintf(fp,"ADDRESS_RADIX = HEX;\n");
        fprintf(fp,"DATA_RADIX = HEX;\n");
        fprintf(fp,"CONTENT\n");
        fprintf(fp,"BEGIN\n");
             /* 以十六进制输出地址和数据 */
        for(n=0;n/* 周期为1024个点的正弦波 */
            v=sin(2*PI*n/DEPTH);
            /* 将-1~1之间的正弦波的值扩展到0~4095之间 */
            temp=(int)((v+1)*4095/2);   //v+1将数值平移到0~2之间
            /* 以十六进制输出地址和数据 */
            fprintf(fp,"%x\t:\t%x;\n",n,temp);
        }
        fprintf(fp,"END;\n");
        fclose(fp);    //关闭文件
    }
}

4、matlab正弦波频谱分析程序

将signal tap采集的正弦波数据生成.txt文件保存,导入到matlab中分析频谱。
clear all; close all;
varnum;   %调用signal tap 采集的正弦波数据,列矢量
signal=transpose(VarName); %转置
fs=50E6; %采样频率
N=1024; %采样点数
t=[0:1/fs:(N-1)/fs]; %采样时刻
figure(1);plot(t,signal);
title('正弦波信号');
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');

五、实验结果

1、signal tap 数据截图

(1)f1=500kHz正弦波,地址位宽m=10,频率控制字K=10
EDA实验DDS设计_第3张图片
EDA实验DDS设计_第4张图片

(2)f2=1MHz正弦波,地址位宽m=10,频率控制字K=20
EDA实验DDS设计_第5张图片
EDA实验DDS设计_第6张图片

(2)f2=3MHz正弦波,地址位宽m=10,频率控制字K=61
EDA实验DDS设计_第7张图片
EDA实验DDS设计_第8张图片

2、matlab频谱分析

EDA实验DDS设计_第9张图片
由频谱图可以看出DDS输出的频率略小于实验要求的频率。这是由于实验中频率控制字只能取整数,略去了小数位,实际取值小于理论计算值。实验结果与理论推算结果是一致的。

你可能感兴趣的:(EDA实验DDS设计)