DDS作業

實驗內容

在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 截圖

手工繪製RTL圖


Quartus掃描生成的RTL




SignalTap截圖

0.5M

1M
3M

MATLAB頻譜分析截圖

0.5M
1M

3M

Verilog代碼


module switch_freq_word(
    CLK     ,   //時鐘
    SW      ,   //選擇頻率
    FQWD    ,   //輸出頻率字,作爲下一級計數器的步進值
    EN      );  //輸出頻率字的更新使能,高電平有效
input CLK,EN;       
input [2:0] SW; 
output reg[31:0] FQWD;  
always @(posedge CLK) begin
    if (EN) begin
        case(SW)
        3'b001: FQWD <= 10;//500kHz
        3'b010: FQWD <= 20;//1MHz
        3'b100: FQWD <= 60;//3MHz
        default: FQWD <= 10;
        endcase
    end
    else begin
        FQWD <= FQWD ;
    end
end
endmodule
////////////////////////////////////////////////////
module dds_core(
  CLK   ,   // 時鐘
  IN    ,   // 步進值
  SINOUT);  // 地址
input CLK;
input  [31:0] IN;//頻率字字長32位
output reg[9:0] SINOUT;
always @ (posedge CLK) begin
  SINOUT <= IN + SINOUT;
end
endmodule  

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 1023  :RD = #1 12'b 111111110100; //    -12 0xFF4
  default : RD = #1 0;
  endcase
endmodule 

MATLAB代碼

MATLAB分析signaltap數據,進行頻譜分析
san;
data=san(:,5);%取數據中的第五列
signal=transpose(data); %矩陣轉置
fs=50E6; %採樣頻率
N=1024; %採樣點數
t=[0:1/fs:(N-1)/fs]; %採樣時刻
figure(1);plot(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');

生成波表ROM的MATLAB代碼
#include<stdio.h>
#include<math.h>
#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<DEPTH;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);    //關閉文件
    }
}




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章